From 8ad863082097ffdcab4a8e7f426d344a1fe6f892 Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期六, 07 十一月 2026 00:27:02 +0800
Subject: [PATCH] 修复人员管理接口校验与导出,完善设备保养计划与文件受控功能
---
cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenancePlanServiceImpl.java | 402 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 370 insertions(+), 32 deletions(-)
diff --git a/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenancePlanServiceImpl.java b/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenancePlanServiceImpl.java
index 656bb10..64e266f 100644
--- a/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenancePlanServiceImpl.java
+++ b/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceMaintenancePlanServiceImpl.java
@@ -17,34 +17,48 @@
import com.ruoyi.common.utils.WxCpUtils;
import com.ruoyi.device.dto.DeviceMaintenancePlanDetailsDto;
import com.ruoyi.device.dto.DeviceMaintenancePlanDto;
+import com.ruoyi.device.mapper.DeviceMaintenanceAttachmentMapper;
+import com.ruoyi.device.mapper.DeviceMaintenanceMapper;
import com.ruoyi.device.mapper.DeviceMaintenancePlanDetailsMapper;
import com.ruoyi.device.mapper.DeviceMaintenancePlanMapper;
import com.ruoyi.device.mapper.DeviceMapper;
import com.ruoyi.device.pojo.Device;
+import com.ruoyi.device.pojo.DeviceMaintenance;
+import com.ruoyi.device.pojo.DeviceMaintenanceAttachment;
import com.ruoyi.device.pojo.DeviceMaintenancePlan;
import com.ruoyi.device.pojo.DeviceMaintenancePlanDetails;
import com.ruoyi.device.service.DeviceMaintenancePlanDetailsService;
import com.ruoyi.device.service.DeviceMaintenancePlanService;
+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.commons.collections4.CollectionUtils;
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;
+import org.springframework.web.multipart.MultipartFile;
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;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -71,6 +85,16 @@
private UserMapper userMapper;
@Resource
private DeviceMapper deviceMapper;
+ @Resource
+ private DeviceMaintenanceMapper deviceMaintenanceMapper;
+ @Resource
+ private DeviceMaintenanceAttachmentMapper deviceMaintenanceAttachmentMapper;
+
+ @Value("${file.path}")
+ private String filePath;
+
+ @Value("${wordUrl}")
+ private String wordUrl;
/**
* 鍒嗛〉鏌ヨ璁惧淇濆吇璁″垝
@@ -133,13 +157,22 @@
}
this.saveOrUpdate(deviceMaintenancePlanDto);
- // 鍒犻櫎鍘熸湰鐨勮鎯�
+ // 鍒犻櫎鍘熸湰鐨勮鎯咃紱鏄庣粏閲嶅缓鍚庝粛淇濈暀鍘熸槑缁唅d鐨勯檮浠朵笉娓呯悊锛宨d涓㈠け鐨勬墠娓呯悊
+ List<DeviceMaintenancePlanDetails> oldDetails = deviceMaintenancePlanDetailsService.list(
+ Wrappers.<DeviceMaintenancePlanDetails>lambdaQuery()
+ .eq(DeviceMaintenancePlanDetails::getMaintenancePlanId, deviceMaintenancePlanDto.getMaintenancePlanId()));
deviceMaintenancePlanDetailsService.remove(Wrappers.<DeviceMaintenancePlanDetails>lambdaQuery().eq(DeviceMaintenancePlanDetails::getMaintenancePlanId, deviceMaintenancePlanDto.getMaintenancePlanId()));
+ List<Integer> lostDetailIds = oldDetails.stream().map(DeviceMaintenancePlanDetails::getMaintenancePlanDetailId)
+ .collect(Collectors.toList());
// 璇︽儏璧嬪�煎苟淇濆瓨
List<DeviceMaintenancePlanDetailsDto> deviceMaintenancePlanDetails = deviceMaintenancePlanDto.getDeviceMaintenancePlanDetails();
if (CollectionUtils.isNotEmpty(deviceMaintenancePlanDetails)) { // 璇︽儏涓嶄负绌�
+ List<Integer> keptDetailIds = deviceMaintenancePlanDetails.stream()
+ .map(DeviceMaintenancePlanDetails::getMaintenancePlanDetailId)
+ .filter(id -> id != null)
+ .collect(Collectors.toList());
+ lostDetailIds.removeAll(keptDetailIds);
List<DeviceMaintenancePlanDetails> collect = deviceMaintenancePlanDetails.stream().map(deviceMaintenancePlanDetail -> { // 閬嶅巻璇︽儏
- deviceMaintenancePlanDetail.setDeviceId(deviceMaintenancePlanDto.getDeviceId()); // 璁惧ID
deviceMaintenancePlanDetail.setMaintenancePlanId(deviceMaintenancePlanDto.getMaintenancePlanId()); // 淇濆吇璁″垝ID
DeviceMaintenancePlanDetails planDetails = new DeviceMaintenancePlanDetails();
BeanUtils.copyProperties(deviceMaintenancePlanDetail, planDetails);
@@ -147,6 +180,7 @@
}).collect(Collectors.toList());
deviceMaintenancePlanDetailsService.saveBatch(collect);
}
+ removeAttachmentsByDetailIds(lostDetailIds);
return Result.success();
}
@@ -157,8 +191,12 @@
*/
@Override
public Result deleteMaintenancePlan(DeviceMaintenancePlanDto deviceMaintenancePlanDto) {
+ List<DeviceMaintenancePlanDetails> details = deviceMaintenancePlanDetailsService.list(
+ Wrappers.<DeviceMaintenancePlanDetails>lambdaQuery()
+ .eq(DeviceMaintenancePlanDetails::getMaintenancePlanId, deviceMaintenancePlanDto.getMaintenancePlanId()));
this.removeById(deviceMaintenancePlanDto);
deviceMaintenancePlanDetailsService.remove(Wrappers.<DeviceMaintenancePlanDetails>lambdaQuery().eq(DeviceMaintenancePlanDetails::getMaintenancePlanId, deviceMaintenancePlanDto.getMaintenancePlanId()));
+ removeAttachmentsByDetailIds(details.stream().map(DeviceMaintenancePlanDetails::getMaintenancePlanDetailId).collect(Collectors.toList()));
return Result.success();
}
@@ -173,27 +211,27 @@
// 鏌ヨ璁惧淇濆吇璁″垝
DeviceMaintenancePlanDto deviceMaintenancePlan = baseMapper.selectMaintenancePlanById(maintenancePlanId);
- // 鏌ヨ璁惧淇濆吇璁″垝璇︽儏
- List<DeviceMaintenancePlanDetailsDto> deviceMaintenancePlanDetailsDtoList = deviceMaintenancePlanDetailsMapper.deviceInspectionRecordDetailsList(maintenancePlanId);
+ // 鏌ヨ璁惧淇濆吇璁″垝璇︽儏锛屾寜鈥滆澶� + 淇濆吇鏈堜唤鈥濆厹搴曞幓閲�
+ List<DeviceMaintenancePlanDetailsDto> deviceMaintenancePlanDetailsDtoList = dedupeMaintenanceDetails(
+ deviceMaintenancePlanDetailsMapper.deviceInspectionRecordDetailsList(maintenancePlanId));
// 璁剧疆搴忓彿
- deviceMaintenancePlanDetailsDtoList.forEach(deviceInspectionRecordDetails -> {
- deviceInspectionRecordDetails.setIndex(deviceMaintenancePlanDetailsDtoList.indexOf(deviceInspectionRecordDetails) + 1);
- });
+ for (int i = 0; i < deviceMaintenancePlanDetailsDtoList.size(); i++) {
+ deviceMaintenancePlanDetailsDtoList.get(i).setIndex(i + 1);
+ }
// 鑾峰彇璺緞
InputStream inputStream = this.getClass().getResourceAsStream("/static/word/maintenance-plan.docx");
Configure configure = Configure.builder()
.bind("deviceMaintenancePlanDetailsDtoList", new HackLoopTableRenderPolicy())
.build();
- XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render(
- new HashMap<String, Object>() {{
- put("deviceMaintenancePlan", deviceMaintenancePlan);
- put("deviceMaintenancePlanDetailsDtoList", deviceMaintenancePlanDetailsDtoList);
- // 缂栧埗浜虹鍚嶅湴鍧�
- put("compilerUrl", UserUtils.getFinalUserSignatureOrTransparent(deviceMaintenancePlan.getCompilerId()));
- // 瀹℃牳浜虹鍚嶅湴鍧�
- put("auditUrl", UserUtils.getFinalUserSignatureOrTransparent(deviceMaintenancePlan.getAuditId()));
- }});
+ Map<String, Object> renderData = new HashMap<>();
+ renderData.put("deviceMaintenancePlan", deviceMaintenancePlan);
+ renderData.put("deviceMaintenancePlanDetailsDtoList", deviceMaintenancePlanDetailsDtoList);
+ // 缂栧埗浜虹鍚嶅湴鍧�
+ renderData.put("compilerUrl", UserUtils.getFinalUserSignatureOrTransparent(deviceMaintenancePlan.getCompilerId()));
+ // 瀹℃牳浜虹鍚嶅湴鍧�
+ renderData.put("auditUrl", UserUtils.getFinalUserSignatureOrTransparent(deviceMaintenancePlan.getAuditId()));
+ XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render(renderData);
try {
response.setContentType("application/msword");
@@ -225,7 +263,8 @@
// 鏌ヨ璇︽儏
DeviceMaintenancePlanDto deviceMaintenancePlanDto = new DeviceMaintenancePlanDto();
BeanUtils.copyProperties(deviceMaintenancePlan, deviceMaintenancePlanDto);
- deviceMaintenancePlanDto.setDeviceMaintenancePlanDetails(deviceMaintenancePlanDetailsMapper.deviceInspectionRecordDetailsList(maintenancePlanId));
+ deviceMaintenancePlanDto.setDeviceMaintenancePlanDetails(dedupeMaintenanceDetails(
+ deviceMaintenancePlanDetailsMapper.deviceInspectionRecordDetailsList(maintenancePlanId)));
return Result.success(deviceMaintenancePlanDto);
}
@@ -328,20 +367,38 @@
}
/**
- * 璁惧妗f鍙樻洿鍚庯紝鎶婂凡鍒扮偣鐨勮澶囧悓姝ュ埌瀵瑰簲骞翠唤鐨勮澶囦繚鍏昏鍒掓槑缁�
+ * 淇濆吇璁″垝骞翠唤鍒楄〃锛氬垹闄ゆ病鏈変换浣曟槑缁嗙殑绌哄勾浠借鍒掑悗锛岃繑鍥炴湁鏄庣粏鐨勫勾浠斤紙鍊掑簭锛�
+ */
+ @Override
+ public List<String> getMaintenancePlanYears() {
+ // 鍘嗗彶鏁版嵁鑷剤锛氬厛璁╁凡瀹℃牳鐨勬槑缁嗘寜瀹℃牳瀹屾垚骞翠唤褰掍綅锛屽啀娓呯悊绌哄勾浠借鍒�
+ reclassifyReviewedDetails();
+ List<DeviceMaintenancePlan> plans = baseMapper.selectList(null);
+ for (DeviceMaintenancePlan plan : plans) {
+ Long detailCount = deviceMaintenancePlanDetailsMapper.selectCount(Wrappers.<DeviceMaintenancePlanDetails>lambdaQuery()
+ .eq(DeviceMaintenancePlanDetails::getMaintenancePlanId, plan.getMaintenancePlanId()));
+ if (detailCount == null || detailCount == 0) {
+ removeById(plan.getMaintenancePlanId());
+ }
+ }
+ return baseMapper.selectPlanYears();
+ }
+
+ /**
+ * 璁惧妗f鍙樻洿鍚庯紝绔嬪嵆鎶婅澶囩櫥璁板埌涓嬫淇濆吇鏃ユ湡鎵�鍦ㄥ勾浠界殑璁惧淇濆吇璁″垝鏄庣粏
*/
@Override
public void syncDeviceMaintenanceDetail(Device device) {
- LocalDate remind = calcMaintenanceRemindDate(device);
- if (remind == null || remind.isAfter(LocalDate.now())) {
+ LocalDate due = calcMaintenanceDueDate(device);
+ if (due == null) {
return;
}
- DeviceMaintenancePlan plan = getOrCreatePlanEntity(String.valueOf(remind.getYear()));
+ DeviceMaintenancePlan plan = getOrCreatePlanEntity(String.valueOf(due.getYear()));
fillMaintenanceDetailIfAbsent(plan, device);
}
/**
- * 淇濆吇璁板綍淇濆瓨鍚庯紝婊氬姩璁惧妗f鐨勬渶杩�/涓嬫淇濆吇鏃ユ湡
+ * 瀹℃牳閫氳繃鍚庯紝鎸夊鏍搁�氳繃褰撳ぉ婊氬姩璁惧妗f鐨勬渶杩�/涓嬫淇濆吇鏃ユ湡
*/
@Override
public void updateDeviceMaintenanceDate(Integer deviceId, LocalDate maintenanceDate) {
@@ -365,6 +422,75 @@
}
}
deviceMapper.updateById(device);
+ // 鏈疆淇濆吇瀹屾垚鍚庣珛鍗崇櫥璁颁笅涓�杞紝鍘嗗彶鏄庣粏淇濇寔涓嶅姩
+ syncDeviceMaintenanceDetail(device);
+ }
+
+ /**
+ * 瀹℃牳閫氳繃鍚庯紝鎶婅鍒掓槑缁嗗綊鍒板鏍稿畬鎴愬勾浠界殑璁″垝涓嬶紱鎻愬墠瀹屾垚鐨勬槑缁嗕笉鍐嶇暀鍦ㄥ師璁″垝骞翠唤
+ */
+ @Override
+ public void reclassifyMaintenanceDetailByReviewDate(Integer maintenancePlanDetailId, LocalDate reviewDate) {
+ if (maintenancePlanDetailId == null || reviewDate == null) {
+ return;
+ }
+ DeviceMaintenancePlanDetails detail = deviceMaintenancePlanDetailsMapper.selectById(maintenancePlanDetailId);
+ if (detail == null || detail.getMaintenancePlanId() == null) {
+ return;
+ }
+ DeviceMaintenancePlan sourcePlan = baseMapper.selectById(detail.getMaintenancePlanId());
+ if (sourcePlan == null) {
+ return;
+ }
+ String targetYear = String.valueOf(reviewDate.getYear());
+ if (StringUtils.isNotBlank(sourcePlan.getPlanYear()) && targetYear.equals(sourcePlan.getPlanYear().trim())) {
+ return;
+ }
+ moveMaintenanceDetailToYear(detail, reviewDate);
+ }
+
+ /**
+ * 鎶婅鍒掓槑缁嗘尓鍒板鏍稿畬鎴愬勾浠界殑璁″垝涓嬶紝璁″垝鏃ユ湡鎸夊疄闄呭畬鎴愭棩鏈熻褰�
+ */
+ private void moveMaintenanceDetailToYear(DeviceMaintenancePlanDetails detail, LocalDate reviewDate) {
+ DeviceMaintenancePlan targetPlan = getOrCreatePlanEntity(String.valueOf(reviewDate.getYear()));
+ DeviceMaintenancePlanDetails update = new DeviceMaintenancePlanDetails();
+ update.setMaintenancePlanDetailId(detail.getMaintenancePlanDetailId());
+ update.setMaintenancePlanId(targetPlan.getMaintenancePlanId());
+ // 璁″垝鏃ユ湡鎸夊疄闄呭畬鎴愭棩鏈熻褰曪紝鍒楄〃鎸夊畬鎴愬勾浠芥帓搴忥紝涓嶅啀鎸夊師璁″垝鏃ユ湡鏍囩孩
+ update.setMaintenanceDate(reviewDate);
+ deviceMaintenancePlanDetailsMapper.updateById(update);
+ }
+
+ /**
+ * 鍘嗗彶鏁版嵁鑷剤锛氬凡瀹℃牳閫氳繃浣嗚鍒掑勾浠戒笌瀹℃牳瀹屾垚骞翠唤涓嶄竴鑷寸殑鏄庣粏锛屾寜瀹℃牳瀹屾垚骞翠唤褰掍綅
+ */
+ private void reclassifyReviewedDetails() {
+ List<DeviceMaintenance> records = deviceMaintenanceMapper.selectList(Wrappers.<DeviceMaintenance>lambdaQuery()
+ .eq(DeviceMaintenance::getReviewStatus, 1)
+ .isNotNull(DeviceMaintenance::getMaintenancePlanDetailId)
+ .isNotNull(DeviceMaintenance::getReviewTime));
+ if (CollectionUtils.isEmpty(records)) {
+ return;
+ }
+ List<Integer> detailIds = records.stream().map(DeviceMaintenance::getMaintenancePlanDetailId)
+ .distinct().collect(Collectors.toList());
+ Map<Integer, DeviceMaintenancePlanDetails> detailMap = deviceMaintenancePlanDetailsMapper.selectBatchIds(detailIds)
+ .stream().collect(Collectors.toMap(DeviceMaintenancePlanDetails::getMaintenancePlanDetailId, item -> item, (a, b) -> a));
+ Map<Integer, String> planYears = baseMapper.selectList(null).stream()
+ .collect(Collectors.toMap(DeviceMaintenancePlan::getMaintenancePlanId,
+ item -> item.getPlanYear() == null ? "" : item.getPlanYear().trim(), (a, b) -> a));
+ for (DeviceMaintenance record : records) {
+ DeviceMaintenancePlanDetails detail = detailMap.get(record.getMaintenancePlanDetailId());
+ if (detail == null || detail.getMaintenancePlanId() == null) {
+ continue;
+ }
+ String reviewYear = String.valueOf(record.getReviewTime().getYear());
+ if (reviewYear.equals(planYears.get(detail.getMaintenancePlanId()))) {
+ continue;
+ }
+ moveMaintenanceDetailToYear(detail, record.getReviewTime().toLocalDate());
+ }
}
/**
@@ -401,7 +527,7 @@
}
/**
- * 鎵弿鎵�鏈夎澶囷紝鎶婂凡鍒扮偣锛堜笅娆′繚鍏绘棩鏈熷墠1涓湀璧凤紝鍚凡杩囨湡锛夌殑璁惧琛ヨ繘鏈勾搴﹁鍒�
+ * 鎵弿鎵�鏈夎澶囷紝鎶婂簲淇濆吇鏃ユ湡钀藉湪璇ヨ鍒掑勾浠界殑璁惧琛ヨ繘璁″垝锛堝綋鍓嶅勾鍙婁互寰�骞村害鍖呭惈閫炬湡鏈繚鍏荤殑璁惧锛�
*/
private void ensureMaintenanceDetails(DeviceMaintenancePlan plan) {
List<Device> devices = deviceMapper.selectList(null);
@@ -411,9 +537,9 @@
}
/**
- * 璁惧鎻愰啋璧风偣锛氫笅娆′繚鍏绘棩鏈熷墠1涓湀锛堟病濉笅娆℃棩鏈熸椂鐢ㄦ渶杩戞棩鏈�+淇濆吇鍛ㄦ湡鍏滃簳锛�
+ * 璁惧鏈疆搴斾繚鍏绘棩鏈燂紙娌″~涓嬫鏃ユ湡鏃剁敤鏈�杩戞棩鏈�+淇濆吇鍛ㄦ湡鍏滃簳锛�
*/
- private LocalDate calcMaintenanceRemindDate(Device device) {
+ private LocalDate calcMaintenanceDueDate(Device device) {
LocalDateTime base = device.getNextMaintenanceDate();
if (base == null && device.getLastMaintenanceDate() != null && StringUtils.isNotBlank(device.getMaintenanceCycle())) {
try {
@@ -421,24 +547,42 @@
} catch (NumberFormatException ignored) {
}
}
- return base == null ? null : base.toLocalDate().minusMonths(1);
+ return base == null ? null : base.toLocalDate();
}
/**
- * 宸插埌鐐逛笖璁″垝涓皻鏃犺璁惧鏈疆鏄庣粏鏃惰嚜鍔ㄨˉ涓�鏉�
+ * 璁″垝涓皻鏃犺璁惧鏈疆鏄庣粏鏃惰嚜鍔ㄨˉ涓�鏉★紱淇濆吇鏃堕棿鍙栧簲淇濆吇鏃ユ湡
*/
private void fillMaintenanceDetailIfAbsent(DeviceMaintenancePlan plan, Device device) {
- LocalDate remind = calcMaintenanceRemindDate(device);
- if (remind == null || remind.isAfter(LocalDate.now())) {
+ LocalDate due = calcMaintenanceDueDate(device);
+ if (due == null) {
return;
}
- if (plan.getPlanYear() != null && String.valueOf(remind.getYear()).compareTo(plan.getPlanYear()) > 0) {
+ if (StringUtils.isBlank(plan.getPlanYear())) {
return;
}
+ int planYearValue;
+ try {
+ planYearValue = Integer.parseInt(plan.getPlanYear().trim());
+ } catch (NumberFormatException e) {
+ return;
+ }
+ int dueYear = due.getYear();
+ // 鏈潵骞翠唤鐨勮鍒掑彧鐧昏搴斾繚鍏绘棩鏈熷氨鍦ㄨ骞翠唤鐨勮澶囷紝閬垮厤鎶婂線骞寸殑鏃ф棩鏈熻ˉ杩涙湭鏉ョ殑璁″垝
+ if (planYearValue > LocalDate.now().getYear()) {
+ if (dueYear != planYearValue) {
+ return;
+ }
+ } else if (dueYear > planYearValue) {
+ return;
+ }
+ // 鍚屼竴璁惧鍚屼竴搴斾繚鍏绘湀浠藉彧淇濈暀涓�鏉★紝閬垮厤鎵嬫敼杩囪鍐呮棩鏈熷悗鍒锋柊閲嶅鐢熸垚
+ LocalDate monthStart = due.withDayOfMonth(1);
Long exist = deviceMaintenancePlanDetailsMapper.selectCount(Wrappers.<DeviceMaintenancePlanDetails>lambdaQuery()
.eq(DeviceMaintenancePlanDetails::getMaintenancePlanId, plan.getMaintenancePlanId())
.eq(DeviceMaintenancePlanDetails::getDeviceId, device.getId())
- .eq(DeviceMaintenancePlanDetails::getMaintenanceDate, remind));
+ .ge(DeviceMaintenancePlanDetails::getMaintenanceDate, monthStart)
+ .lt(DeviceMaintenancePlanDetails::getMaintenanceDate, monthStart.plusMonths(1)));
if (exist != null && exist > 0) {
return;
}
@@ -446,8 +590,202 @@
detail.setMaintenancePlanId(plan.getMaintenancePlanId());
detail.setDeviceId(device.getId());
detail.setMaintenanceIntervals(device.getMaintenanceCycle());
- detail.setMaintenanceDate(remind);
+ detail.setMaintenanceDate(due);
deviceMaintenancePlanDetailsMapper.insert(detail);
}
+ /**
+ * 涓轰繚鍏昏褰曟壘涓�鏉″彲鍏宠仈鐨勮鍒掓槑缁嗭紱娌℃湁鍙敤鏄庣粏鏃跺湪褰撳墠骞村害璁″垝鏂板鏈疆鏄庣粏
+ */
+ @Override
+ public DeviceMaintenancePlanDetails resolveMaintenancePlanDetail(Integer deviceId, Integer maintenancePlanDetailId, LocalDate maintenanceDate) {
+ if (maintenancePlanDetailId != null) {
+ DeviceMaintenancePlanDetails detail = deviceMaintenancePlanDetailsMapper.selectById(maintenancePlanDetailId);
+ if (detail == null) {
+ throw new ErrorException("淇濆吇璁″垝鏄庣粏涓嶅瓨鍦�");
+ }
+ return detail;
+ }
+ if (deviceId == null) {
+ throw new ErrorException("缂哄皯璁惧id");
+ }
+ Device device = deviceMapper.selectById(deviceId);
+ if (device == null) {
+ throw new ErrorException("淇濆吇璁惧涓嶅瓨鍦�");
+ }
+ LocalDate planDate = maintenanceDate == null ? LocalDate.now() : maintenanceDate;
+ DeviceMaintenancePlan plan = getOrCreatePlanEntity(String.valueOf(planDate.getYear()));
+ List<DeviceMaintenancePlanDetails> details = deviceMaintenancePlanDetailsMapper.selectList(
+ Wrappers.<DeviceMaintenancePlanDetails>lambdaQuery()
+ .eq(DeviceMaintenancePlanDetails::getDeviceId, deviceId)
+ .orderByAsc(DeviceMaintenancePlanDetails::getMaintenanceDate));
+ DeviceMaintenancePlanDetails nearest = null;
+ long nearestDistance = Long.MAX_VALUE;
+ for (DeviceMaintenancePlanDetails detail : details) {
+ // 宸叉湁淇濆吇璁板綍鐨勬槑缁嗕唬琛ㄥ凡瀹屾垚鐨勪竴杞紝鍚庣画璁板綍姘歌繙涓嶅鐢ㄣ�佷笉瑕嗙洊
+ Long recordCount = deviceMaintenanceMapper.selectCount(Wrappers.<DeviceMaintenance>lambdaQuery()
+ .eq(DeviceMaintenance::getMaintenancePlanDetailId, detail.getMaintenancePlanDetailId()));
+ if (recordCount != null && recordCount > 0) {
+ continue;
+ }
+ if (detail.getMaintenancePlanId() != null && detail.getMaintenancePlanId().equals(plan.getMaintenancePlanId())) {
+ return detail;
+ }
+ long distance = monthDistance(detail.getMaintenanceDate(), planDate);
+ if (distance < nearestDistance) {
+ nearest = detail;
+ nearestDistance = distance;
+ }
+ }
+ if (nearest != null) {
+ return nearest;
+ }
+ DeviceMaintenancePlanDetails detail = new DeviceMaintenancePlanDetails();
+ detail.setMaintenancePlanId(plan.getMaintenancePlanId());
+ detail.setDeviceId(device.getId());
+ detail.setMaintenanceIntervals(device.getMaintenanceCycle());
+ detail.setMaintenanceDate(planDate);
+ deviceMaintenancePlanDetailsMapper.insert(detail);
+ return detail;
+ }
+
+ /**
+ * 淇敼璁惧淇濆吇璁″垝璇︽儏锛堝凡瀹℃牳鐨勬槑缁嗕笉鍏佽淇敼锛�
+ */
+ @Override
+ public boolean updateMaintenancePlanDetail(DeviceMaintenancePlanDetails detail) {
+ if (detail == null || detail.getMaintenancePlanDetailId() == null) {
+ throw new ErrorException("缂哄皯璁惧淇濆吇璁″垝鏄庣粏id");
+ }
+ DeviceMaintenance record = deviceMaintenanceMapper.selectOne(Wrappers.<DeviceMaintenance>lambdaQuery()
+ .eq(DeviceMaintenance::getMaintenancePlanDetailId, detail.getMaintenancePlanDetailId())
+ .last("limit 1"));
+ if (record != null && record.getReviewStatus() != null) {
+ throw new ErrorException("璇ヨ鍒掑凡瀹℃牳锛屼笉鍏佽淇敼");
+ }
+ return deviceMaintenancePlanDetailsMapper.updateById(detail) > 0;
+ }
+
+ /**
+ * 鍒犻櫎璁惧淇濆吇璁″垝璇︽儏锛涘凡鍑哄鏍哥粨鏋滅殑璁板綍闅忓巻鍙茬暀妗o紝鏈鏍哥殑璁板綍闅忔槑缁嗕竴璧峰垹闄�
+ */
+ @Override
+ public boolean removeMaintenancePlanDetail(Integer maintenancePlanDetailId) {
+ if (maintenancePlanDetailId == null) {
+ throw new ErrorException("缂哄皯璁惧淇濆吇璁″垝鏄庣粏id");
+ }
+ DeviceMaintenancePlanDetails detail = deviceMaintenancePlanDetailsMapper.selectById(maintenancePlanDetailId);
+ if (detail == null) {
+ return false;
+ }
+ List<DeviceMaintenance> records = deviceMaintenanceMapper.selectList(Wrappers.<DeviceMaintenance>lambdaQuery()
+ .eq(DeviceMaintenance::getMaintenancePlanDetailId, maintenancePlanDetailId));
+ // 瀹℃牳涓嶉�氳繃鐨勮褰曞厑璁歌繛鍚屾槑缁嗕竴璧峰垹闄わ紱瀹℃牳閫氳繃鐨勮褰曚负鍘嗗彶鐣欐。锛屼笉鍏佽鍒犻櫎
+ boolean hasPassedRecord = records.stream().anyMatch(item -> item.getReviewStatus() != null
+ && item.getReviewStatus() == 1);
+ if (hasPassedRecord) {
+ throw new ErrorException("璇ヨ鍒掑凡瀛樺湪瀹℃牳閫氳繃鐨勪繚鍏昏褰曪紝涓轰繚鐣欏巻鍙茶褰曚笉鍏佽鍒犻櫎");
+ }
+ if (!records.isEmpty()) {
+ List<Integer> recordIds = records.stream().map(DeviceMaintenance::getId).collect(Collectors.toList());
+ deviceMaintenanceMapper.deleteBatchIds(recordIds);
+ }
+ removeAttachmentsByDetailIds(List.of(maintenancePlanDetailId));
+ return deviceMaintenancePlanDetailsMapper.deleteById(maintenancePlanDetailId) > 0;
+ }
+
+ @Override
+ public List<DeviceMaintenanceAttachment> selectAttachments(Integer maintenancePlanDetailId) {
+ if (maintenancePlanDetailId == null) {
+ return new ArrayList<>();
+ }
+ return deviceMaintenanceAttachmentMapper.selectList(Wrappers.<DeviceMaintenanceAttachment>lambdaQuery()
+ .eq(DeviceMaintenanceAttachment::getMaintenancePlanDetailId, maintenancePlanDetailId)
+ .orderByAsc(DeviceMaintenanceAttachment::getSort, DeviceMaintenanceAttachment::getId));
+ }
+
+ @Override
+ public DeviceMaintenanceAttachment uploadAttachment(Integer maintenancePlanDetailId, MultipartFile file) {
+ if (maintenancePlanDetailId == null) {
+ throw new ErrorException("缂哄皯淇濆吇璁″垝鏄庣粏id");
+ }
+ if (deviceMaintenancePlanDetailsMapper.selectById(maintenancePlanDetailId) == 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));
+ DeviceMaintenanceAttachment attachment = new DeviceMaintenanceAttachment();
+ attachment.setMaintenancePlanDetailId(maintenancePlanDetailId);
+ attachment.setFileName(originalName);
+ attachment.setFileUrl(fileUrl);
+ attachment.setSort(selectAttachments(maintenancePlanDetailId).size());
+ deviceMaintenanceAttachmentMapper.insert(attachment);
+ return attachment;
+ } catch (IOException e) {
+ throw new ErrorException("闄勪欢涓婁紶澶辫触");
+ }
+ }
+
+ @Override
+ public boolean deleteAttachment(Long id) {
+ return deviceMaintenanceAttachmentMapper.deleteById(id) > 0;
+ }
+
+ /**
+ * 鍒犻櫎璁″垝鏄庣粏瀵瑰簲鐨勯檮浠惰褰�
+ */
+ private void removeAttachmentsByDetailIds(List<Integer> maintenancePlanDetailIds) {
+ if (CollectionUtils.isEmpty(maintenancePlanDetailIds)) {
+ return;
+ }
+ deviceMaintenanceAttachmentMapper.delete(Wrappers.<DeviceMaintenanceAttachment>lambdaQuery()
+ .in(DeviceMaintenanceAttachment::getMaintenancePlanDetailId, maintenancePlanDetailIds));
+ }
+
+ /**
+ * 鍚屼竴璁″垝銆佸悓涓�璁惧鍙繚鐣欎竴鏉★紱SQL 宸叉寜鈥滃凡鏈変繚鍏昏褰曚紭鍏堛�佸鏍搁�氳繃浼樺厛銆佹渶鏂颁紭鍏堚�濇帓搴忥紝杩欓噷鍙栭鏉�
+ */
+ private List<DeviceMaintenancePlanDetailsDto> dedupeMaintenanceDetails(List<DeviceMaintenancePlanDetailsDto> details) {
+ if (CollectionUtils.isEmpty(details)) {
+ return details;
+ }
+ Map<String, DeviceMaintenancePlanDetailsDto> unique = new LinkedHashMap<>();
+ for (DeviceMaintenancePlanDetailsDto detail : details) {
+ String key = detail.getDeviceId() != null ? String.valueOf(detail.getDeviceId())
+ : "name:" + detail.getDeviceName();
+ unique.putIfAbsent(key, detail);
+ }
+ return new ArrayList<>(unique.values());
+ }
+
+ /**
+ * 涓や釜淇濆吇鏃ユ湡涔嬮棿鐩稿樊鐨勬湀鏁�
+ */
+ private long monthDistance(LocalDate from, LocalDate target) {
+ if (from == null || target == null) {
+ return Long.MAX_VALUE;
+ }
+ return Math.abs(ChronoUnit.MONTHS.between(YearMonth.from(from), YearMonth.from(target)));
+ }
+
}
--
Gitblit v1.9.3