cnas-device/src/main/java/com/ruoyi/device/controller/DeviceExaminePlanController.java
@@ -7,6 +7,7 @@ import com.ruoyi.device.dto.DeviceExaminePlanDto; import com.ruoyi.device.dto.DeviceExamineRecordContrastDto; import com.ruoyi.device.dto.DeviceExamineRecordDto; import com.ruoyi.device.pojo.DeviceExamineAttachment; import com.ruoyi.device.pojo.DeviceExaminePlan; import com.ruoyi.device.pojo.DeviceExaminePlanDetails; import com.ruoyi.device.service.DeviceExaminePlanDetailsService; @@ -21,6 +22,7 @@ import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletResponse; import java.util.List; import java.util.Map; /** @@ -192,6 +194,44 @@ } /** * æ¥æ¾æå®è®¾å¤å¯å¤ç¨ç计åæç»ï¼åªæ¥è¯¢ï¼ä¸æ°å¢ï¼ * @return */ @Operation(summary = "æ¥æ¾å¯å¤ç¨çæ ¸æ¥è®¡åæç»") @GetMapping("/findExaminePlanDetail") public Result<DeviceExaminePlanDetails> findExaminePlanDetail(Integer deviceId, String checkTime){ return Result.success(deviceExaminePlanService.findExaminePlanDetail(deviceId, checkTime)); } /** * æ¥è¯¢æ ¸æ¥è®°å½éä»¶ */ @Operation(summary = "æ¥è¯¢æ ¸æ¥è®°å½éä»¶") @GetMapping("/selectAttachments") public Result<List<DeviceExamineAttachment>> selectAttachments(Integer planDetailsId) { return Result.success(deviceExaminePlanService.selectAttachments(planDetailsId)); } /** * ä¸ä¼ æ ¸æ¥è®°å½éä»¶ï¼ä»»ææ ¼å¼ï¼æ¯æå¤ä¸ªï¼ */ @Operation(summary = "ä¸ä¼ æ ¸æ¥è®°å½éä»¶") @PostMapping("/uploadAttachment") public Result uploadAttachment(@RequestParam("planDetailsId") Integer planDetailsId, @RequestParam("file") MultipartFile file) { return Result.success(deviceExaminePlanService.uploadAttachment(planDetailsId, file)); } /** * å 餿 ¸æ¥è®°å½éä»¶ */ @Operation(summary = "å 餿 ¸æ¥è®°å½éä»¶") @DeleteMapping("/deleteAttachment") public Result deleteAttachment(Long id) { return Result.success(deviceExaminePlanService.deleteAttachment(id)); } /** * 导åºè®¾å¤æ ¸æ¥è®¡å * @param planId è®¾å¤æ ¸æ¥è®¡åid * @return cnas-device/src/main/java/com/ruoyi/device/dto/DeviceExaminePlanDetailsDto.java
@@ -23,4 +23,7 @@ @Schema(description = "å°ç¹æ 红, 1:éæ ¸æ¥") private Integer redFlag; @Schema(description = "éä»¶æ°é") private Integer attachmentCount; } cnas-device/src/main/java/com/ruoyi/device/dto/DeviceRecordDto.java
@@ -9,6 +9,10 @@ @Schema(description = "设å¤åç§°") private String deviceName; @Schema(description = "设å¤åå·") private String specificationModel; @Schema(description = "设å¤ç¼å·") private String managementNumber; @Schema(description = "å ³èåå§è®°å½ç¼å·") private String orderCode; } cnas-device/src/main/java/com/ruoyi/device/excel/DeviceRecordExportWord.java
ÎļþÒÑɾ³ý cnas-device/src/main/java/com/ruoyi/device/mapper/DeviceExamineAttachmentMapper.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,9 @@ package com.ruoyi.device.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.device.pojo.DeviceExamineAttachment; import org.apache.ibatis.annotations.Mapper; @Mapper public interface DeviceExamineAttachmentMapper extends BaseMapper<DeviceExamineAttachment> { } cnas-device/src/main/java/com/ruoyi/device/mapper/DeviceRecordMapper.java
@@ -36,5 +36,5 @@ * @param exportDate * @return */ List<DeviceRecord> selectExportList(@Param("deviceId") Integer deviceId, @Param("sampleCode") String sampleCode, @Param("managementNumber") String managementNumber, @Param("exportDate") String exportDate); List<DeviceRecordDto> selectExportList(@Param("deviceId") Integer deviceId, @Param("sampleCode") String sampleCode, @Param("managementNumber") String managementNumber, @Param("exportDate") String exportDate); } cnas-device/src/main/java/com/ruoyi/device/pojo/DeviceExamineAttachment.java
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,28 @@ package com.ruoyi.device.pojo; import com.baomidou.mybatisplus.annotation.*; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.time.LocalDateTime; @Data @TableName("device_examine_attachment") public class DeviceExamineAttachment { @TableId(type = IdType.AUTO) private Long id; private Integer planDetailsId; private String fileName; private String fileUrl; private Integer sort; @TableField(fill = FieldFill.INSERT) private Integer createUser; @TableField(fill = FieldFill.INSERT_UPDATE) private Integer updateUser; @TableField(fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updateTime; } cnas-device/src/main/java/com/ruoyi/device/pojo/DeviceExaminePlanDetails.java
@@ -36,6 +36,9 @@ @Schema(description = "计ååç§°") private String deviceName; @Schema(description = "设å¤åå·") private String deviceModel; @Schema(description = "æ ¸æ¥æ¶é´") private String checkTime; @@ -54,6 +57,18 @@ @Schema(description = "æ ¸æ¥è´£ä»»äºº") private String checkChargerUser; @Schema(description = "ç¯å¢æ¸©æ¹¿åº¦") private String environment; @Schema(description = "æ ¸æ¥ä¾æ®") private String checkBasis; @Schema(description = "å¤è§æ åµ") private String appearanceStatus; @Schema(description = "è¿è¡æ¯å¦æ£å¸¸") private String runningStatus; @Schema(description = "夿³¨") private String remark; cnas-device/src/main/java/com/ruoyi/device/pojo/DeviceRecord.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; @@ -62,8 +63,10 @@ private String remark; @Schema(description = "使ç¨å¼å§æ¥æ") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime useStartDate; @Schema(description = "使ç¨ç»ææ¥æ") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime useEndDate; } cnas-device/src/main/java/com/ruoyi/device/service/DeviceExaminePlanService.java
@@ -6,11 +6,13 @@ import com.ruoyi.device.dto.DeviceExaminePlanDetailsDto; import com.ruoyi.device.dto.DeviceExaminePlanDto; import com.ruoyi.device.pojo.Device; import com.ruoyi.device.pojo.DeviceExamineAttachment; import com.ruoyi.device.pojo.DeviceExaminePlan; import com.ruoyi.device.pojo.DeviceExaminePlanDetails; import org.springframework.web.multipart.MultipartFile; import jakarta.servlet.http.HttpServletResponse; import java.util.List; /** * <p> @@ -116,6 +118,14 @@ DeviceExaminePlanDetails resolveExaminePlanDetail(Integer deviceId, String checkTime); /** * æ¥æ¾æå®è®¾å¤å¯å¤ç¨çæ ¸æ¥è®°å½è®¡åæç»ï¼åªæ¥è¯¢ï¼ä¸æ°å¢è®¡åææç»ï¼ * @param deviceId 设å¤id * @param checkTime æ ¸æ¥æä»½ï¼yyyy-MMï¼ * @return å¯å¤ç¨ç计åæç»ï¼æ²¡ææ¶è¿å null */ DeviceExaminePlanDetails findExaminePlanDetail(Integer deviceId, String checkTime); /** * ä¿®æ¹è®¡åæç»ï¼æ ¸æ¥æä»½è·¨å¹´æ¶å½å°å¯¹åºå¹´ä»½ç计åï¼ * @param detail 计åæç» * @return æ¯å¦ä¿®æ¹æå @@ -128,4 +138,26 @@ * @return æ¯å¦å 餿å */ boolean removeExaminePlanDetail(Integer planDetailsId); /** * æ¥è¯¢æ ¸æ¥è®°å½çéä»¶å表 * @param planDetailsId 计åæç»id * @return éä»¶å表 */ List<DeviceExamineAttachment> selectAttachments(Integer planDetailsId); /** * ä¸ä¼ æ ¸æ¥è®°å½çéä»¶ï¼æ¯æä»»ææ ¼å¼ï¼å¯å¤ä¸ªï¼ * @param planDetailsId 计åæç»id * @param file æä»¶ * @return éä»¶ä¿¡æ¯ */ DeviceExamineAttachment uploadAttachment(Integer planDetailsId, MultipartFile file); /** * å 餿 ¸æ¥è®°å½çéä»¶ * @param id éä»¶id * @return æ¯å¦å 餿å */ boolean deleteAttachment(Long id); } cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceExaminePlanServiceImpl.java
@@ -20,12 +20,14 @@ import com.ruoyi.device.dto.DeviceExaminePlanDetailsDto; import com.ruoyi.device.dto.DeviceExaminePlanDto; import com.ruoyi.device.excel.upload.DeviceExaminePlanUpload; import com.ruoyi.device.mapper.DeviceExamineAttachmentMapper; import com.ruoyi.device.mapper.DeviceExaminePlanDetailsMapper; import com.ruoyi.device.mapper.DeviceExaminePlanMapper; import com.ruoyi.device.mapper.DeviceExamineRecordContrastMapper; import com.ruoyi.device.mapper.DeviceExamineRecordMapper; import com.ruoyi.device.mapper.DeviceMapper; import com.ruoyi.device.pojo.Device; import com.ruoyi.device.pojo.DeviceExamineAttachment; import com.ruoyi.device.pojo.DeviceExaminePlan; import com.ruoyi.device.pojo.DeviceExaminePlanDetails; import com.ruoyi.device.pojo.DeviceExamineRecord; @@ -38,6 +40,7 @@ import com.ruoyi.system.mapper.UserMapper; import com.ruoyi.system.service.InformationNotificationService; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -45,6 +48,7 @@ import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -86,6 +90,14 @@ private DeviceExamineRecordMapper deviceExamineRecordMapper; @Resource private DeviceExamineRecordContrastMapper deviceExamineRecordContrastMapper; @Resource private DeviceExamineAttachmentMapper deviceExamineAttachmentMapper; @Value("${file.path}") private String filePath; @Value("${wordUrl}") private String wordUrl; /** * æ°å¢è®¾å¤æ ¸æ¥è®¡å @@ -415,12 +427,8 @@ if (device == null) { return; } // æåæ ¸æ¥æ¶è®¡åæä»½å¯è½è¿æ²¡å°ï¼åå®é 宿å½å¤©ï¼å¦åææ¬è½®è®¡åæ ¸æ¥æä»½ LocalDate checkDate = parseCheckDate(detail.getCheckTime()); if (checkDate.isAfter(LocalDate.now())) { checkDate = LocalDate.now(); } LocalDateTime checkDateTime = checkDate.atStartOfDay(); // å®¡æ ¸éè¿å½å¤©å³è§ä¸ºå®é æ ¸æ¥å®ææ¶é´ LocalDateTime checkDateTime = LocalDate.now().atStartOfDay(); // åªå 许ååæ»å¨ï¼é¿å éå¤å¤æ ¸æ§è®°å½æ¶ææ¥ææ¹åå» if (device.getLastExamineDate() != null && !checkDateTime.isAfter(device.getLastExamineDate())) { return; @@ -513,26 +521,22 @@ } /** * 计åæç»çæ ¸æ¥æ¶é´å¯è½æ¯ yyyy-MM æ yyyy-MM-ddï¼ç»ä¸åæä»½é¦æ¥ */ private LocalDate parseCheckDate(String checkTime) { if (StringUtils.isNotBlank(checkTime)) { String normalized = checkTime.trim().replace('.', '-').replace('/', '-'); if (normalized.length() >= 7) { try { return YearMonth.parse(normalized.substring(0, 7)).atDay(1); } catch (Exception ignored) { } } } return LocalDate.now(); } /** * 为æå®è®¾å¤æ¾ä¸æ¡å¯å½å ¥æ ¸æ¥è®°å½ç计åæç»ï¼æ²¡æå¯ç¨æç»æ¶å¨å½åå¹´åº¦è®¡åæ°å¢æ¬è½®æç» */ @Override public DeviceExaminePlanDetails resolveExaminePlanDetail(Integer deviceId, String checkTime) { return findExaminePlanDetail(deviceId, checkTime, true); } /** * æ¥æ¾æå®è®¾å¤å¯å¤ç¨ç计åæç»ï¼åªæ¥è¯¢ï¼ä¸æ°å¢è®¡åææç» */ @Override public DeviceExaminePlanDetails findExaminePlanDetail(Integer deviceId, String checkTime) { return findExaminePlanDetail(deviceId, checkTime, false); } private DeviceExaminePlanDetails findExaminePlanDetail(Integer deviceId, String checkTime, boolean createIfAbsent) { if (deviceId == null) { throw new ErrorException("è¯·éæ©æ ¸æ¥è®¾å¤"); } @@ -541,7 +545,16 @@ throw new ErrorException("æ ¸æ¥è®¾å¤ä¸åå¨"); } String checkMonth = normalizeCheckMonth(checkTime); DeviceExaminePlan plan = getOrCreatePlanEntity(checkMonth.substring(0, 4)); String planYear = checkMonth.substring(0, 4); DeviceExaminePlan plan; if (createIfAbsent) { plan = getOrCreatePlanEntity(planYear); } else { plan = baseMapper.selectOne(Wrappers.<DeviceExaminePlan>lambdaQuery() .eq(DeviceExaminePlan::getPlanYear, planYear) .orderByDesc(DeviceExaminePlan::getPlanId) .last("limit 1")); } List<DeviceExaminePlanDetails> details = deviceExaminePlanDetailsMapper.selectList( Wrappers.<DeviceExaminePlanDetails>lambdaQuery() .eq(DeviceExaminePlanDetails::getDeviceId, deviceId) @@ -555,7 +568,7 @@ if (recordCount != null && recordCount > 0) { continue; } if (detail.getPlanId() != null && detail.getPlanId().equals(plan.getPlanId())) { if (plan != null && detail.getPlanId() != null && detail.getPlanId().equals(plan.getPlanId())) { return detail; } long distance = monthDistance(detail.getCheckTime(), checkMonth); @@ -568,6 +581,9 @@ if (nearest != null) { return nearest; } if (!createIfAbsent) { return null; } DeviceExaminePlanDetails detail = new DeviceExaminePlanDetails(); detail.setPlanId(plan.getPlanId()); detail.setDeviceId(device.getId()); @@ -577,7 +593,8 @@ } detail.setDeviceName(deviceName); detail.setDeviceNumber(device.getManagementNumber()); detail.setCheckTime(checkMonth); String detailCheckTime = normalizeCheckDate(checkTime); detail.setCheckTime(StringUtils.isBlank(detailCheckTime) ? checkMonth : detailCheckTime); deviceExaminePlanDetailsMapper.insert(detail); return detail; } @@ -596,6 +613,23 @@ } } return LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")); } /** * è§èæ ¸æ¥æ¥æï¼å¸¦å ·ä½æ¥æçä¿çå°æ¥ï¼åªå¡«æä»½çè§è为 yyyy-MM */ private String normalizeCheckDate(String checkTime) { if (StringUtils.isBlank(checkTime)) { return null; } String normalized = checkTime.trim().replace('.', '-').replace('/', '-'); if (normalized.length() >= 10) { try { return LocalDate.parse(normalized.substring(0, 10)).toString(); } catch (Exception ignored) { } } return normalizeCheckMonth(normalized); } /** @@ -620,9 +654,9 @@ throw new ErrorException("缺å°è®¾å¤æ ¸æ¥è®¡åæç»id"); } if (StringUtils.isNotBlank(detail.getCheckTime())) { String checkMonth = normalizeCheckMonth(detail.getCheckTime()); detail.setCheckTime(checkMonth); DeviceExaminePlan plan = getOrCreatePlanEntity(checkMonth.substring(0, 4)); String checkTime = normalizeCheckDate(detail.getCheckTime()); detail.setCheckTime(checkTime); DeviceExaminePlan plan = getOrCreatePlanEntity(checkTime.substring(0, 4)); detail.setPlanId(plan.getPlanId()); } return deviceExaminePlanDetailsMapper.updateById(detail) > 0; @@ -636,6 +670,10 @@ if (planDetailsId == null) { throw new ErrorException("缺å°è®¾å¤æ ¸æ¥è®¡åæç»id"); } DeviceExaminePlanDetails detail = deviceExaminePlanDetailsMapper.selectById(planDetailsId); if (detail == null) { return false; } Long recordCount = deviceExamineRecordMapper.selectCount(Wrappers.<DeviceExamineRecord>lambdaQuery() .eq(DeviceExamineRecord::getPlanDetailsId, planDetailsId)); Long contrastCount = deviceExamineRecordContrastMapper.selectCount(Wrappers.<DeviceExamineRecordContrast>lambdaQuery() @@ -643,6 +681,162 @@ if ((recordCount != null && recordCount > 0) || (contrastCount != null && contrastCount > 0)) { throw new ErrorException("该计åå·²å卿 ¸æ¥è®°å½ï¼ä¸ºä¿çåå²è®°å½ä¸å 许å é¤"); } return deviceExaminePlanDetailsService.removeById(planDetailsId); boolean removed = deviceExaminePlanDetailsService.removeById(planDetailsId); if (removed && detail.getDeviceId() != null) { rollbackDeviceExamineDate(detail); } return removed; } /** * å 餿ªå®¡æ ¸ç计ååï¼æè®¾å¤æ¡£æ¡æ¢å¤å°æè¿ä¸æ¡å®¡æ ¸éè¿çè®°å½ï¼ * 没æå·²å®æè®°å½æ¶ï¼ææ¸ 空档æ¡çæ ¸æ¥æ¥æå卿 */ private void rollbackDeviceExamineDate(DeviceExaminePlanDetails removedDetail) { Device device = deviceMapper.selectById(removedDetail.getDeviceId()); if (device == null) { return; } Long remainCount = deviceExaminePlanDetailsMapper.selectCount(Wrappers.<DeviceExaminePlanDetails>lambdaQuery() .eq(DeviceExaminePlanDetails::getDeviceId, removedDetail.getDeviceId())); boolean isCurrentRound = sameExamineMonth(removedDetail.getCheckTime(), device.getNextExamineDate()); // å é¤ç䏿¯æ¡£æ¡å½åç»è®°çé£ä¸è½®ï¼ä¸è®¾å¤è¿æå ¶ä»è®¡åæ¶ï¼ä¸å¨æ¡£æ¡ if (!isCurrentRound && remainCount != null && remainCount > 0) { return; } LocalDate lastDone = null; List<DeviceExaminePlanDetails> details = deviceExaminePlanDetailsMapper.selectList( Wrappers.<DeviceExaminePlanDetails>lambdaQuery() .eq(DeviceExaminePlanDetails::getDeviceId, removedDetail.getDeviceId())); for (DeviceExaminePlanDetails item : details) { if (!hasPassedExamineRecord(item.getPlanDetailsId())) { continue; } LocalDate date = parseCheckMonth(item.getCheckTime()); if (date != null && (lastDone == null || date.isAfter(lastDone))) { lastDone = date; } } if (lastDone == null) { deviceMapper.update(null, Wrappers.<Device>lambdaUpdate() .eq(Device::getId, removedDetail.getDeviceId()) .set(Device::getLastExamineDate, null) .set(Device::getNextExamineDate, null) .set(Device::getExamineCycle, null)); return; } LocalDateTime last = lastDone.atStartOfDay(); LocalDateTime next = null; if (StringUtils.isNotBlank(device.getExamineCycle())) { try { next = last.plusMonths(Long.parseLong(device.getExamineCycle().trim())); } catch (NumberFormatException ignored) { } } deviceMapper.update(null, Wrappers.<Device>lambdaUpdate() .eq(Device::getId, removedDetail.getDeviceId()) .set(Device::getLastExamineDate, last) .set(Device::getNextExamineDate, next)); } /** * æç»ä¸æ¯å¦åå¨å®¡æ ¸éè¿çæ ¸æ¥è®°å½ææ¯å¯¹è®°å½ */ private boolean hasPassedExamineRecord(Integer planDetailsId) { Long recordCount = deviceExamineRecordMapper.selectCount(Wrappers.<DeviceExamineRecord>lambdaQuery() .eq(DeviceExamineRecord::getPlanDetailsId, planDetailsId) .eq(DeviceExamineRecord::getReviewStatus, 1)); if (recordCount != null && recordCount > 0) { return true; } Long contrastCount = deviceExamineRecordContrastMapper.selectCount(Wrappers.<DeviceExamineRecordContrast>lambdaQuery() .eq(DeviceExamineRecordContrast::getPlanDetailsId, planDetailsId) .eq(DeviceExamineRecordContrast::getReviewStatus, 1)); return contrastCount != null && contrastCount > 0; } /** * 计åæç»çæ ¸æ¥æä»½æ¯å¦å°±æ¯æ¡£æ¡ä¸æ¬¡æ ¸æ¥æ¥ææå¨æä»½ */ private boolean sameExamineMonth(String checkTime, LocalDateTime nextExamineDate) { if (StringUtils.isBlank(checkTime) || nextExamineDate == null) { return false; } String normalized = checkTime.trim().replace('.', '-').replace('/', '-'); return normalized.length() >= 7 && normalized.substring(0, 7).equals(nextExamineDate.format(DateTimeFormatter.ofPattern("yyyy-MM"))); } /** * è§£ææç»æ ¸æ¥æä»½ä¸ºå½æé¦æ¥ï¼æ ¼å¼ä¸åæ³æ¶è¿å null */ private LocalDate parseCheckMonth(String checkTime) { if (StringUtils.isNotBlank(checkTime)) { String normalized = checkTime.trim().replace('.', '-').replace('/', '-'); if (normalized.length() >= 7) { try { return YearMonth.parse(normalized.substring(0, 7)).atDay(1); } catch (Exception ignored) { } } } return null; } @Override public List<DeviceExamineAttachment> selectAttachments(Integer planDetailsId) { if (planDetailsId == null) { return new ArrayList<>(); } return deviceExamineAttachmentMapper.selectList(Wrappers.<DeviceExamineAttachment>lambdaQuery() .eq(DeviceExamineAttachment::getPlanDetailsId, planDetailsId) .orderByAsc(DeviceExamineAttachment::getSort, DeviceExamineAttachment::getId)); } @Override public DeviceExamineAttachment uploadAttachment(Integer planDetailsId, MultipartFile file) { if (planDetailsId == null) { throw new ErrorException("ç¼ºå°æ ¸æ¥è®¡åæç»id"); } if (deviceExaminePlanDetailsMapper.selectById(planDetailsId) == null) { throw new ErrorException("æ ¸æ¥è®¡åæç»ä¸åå¨"); } if (file == null || file.isEmpty()) { throw new ErrorException("éä»¶ä¸è½ä¸ºç©º"); } // ç³»ç»å ¨å±ä¸ä¼ ä¸é为200MBï¼è¿éæåç»åºå好æç¤º if (file.getSize() > 200L * 1024 * 1024) { throw new ErrorException("éä»¶ä¸è½è¶ è¿200MB"); } String originalName = file.getOriginalFilename(); if (originalName == null || originalName.trim().isEmpty()) { originalName = "æªå½åæä»¶"; } // ä¸ªå«æµè§å¨å¯è½å¸¦ä¸è·¯å¾åç¼ï¼åªä¿çæä»¶åæ¬èº« originalName = originalName.replaceAll(".*[/\\\\]", ""); try { // å¾çæ¾å¾çç®å½ï¼/img éæè·¯å¾ï¼ï¼å ¶ä½ä»»ææ ¼å¼æ¾ word ç®å½ï¼/word éæè·¯å¾ï¼ boolean image = originalName.matches("(?i).+\\.(jpg|jpeg|png|gif)$"); File directory = new File(image ? filePath : wordUrl); if (!directory.exists()) { directory.mkdirs(); } String fileUrl = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyMMddHHmmssSSS")) + "-" + originalName; file.transferTo(new File(directory, fileUrl)); DeviceExamineAttachment attachment = new DeviceExamineAttachment(); attachment.setPlanDetailsId(planDetailsId); attachment.setFileName(originalName); attachment.setFileUrl(fileUrl); attachment.setSort(selectAttachments(planDetailsId).size()); deviceExamineAttachmentMapper.insert(attachment); return attachment; } catch (IOException e) { throw new ErrorException("éä»¶ä¸ä¼ 失败"); } } @Override public boolean deleteAttachment(Long id) { return deviceExamineAttachmentMapper.deleteById(id) > 0; } } cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceExamineRecordServiceImpl.java
@@ -37,6 +37,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.URLEncoder; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.List; @@ -177,20 +179,59 @@ if (dto.getPlanDetailsId() == null) { throw new ErrorException("缺å°è®¡å详ç»ä¿¡æ¯id"); } DeviceExaminePlanDetails planDetails = deviceExaminePlanDetailsMapper.selectById(dto.getPlanDetailsId()); if (planDetails == null) { throw new ErrorException("æ ¸æ¥è®¡åæç»ä¸åå¨"); } if (planDetails.getCheckChargerUserId() == null && StringUtils.isBlank(planDetails.getCheckChargerUser())) { throw new ErrorException("请å å¨ç¼è¾ä¸å¡«åæ ¸æ¥è´è´£äºº"); } 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, dto.getReviewStatus()) .set(DeviceExamineRecord::getReviewStatus, reviewStatus) .set(DeviceExamineRecord::getReviewRemark, dto.getReviewRemark()); // 为0æ¸ é¤å®¡æ ¸äºº if (dto.getReviewStatus().equals(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()); } this.update(wrapper); 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 (dto.getReviewStatus() != null && dto.getReviewStatus() == 1) { if (reviewStatus != null && reviewStatus == 1) { // æåå®¡æ ¸æ¶ææ¬è½®è®¡åå½å°å®é å®¡æ ¸æä»½ï¼ä¾¿äºç³»ç»ç»è®°ä¸ä¸è½®ï¼æå¨å½å ¥å°æ¥çæ¥æä¿æåæ · String currentCheckTime = planDetails.getCheckTime(); boolean hasCheckDate = currentCheckTime != null && currentCheckTime.trim().length() >= 10; if (!hasCheckDate) { DeviceExaminePlanDetails updateDetail = new DeviceExaminePlanDetails(); updateDetail.setPlanDetailsId(dto.getPlanDetailsId()); updateDetail.setCheckTime(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"))); deviceExaminePlanService.updateExaminePlanDetail(updateDetail); } deviceExaminePlanService.updateDeviceExamineDate(dto.getPlanDetailsId()); } return true; cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceRecordServiceImpl.java
@@ -3,30 +3,56 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.config.Configure; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.device.dto.DeviceRecordDto; import com.ruoyi.device.excel.DeviceRecordExportWord; import com.ruoyi.device.mapper.DeviceMapper; import com.ruoyi.device.mapper.DeviceRecordMapper; import com.ruoyi.device.pojo.Device; import com.ruoyi.device.pojo.DeviceRecord; import com.ruoyi.device.service.DeviceRecordService; import com.ruoyi.inspect.util.HackLoopTableRenderPolicy; import com.ruoyi.system.domain.vo.SysRoleVo; import com.ruoyi.system.mapper.SysRoleMenuMapper; import org.springframework.beans.BeanUtils; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.TableRowAlign; import org.apache.poi.xwpf.usermodel.UnderlinePatterns; 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.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageMar; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPageSz; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblCellMar; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblLayoutType; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STPageOrientation; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblLayoutType; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth; import org.springframework.stereotype.Service; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import java.io.InputStream; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -40,8 +66,18 @@ */ @Service public class DeviceRecordServiceImpl extends ServiceImpl<DeviceRecordMapper, DeviceRecord> implements DeviceRecordService { @Resource private DeviceMapper deviceMapper; private static final String FORM_TITLE = "仪å¨è®¾å¤è¿è¡è®°å½"; 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_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 DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm"); @Resource private SysRoleMenuMapper sysRoleMenuMapper; @@ -62,87 +98,403 @@ return baseMapper.deviceRecordPage(deviceId, page, sampleCode, managementNumber, testUserId); } @Override public void exportUseRecord(Integer deviceId, String sampleCode, String managementNumber, String exportDate, HttpServletResponse response) { // æ¥è¯¢cnas设å¤ä½¿ç¨è®°å½(æå½åç鿡件, æ¡ä»¶ä¸ºç©ºæ¶å¯¼åºå ¨é¨) List<DeviceRecord> deviceList = baseMapper.selectExportList(deviceId, sampleCode, managementNumber, exportDate); // 设å¤ä¿¡æ¯(æªéä¸å ·ä½è®¾å¤æ¶å¯¼åºå ¨é¨è®¾å¤çè®°å½, 设å¤ä¿¡æ¯ç空) Device device = deviceId == null ? null : deviceMapper.selectById(deviceId); // æ¥è¯¢è®¾å¤å±äºåªä¸ªå®éªå®¤ String laboratoryName = "è£ å¤çº¿ç¼å®éªå®¤"; // è¦æ å°å°wordæ°æ® List<DeviceRecordExportWord> deviceExportList = new ArrayList<>(); // deviceExportList èµå¼ for (DeviceRecord deviceRecord : deviceList) { // å¤çè®¾å¤ å¼å§ä½¿ç¨æ¶é´ å ç»ææ¶é´ String startTime = ""; String endTime = ""; String operationDate = ""; DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); if (deviceRecord.getUseStartDate() != null) { startTime = deviceRecord.getUseStartDate().format(formatter); endTime = deviceRecord.getUseEndDate().format(formatter); String[] startTimeSplit = startTime.split(" "); String[] endTimeSplit = endTime.split(" "); if (startTimeSplit[0].equals(endTimeSplit[0])) { startTime = startTimeSplit[1]; endTime = endTimeSplit[1]; } else { endTime = endTimeSplit[0] + '\n' + endTimeSplit[1]; startTime = startTimeSplit[0] + '\n' + startTimeSplit[1]; } DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy.M.d"); operationDate = deviceRecord.getUseStartDate().format(formatter2); } // å¤ç使ç¨åå使ç¨å String useBeforeString = deviceRecord.getUseBefore() == 0? "å¼å¸¸" : "è¯å¥½"; String useAfterString = deviceRecord.getUseAfter() == 0 ? "å¼å¸¸" : "è¯å¥½"; DeviceRecordExportWord deviceRecordExportWord = new DeviceRecordExportWord(); // è¿è¡èµå¼ BeanUtils.copyProperties(deviceRecord, deviceRecordExportWord); deviceRecordExportWord.setUseBeforeString(useBeforeString); // 使ç¨å deviceRecordExportWord.setUseAfterString(useAfterString); // 使ç¨å deviceRecordExportWord.setOperationDate(operationDate); // è®¾å¤æä½æ¥æ deviceRecordExportWord.setUseStartDateString(startTime); // å¼å§æ¶é´ deviceRecordExportWord.setUseEndDateString(endTime); // ç»ææ¶é´ deviceExportList.add(deviceRecordExportWord); List<DeviceRecordDto> records = baseMapper.selectExportList(deviceId, sampleCode, managementNumber, exportDate); if (records == null || records.isEmpty()) { throw new ServiceException(exportDate == null || exportDate.isEmpty() ? "没æå¯å¯¼åºç使ç¨è®°å½ï¼æ æ³å¯¼åº" : exportDate + " 没æå¯å¯¼åºç使ç¨è®°å½ï¼æ æ³å¯¼åº"); } // è·åè·¯å¾ InputStream inputStream = this.getClass().getResourceAsStream("/static/word/use-record.docx"); Configure configure = Configure.builder() .bind("useRecord", new HackLoopTableRenderPolicy()) .build(); String deviceName = device == null ? "" : device.getDeviceName(); String deviceManagementNumber = device == null ? "" : device.getManagementNumber(); XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render( new HashMap<String, Object>() {{ put("useRecord", deviceExportList); put("deviceName", deviceName); put("managementNumber", deviceManagementNumber); put("laboratory", laboratoryName); }}); // åå°è®¾å¤æ²¿ç¨æªå¾è¡¨å¤´; å¤å°è®¾å¤åå¹¶å°ä¸å¼ 表, æ¯è¡å¸¦è®¾å¤ä¿¡æ¯ Map<Integer, List<DeviceRecordDto>> deviceRecords = new LinkedHashMap<>(); for (DeviceRecordDto record : records) { deviceRecords.computeIfAbsent(record.getDeviceId(), key -> new ArrayList<>()).add(record); } try { response.setContentType("application/msword"); String fileName = URLEncoder.encode( "仪å¨ä½¿ç¨è®°å½è¡¨", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx"); OutputStream os = response.getOutputStream(); template.write(os); os.flush(); os.close(); inputStream.close(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("导åºå¤±è´¥"); 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); } response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); String fileName = URLEncoder.encode(FORM_TITLE, StandardCharsets.UTF_8).replace("+", "%20"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".docx"); try (OutputStream os = response.getOutputStream()) { document.write(os); os.flush(); } } catch (IOException e) { throw new RuntimeException("导åºå¤±è´¥", e); } } private void setupPage(XWPFDocument document) { CTBody body = document.getDocument().getBody(); CTSectPr sectPr = body.isSetSectPr() ? body.getSectPr() : body.addNewSectPr(); CTPageSz pageSz = sectPr.isSetPgSz() ? sectPr.getPgSz() : sectPr.addNewPgSz(); pageSz.setW(BigInteger.valueOf(16838)); pageSz.setH(BigInteger.valueOf(11906)); pageSz.setOrient(STPageOrientation.LANDSCAPE); CTPageMar pageMar = sectPr.isSetPgMar() ? sectPr.getPgMar() : sectPr.addNewPgMar(); pageMar.setTop(BigInteger.valueOf(680)); pageMar.setBottom(BigInteger.valueOf(680)); pageMar.setLeft(BigInteger.valueOf(794)); pageMar.setRight(BigInteger.valueOf(794)); pageMar.setHeader(BigInteger.valueOf(851)); pageMar.setFooter(BigInteger.valueOf(992)); pageMar.setGutter(BigInteger.ZERO); } private void renderForm(XWPFDocument document, DeviceRecordDto device, 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); renderDeviceInfo(document, device); document.createParagraph(); XWPFTable table = document.createTable(2 + records.size(), COLUMN_WIDTHS.length); configureTable(table, 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 < COLUMN_WIDTHS.length; j++) { setCellWidth(row.getCell(j), COLUMN_WIDTHS[j]); } setRowProperties(row, i < 2); } XWPFTableRow firstHeader = table.getRow(0); for (int i = 0; i < HEADER_FIRST_ROW.length; i++) { setCellText(firstHeader.getCell(i), HEADER_FIRST_ROW[i]); } XWPFTableRow secondHeader = table.getRow(1); for (int i = 0; i < HEADER_SECOND_ROW.length; i++) { setCellText(secondHeader.getCell(i), HEADER_SECOND_ROW[i]); } mergeHorizontal(firstHeader, COLUMN_WIDTHS, 6, 2); mergeHorizontal(firstHeader, COLUMN_WIDTHS, 4, 2); mergeHorizontal(firstHeader, COLUMN_WIDTHS, 2, 2); mergeVertical(firstHeader.getCell(0), secondHeader.getCell(0)); mergeVertical(firstHeader.getCell(1), secondHeader.getCell(1)); mergeVertical(firstHeader.getCell(5), secondHeader.getCell(8)); mergeVertical(firstHeader.getCell(6), secondHeader.getCell(9)); for (int i = 0; i < records.size(); i++) { XWPFTableRow row = table.getRow(2 + i); String[] values = buildRowValues(records.get(i)); for (int j = 0; j < values.length; j++) { 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]); } } } private XWPFParagraph addParagraph(XWPFDocument document, String text, double fontSize, boolean bold, ParagraphAlignment alignment) { XWPFParagraph paragraph = document.createParagraph(); paragraph.setAlignment(alignment); addRun(paragraph, text, fontSize, bold); return paragraph; } private void addDeviceField(XWPFParagraph paragraph, String label, String value) { addRun(paragraph, label, 10.5, false); XWPFRun valueRun = addRun(paragraph, padUnderline(value), 10.5, false); valueRun.setUnderline(UnderlinePatterns.SINGLE); } private String padUnderline(String value) { String content = value == null ? "" : value.trim(); int width = 0; for (int i = 0; i < content.length(); i++) { width += content.charAt(i) >= 0x2E80 ? 2 : 1; } StringBuilder text = new StringBuilder(content); for (int i = width; i < 20; i++) { text.append(' '); } return text.toString(); } private XWPFRun addRun(XWPFParagraph paragraph, String text, double fontSize, boolean bold) { XWPFRun run = paragraph.createRun(); run.setFontFamily(FONT_NAME); run.setFontFamily(FONT_NAME, XWPFRun.FontCharRange.eastAsia); run.setFontSize(fontSize); run.setBold(bold); run.setText(text); return run; } private void renderDeviceInfo(XWPFDocument document, DeviceRecordDto device) { String[] labels = {"设å¤åç§°ï¼", "设å¤åå·ï¼", "设å¤ç¼å·ï¼"}; String[] values = { device == null ? "" : device.getDeviceName(), device == null ? "" : device.getSpecificationModel(), device == null ? "" : device.getManagementNumber() }; int[] widths = {5052, 5053, 5053}; XWPFTable table = document.createTable(1, labels.length); CTTbl ctTbl = table.getCTTbl(); CTTblPr tblPr = ctTbl.getTblPr() != null ? ctTbl.getTblPr() : ctTbl.addNewTblPr(); CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); tblWidth.setType(STTblWidth.DXA); tblWidth.setW(BigInteger.valueOf(totalWidth(COLUMN_WIDTHS))); CTTblLayoutType layoutType = tblPr.isSetTblLayout() ? tblPr.getTblLayout() : tblPr.addNewTblLayout(); layoutType.setType(STTblLayoutType.FIXED); setNoBorders(tblPr); CTTblCellMar cellMar = tblPr.isSetTblCellMar() ? tblPr.getTblCellMar() : tblPr.addNewTblCellMar(); setZeroWidth(cellMar.isSetLeft() ? cellMar.getLeft() : cellMar.addNewLeft()); setZeroWidth(cellMar.isSetRight() ? cellMar.getRight() : cellMar.addNewRight()); CTTblGrid grid = ctTbl.getTblGrid() != null ? ctTbl.getTblGrid() : ctTbl.addNewTblGrid(); while (grid.sizeOfGridColArray() > 0) { grid.removeGridCol(0); } for (int width : widths) { grid.addNewGridCol().setW(BigInteger.valueOf(width)); } XWPFTableRow row = table.getRow(0); for (int i = 0; i < labels.length; i++) { XWPFTableCell cell = row.getCell(i); setCellWidth(cell, widths[i]); cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); XWPFParagraph paragraph = cell.getParagraphs().isEmpty() ? cell.addParagraph() : cell.getParagraphs().get(0); paragraph.setAlignment(ParagraphAlignment.LEFT); paragraph.setSpacingBefore(0); paragraph.setSpacingAfter(0); addDeviceField(paragraph, labels[i], values[i]); } } private void setNoBorders(CTTblPr tblPr) { CTTblBorders borders = tblPr.isSetTblBorders() ? tblPr.getTblBorders() : tblPr.addNewTblBorders(); setNoBorder(borders.isSetTop() ? borders.getTop() : borders.addNewTop()); setNoBorder(borders.isSetLeft() ? borders.getLeft() : borders.addNewLeft()); setNoBorder(borders.isSetBottom() ? borders.getBottom() : borders.addNewBottom()); setNoBorder(borders.isSetRight() ? borders.getRight() : borders.addNewRight()); setNoBorder(borders.isSetInsideH() ? borders.getInsideH() : borders.addNewInsideH()); setNoBorder(borders.isSetInsideV() ? borders.getInsideV() : borders.addNewInsideV()); } private void setNoBorder(CTBorder border) { border.setVal(STBorder.NIL); border.setSz(BigInteger.ZERO); border.setSpace(BigInteger.ZERO); border.setColor("auto"); } private void setZeroWidth(CTTblWidth width) { width.setType(STTblWidth.DXA); width.setW(BigInteger.ZERO); } private void configureTable(XWPFTable table, int[] widths) { table.setTableAlignment(TableRowAlign.CENTER); CTTbl ctTbl = table.getCTTbl(); CTTblPr tblPr = ctTbl.getTblPr() != null ? ctTbl.getTblPr() : ctTbl.addNewTblPr(); CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW(); tblWidth.setType(STTblWidth.DXA); tblWidth.setW(BigInteger.valueOf(totalWidth(widths))); CTTblLayoutType layoutType = tblPr.isSetTblLayout() ? tblPr.getTblLayout() : tblPr.addNewTblLayout(); layoutType.setType(STTblLayoutType.FIXED); CTTblBorders borders = tblPr.isSetTblBorders() ? tblPr.getTblBorders() : tblPr.addNewTblBorders(); setBorder(borders.isSetTop() ? borders.getTop() : borders.addNewTop()); setBorder(borders.isSetLeft() ? borders.getLeft() : borders.addNewLeft()); setBorder(borders.isSetBottom() ? borders.getBottom() : borders.addNewBottom()); setBorder(borders.isSetRight() ? borders.getRight() : borders.addNewRight()); setBorder(borders.isSetInsideH() ? borders.getInsideH() : borders.addNewInsideH()); setBorder(borders.isSetInsideV() ? borders.getInsideV() : borders.addNewInsideV()); CTTblGrid grid = ctTbl.getTblGrid() != null ? ctTbl.getTblGrid() : ctTbl.addNewTblGrid(); while (grid.sizeOfGridColArray() > 0) { grid.removeGridCol(0); } for (int width : widths) { grid.addNewGridCol().setW(BigInteger.valueOf(width)); } } private int totalWidth(int[] widths) { int total = 0; for (int width : widths) { total += width; } return total; } private void setBorder(CTBorder border) { border.setVal(STBorder.SINGLE); border.setSz(BigInteger.valueOf(4)); border.setSpace(BigInteger.ZERO); border.setColor("000000"); } private void setCellWidth(XWPFTableCell cell, int width) { CTTcPr tcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr(); CTTblWidth tcW = tcPr.isSetTcW() ? tcPr.getTcW() : tcPr.addNewTcW(); tcW.setType(STTblWidth.DXA); tcW.setW(BigInteger.valueOf(width)); } private void setCellText(XWPFTableCell cell, String text) { cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); XWPFParagraph paragraph = cell.getParagraphs().isEmpty() ? cell.addParagraph() : cell.getParagraphs().get(0); paragraph.setAlignment(ParagraphAlignment.CENTER); paragraph.setSpacingBefore(0); paragraph.setSpacingAfter(0); addRun(paragraph, text == null ? "" : text, 10.5, false); } private void setRowProperties(XWPFTableRow row, boolean repeatHeader) { CTRow ctRow = row.getCtRow(); CTTrPr trPr = ctRow.isSetTrPr() ? ctRow.getTrPr() : ctRow.addNewTrPr(); trPr.addNewCantSplit(); if (repeatHeader) { trPr.addNewTblHeader(); } } private void mergeHorizontal(XWPFTableRow row, int[] widths, int firstIndex, int span) { int width = 0; for (int i = firstIndex; i < firstIndex + span; i++) { width += widths[i]; } XWPFTableCell first = row.getCell(firstIndex); setCellWidth(first, width); CTTcPr tcPr = first.getCTTc().isSetTcPr() ? first.getCTTc().getTcPr() : first.getCTTc().addNewTcPr(); (tcPr.isSetGridSpan() ? tcPr.getGridSpan() : tcPr.addNewGridSpan()).setVal(BigInteger.valueOf(span)); for (int i = firstIndex + span - 1; i > firstIndex; i--) { row.removeCell(i); } } private void mergeVertical(XWPFTableCell first, XWPFTableCell second) { setVMerge(first, STMerge.RESTART); setVMerge(second, STMerge.CONTINUE); } private void setVMerge(XWPFTableCell cell, STMerge.Enum value) { CTTcPr tcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr(); (tcPr.isSetVMerge() ? tcPr.getVMerge() : tcPr.addNewVMerge()).setVal(value); } private String[] buildRowValues(DeviceRecordDto record) { return new String[]{ formatDate(record.getUseStartDate()), 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[] 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); } private String formatTime(LocalDateTime value) { return value == null ? "" : value.format(TIME_FORMATTER); } private String statusText(Integer value) { if (value == null) { return ""; } return value == 0 ? "å¼å¸¸" : "è¯å¥½"; } private String valueOrEmpty(String value) { return value == null ? "" : value; } } cnas-device/src/main/resources/mapper/DeviceExaminePlanDetailsMapper.xml
@@ -12,6 +12,7 @@ d.device_id, d.device_number, d.device_name, d.device_model, d.check_time, d.check_index, d.check_method, @@ -19,6 +20,10 @@ d.check_charger_user_id, CASE WHEN d.check_charger_user='' or d.check_charger_user is null THEN u.name ELSE d.check_charger_user END AS check_charger_user, d.environment, d.check_basis, d.appearance_status, d.running_status, d.remark, d.file_name, d.file_url, @@ -39,7 +44,8 @@ CASE WHEN dev.next_examine_date IS NOT NULL AND dev.next_examine_date <= date_add(curdate(), interval 1 month) AND (dev.last_examine_date IS NULL OR dev.last_examine_date < str_to_date(concat(left(d.check_time, 7), '-01'), '%Y-%m-%d')) THEN 1 ELSE 0 END red_flag THEN 1 ELSE 0 END red_flag, (select count(*) from device_examine_attachment a where a.plan_details_id = d.plan_details_id) attachment_count from device_examine_plan_details d left join user u on u.id = d.check_charger_user_id left join device_examine_record dc on d.plan_details_id = dc.plan_details_id cnas-device/src/main/resources/mapper/DeviceExaminePlanMapper.xml
@@ -11,6 +11,7 @@ from device_examine_plan cqm left join user u1 on u1.id = cqm.write_user_id left join user u3 on u3.id = cqm.ratify_user_id where exists (select 1 from device_examine_plan_details cqmd where cqmd.plan_id = cqm.plan_id) order by cqm.create_time desc) a <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''"> ${ew.customSqlSegment} cnas-device/src/main/resources/mapper/InsOrderDeviceRecordMapper.xml
@@ -5,9 +5,12 @@ <select id="deviceRecordPage" resultType="com.ruoyi.device.dto.DeviceRecordDto"> select dr.*, d.device_name, d.management_number d.specification_model, d.management_number, o.entrust_code as order_code from device_record dr left join device d on d.id = dr.device_id left join ins_order o on o.id = dr.ins_order_id where 1=1 <if test="deviceId != null"> and dr.device_id = #{deviceId} @@ -37,7 +40,10 @@ <!-- æ¥è¯¢å¯¼åºè®¾å¤ä½¿ç¨è®°å½ --> <select id="selectExportList" resultType="com.ruoyi.device.dto.DeviceRecordDto"> select dr.* select dr.*, d.device_name, d.specification_model, d.management_number from device_record dr left join device d on d.id = dr.device_id where dr.use_start_date is not null cnas-device/src/main/resources/static/word/use-record.docxBinary files differ
inspect-server/src/main/java/com/ruoyi/inspect/mapper/InsOrderTemplateDeviceMapper.java
@@ -13,4 +13,7 @@ List<Integer> selectExistingDeviceIds(@Param("deviceIds") List<Integer> deviceIds); List<Integer> selectDeviceIdsByOrderId(@Param("orderId") Integer orderId); List<Integer> selectDeviceIdsByOrderAndTemplate(@Param("orderId") Integer orderId, @Param("templateId") Integer templateId); } inspect-server/src/main/java/com/ruoyi/inspect/service/impl/InsOrderPlanServiceImpl.java
@@ -605,11 +605,9 @@ } // æ·»å 设å¤è®°å½ threadPoolTaskExecutor.execute(() -> { // æ·»å 设å¤ä½¿ç¨è®°å½ addDeviceRecord(insSample, userId); }); // åå§è®°å½ä¿ååï¼æå½å模æ¿éç¨ç设å¤çæä½¿ç¨è®°å½ syncDeviceRecordsFromTemplate(saveInsContextDto.getOrderId(), saveInsContextDto.getSampleId(), saveInsContextDto.getCurrentTable(), userId); } /** @@ -692,6 +690,9 @@ .and(w -> w.isNull(InsProduct::getLastValue).or().eq(InsProduct::getLastValue, ""))); sample.setInsState(unfinished == 0 ? 2 : 1); insSampleMapper.updateById(sample); // åå§è®°å½ä¿ååï¼æå½å模æ¿éç¨ç设å¤çæä½¿ç¨è®°å½ syncDeviceRecordsFromTemplate(dto.getOrderId(), dto.getSampleId(), dto.getTemplateId(), userId); } /** @@ -1031,60 +1032,52 @@ } } private synchronized void addDeviceRecord(InsSample insSample, Integer userId) { InsOrder order = insOrderMapper.selectById(insSample.getInsOrderId()); /** * åå§è®°å½ä¿ååï¼æå½å模æ¿éç¨ç设å¤çæå¾ å¡«åç使ç¨è®°å½ã * åä¸è®¢åãæ ·åã设å¤åªçæä¸æ¡ï¼å·²ç»å¡«åè¿çè®°å½ä¸ä¼è¢«è¦çã */ private synchronized void syncDeviceRecordsFromTemplate(Integer orderId, Integer sampleId, Integer templateId, Integer userId) { if (orderId == null || sampleId == null || templateId == null) { return; } InsOrder order = insOrderMapper.selectById(orderId); InsSample sample = insSampleMapper.selectById(sampleId); if (order == null || sample == null) { return; } List<Integer> deviceIds = insOrderTemplateDeviceMapper .selectDeviceIdsByOrderAndTemplate(orderId, templateId); if (CollectionUtils.isEmpty(deviceIds)) { return; } User user = userMapper.selectById(userId); // æ¥è¯¢è®¾å¤ä½¿ç¨è®°å½æ¥è¯¢è¯¥è®¢åç使ç¨è®°å½ List<InsOrderDeviceRecordDto> deviceRecordDtoList = insOrderDeviceRecordMapper.selectDeviceNumber(insSample.getInsOrderId()); Set<String> recordCodeset = deviceRecordDtoList.stream().map(InsOrderDeviceRecordDto::getManagementNumber).collect(Collectors.toSet()); // è·å订å设å¤ç¼å· List<InsProductResult> resultList = insProductResultMapper.selectResultByOrderId(insSample.getInsOrderId()); Set<String> deviceCodeSet = new HashSet<>(); for (InsProductResult result : resultList) { // æ·»å 设å¤ç¼å· List<JSONObject> jsonObjects = JSON.parseArray(result.getEquipValue(), JSONObject.class); for (JSONObject jsonObject : jsonObjects) { if (!"".equals(jsonObject.get("v") + "")) { List<String> v = StrUtil.split(jsonObject.get("v") + "", "ï¼"); deviceCodeSet.addAll(v); } String usePerson = user == null ? "" : user.getName(); String sampleCode = StringUtils.isNotBlank(sample.getSampleCode()) ? sample.getSampleCode() : order.getEntrustCode(); for (Integer deviceId : deviceIds) { if (deviceId == null) { continue; } Long count = insOrderDeviceRecordMapper.selectCount(Wrappers.<InsOrderDeviceRecord>lambdaQuery() .eq(InsOrderDeviceRecord::getInsOrderId, orderId) .eq(InsOrderDeviceRecord::getDeviceId, deviceId) .eq(InsOrderDeviceRecord::getSampleCode, sampleCode)); if (count != null && count > 0) { continue; } InsOrderDeviceRecord record = new InsOrderDeviceRecord(); record.setInsOrderId(orderId); record.setDeviceId(deviceId); record.setSampleCode(sampleCode); record.setTemperature(order.getTemperature()); record.setHumidity(order.getHumidity()); record.setUseBefore(1); record.setUseAfter(1); record.setUsePersonId(userId); record.setUsePerson(usePerson); insOrderDeviceRecordMapper.insert(record); } // 1.夿æ¯å¦ææ²¡ææ·»å ç使ç¨è®°å½ Set<String> orderDeviceNumbers = getDeviceDifference(deviceCodeSet, recordCodeset); // æ·»å 使ç¨è®°å½, æ ¹æ®ç¼å·æ¥è¯¢è®¾å¤id if (CollectionUtils.isNotEmpty(orderDeviceNumbers)) { List<Integer> orderDeviceIds = insOrderDeviceRecordMapper.selectDeviceIdsByNumbers(orderDeviceNumbers); List<InsOrderDeviceRecord> collect = orderDeviceIds.stream().map(deviceId -> { InsOrderDeviceRecord insOrderDeviceRecord = new InsOrderDeviceRecord(); insOrderDeviceRecord.setInsOrderId(insSample.getInsOrderId()); insOrderDeviceRecord.setDeviceId(deviceId); insOrderDeviceRecord.setSampleCode(order.getEntrustCode()); insOrderDeviceRecord.setUseBefore(1); insOrderDeviceRecord.setUseAfter(1); insOrderDeviceRecord.setUsePerson(user.getName()); insOrderDeviceRecord.setUsePersonId(user.getId()); return insOrderDeviceRecord; }).collect(Collectors.toList()); insOrderDeviceRecordService.saveBatch(collect); } // 2.夿æ¯å¦åæ¶äºè®¾å¤ä½¿ç¨ Set<String> repoprNumbers = getDeviceDifference(recordCodeset, deviceCodeSet); if (CollectionUtils.isNotEmpty(repoprNumbers)) { List<Integer> reportDeviceIds = insOrderDeviceRecordMapper.selectDeviceIdsByNumbers(repoprNumbers); insOrderDeviceRecordMapper.delete(Wrappers.<InsOrderDeviceRecord>lambdaQuery() .in(InsOrderDeviceRecord::getDeviceId, reportDeviceIds) .eq(InsOrderDeviceRecord::getInsOrderId, insSample.getInsOrderId())); } } private static Set<String> getDeviceDifference(Set<String> number1, Set<String> number2) { return number1.stream().filter(s1 -> number2.stream().noneMatch(s2 -> s1.equals(s2))) .collect(Collectors.toSet()); } inspect-server/src/main/resources/mapper/InsOrderTemplateDeviceMapper.xml
@@ -20,4 +20,14 @@ order by min(otd.sort), otd.device_id </select> <select id="selectDeviceIdsByOrderAndTemplate" resultType="java.lang.Integer"> select otd.device_id from ins_order_template_device otd where otd.ins_order_id = #{orderId} and otd.template_id = #{templateId} and otd.device_id is not null group by otd.device_id order by min(otd.sort), otd.device_id </select> </mapper>