From 2f07589b54d56085af77b50d580890cd4130b444 Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期一, 19 十月 2026 15:19:53 +0800
Subject: [PATCH] 设备模块后端业务规则、计划接口与日期联动

---
 cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceExaminePlanServiceImpl.java |  173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 171 insertions(+), 2 deletions(-)

diff --git a/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceExaminePlanServiceImpl.java b/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceExaminePlanServiceImpl.java
index 4a4d45b..7ef252c 100644
--- a/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceExaminePlanServiceImpl.java
+++ b/cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceExaminePlanServiceImpl.java
@@ -45,7 +45,10 @@
 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.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -289,9 +292,9 @@
                     put("deviceExaminePlan", deviceExaminePlanDto);
                     put("deviceExaminePlanDetailsDtoList", deviceExaminePlanDetailsDtoList);
                     //鑾峰彇鏍告煡浜虹殑绛惧悕鍦板潃
-                    put("writeUserUrl", UserUtils.getFinalUserSignatureUrl(deviceExaminePlanDto.getWriteUserId()));
+                    put("writeUserUrl", UserUtils.getFinalUserSignatureOrTransparent(deviceExaminePlanDto.getWriteUserId()));
                     //鑾峰彇瀹℃煡浜虹殑绛惧悕鍦板潃
-                    put("reviewUserUrl", UserUtils.getFinalUserSignatureUrl(deviceExaminePlanDto.getRatifyUserId()));
+                    put("reviewUserUrl", UserUtils.getFinalUserSignatureOrTransparent(deviceExaminePlanDto.getRatifyUserId()));
                 }});
 
         try {
@@ -346,4 +349,170 @@
 
         return deviceExaminePlanDto;
     }
+
+    /**
+     * 鎸夊勾浠芥煡璇㈣澶囨牳鏌ヨ鍒掞紙涓嶅瓨鍦ㄥ垯鑷姩鍒涘缓锛夛紝骞惰嚜鍔ㄨˉ鍏ㄥ凡鍒扮偣鐨勮澶囨槑缁�
+     */
+    @Override
+    public DeviceExaminePlanDto getOrCreatePlanByYear(String planYear) {
+        if (StringUtils.isBlank(planYear)) {
+            planYear = String.valueOf(LocalDate.now().getYear());
+        }
+        DeviceExaminePlan plan = getOrCreatePlanEntity(planYear);
+        ensureExamineDetails(plan);
+        DeviceExaminePlanDto planDto = new DeviceExaminePlanDto();
+        BeanUtils.copyProperties(plan, planDto);
+        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        planDto.setWriteTimeStr(plan.getWriteTime() == null ? null : plan.getWriteTime().format(dateFormatter));
+        planDto.setRatifyTimeStr(plan.getRatifyTime() == null ? null : plan.getRatifyTime().format(dateFormatter));
+        if (plan.getWriteUserId() != null) {
+            User writeUser = userMapper.selectById(plan.getWriteUserId());
+            if (writeUser != null) {
+                planDto.setWriteName(writeUser.getName());
+            }
+        }
+        if (plan.getRatifyUserId() != null) {
+            User ratifyUser = userMapper.selectById(plan.getRatifyUserId());
+            if (ratifyUser != null) {
+                planDto.setRatifyName(ratifyUser.getName());
+            }
+        }
+        return planDto;
+    }
+
+    /**
+     * 璁惧妗f鍙樻洿鍚庯紝鎶婅澶囧悓姝ュ埌瀵瑰簲骞翠唤鐨勮澶囨牳鏌ヨ鍒掓槑缁�
+     */
+    @Override
+    public void syncDeviceExamineDetail(Device device) {
+        LocalDate remind = calcExamineRemindDate(device);
+        if (remind == null || remind.isAfter(LocalDate.now())) {
+            return;
+        }
+        DeviceExaminePlan plan = getOrCreatePlanEntity(String.valueOf(remind.getYear()));
+        fillExamineDetailIfAbsent(plan, device);
+    }
+
+    /**
+     * 澶嶆牳閫氳繃鍚庯紝鎶婅澶囨。妗堢殑鏈�杩�/涓嬫鏍告煡鏃ユ湡婊氬姩鍒版湰杞�
+     */
+    @Override
+    public void updateDeviceExamineDate(Integer planDetailsId) {
+        DeviceExaminePlanDetails detail = deviceExaminePlanDetailsMapper.selectById(planDetailsId);
+        if (detail == null || detail.getDeviceId() == null) {
+            return;
+        }
+        Device device = deviceMapper.selectById(detail.getDeviceId());
+        if (device == null) {
+            return;
+        }
+        LocalDate checkDate = parseCheckDate(detail.getCheckTime());
+        if (checkDate.isAfter(LocalDate.now())) {
+            checkDate = LocalDate.now();
+        }
+        LocalDateTime checkDateTime = checkDate.atStartOfDay();
+        // 鍙厑璁稿悜鍓嶆粴鍔紝閬垮厤閲嶅澶嶆牳鏃ц褰曟椂鎶婃棩鏈熸敼鍥炲幓
+        if (device.getLastExamineDate() != null && !checkDateTime.isAfter(device.getLastExamineDate())) {
+            return;
+        }
+        device.setLastExamineDate(checkDateTime);
+        if (StringUtils.isNotBlank(device.getExamineCycle())) {
+            try {
+                device.setNextExamineDate(checkDateTime.plusMonths(Long.parseLong(device.getExamineCycle().trim())));
+            } catch (NumberFormatException ignored) {
+            }
+        }
+        deviceMapper.updateById(device);
+    }
+
+    /**
+     * 鏌ヨ骞翠唤瀵瑰簲鐨勮鍒掞紝涓嶅瓨鍦ㄥ垯鍒涘缓
+     */
+    private DeviceExaminePlan getOrCreatePlanEntity(String planYear) {
+        DeviceExaminePlan plan = baseMapper.selectOne(Wrappers.<DeviceExaminePlan>lambdaQuery()
+                .eq(DeviceExaminePlan::getPlanYear, planYear)
+                .orderByDesc(DeviceExaminePlan::getPlanId)
+                .last("limit 1"));
+        if (plan == null) {
+            plan = new DeviceExaminePlan();
+            plan.setPlanName(planYear + "骞村害璁惧鏍告煡璁″垝");
+            plan.setPlanYear(planYear);
+            plan.setWriteUserId(SecurityUtils.getUserId().intValue());
+            plan.setWriteTime(LocalDateTime.now());
+            baseMapper.insert(plan);
+        }
+        return plan;
+    }
+
+    /**
+     * 鎵弿鎵�鏈夎澶囷紝鎶婂凡鍒扮偣锛堜笅娆℃牳鏌ユ棩鏈熷墠1涓湀璧凤紝鍚凡杩囨湡锛夌殑璁惧琛ヨ繘鏈勾搴﹁鍒�
+     */
+    private void ensureExamineDetails(DeviceExaminePlan plan) {
+        List<Device> devices = deviceMapper.selectList(null);
+        for (Device device : devices) {
+            fillExamineDetailIfAbsent(plan, device);
+        }
+    }
+
+    /**
+     * 璁惧鎻愰啋璧风偣锛氫笅娆℃牳鏌ユ棩鏈熷墠1涓湀锛堟病濉笅娆℃棩鏈熸椂鐢ㄦ渶杩戞棩鏈�+鏍告煡鍛ㄦ湡鍏滃簳锛�
+     */
+    private LocalDate calcExamineRemindDate(Device device) {
+        LocalDateTime base = device.getNextExamineDate();
+        if (base == null && device.getLastExamineDate() != null && StringUtils.isNotBlank(device.getExamineCycle())) {
+            try {
+                base = device.getLastExamineDate().plusMonths(Long.parseLong(device.getExamineCycle().trim()));
+            } catch (NumberFormatException ignored) {
+            }
+        }
+        return base == null ? null : base.toLocalDate().minusMonths(1);
+    }
+
+    /**
+     * 宸插埌鐐逛笖璁″垝涓皻鏃犺璁惧鏈疆鏄庣粏鏃惰嚜鍔ㄨˉ涓�鏉�
+     */
+    private void fillExamineDetailIfAbsent(DeviceExaminePlan plan, Device device) {
+        LocalDate remind = calcExamineRemindDate(device);
+        if (remind == null || remind.isAfter(LocalDate.now())) {
+            return;
+        }
+        if (plan.getPlanYear() != null && String.valueOf(remind.getYear()).compareTo(plan.getPlanYear()) > 0) {
+            return;
+        }
+        String checkTime = remind.format(DateTimeFormatter.ofPattern("yyyy-MM"));
+        Long exist = deviceExaminePlanDetailsMapper.selectCount(Wrappers.<DeviceExaminePlanDetails>lambdaQuery()
+                .eq(DeviceExaminePlanDetails::getPlanId, plan.getPlanId())
+                .eq(DeviceExaminePlanDetails::getDeviceId, device.getId())
+                .likeRight(DeviceExaminePlanDetails::getCheckTime, checkTime));
+        if (exist != null && exist > 0) {
+            return;
+        }
+        DeviceExaminePlanDetails detail = new DeviceExaminePlanDetails();
+        detail.setPlanId(plan.getPlanId());
+        detail.setDeviceId(device.getId());
+        String deviceName = device.getDeviceName() == null ? "" : device.getDeviceName();
+        if (StringUtils.isNotBlank(device.getSpecificationModel())) {
+            deviceName = deviceName + " " + device.getSpecificationModel();
+        }
+        detail.setDeviceName(deviceName);
+        detail.setDeviceNumber(device.getManagementNumber());
+        detail.setCheckTime(checkTime);
+        deviceExaminePlanDetailsMapper.insert(detail);
+    }
+
+    /**
+     * 璁″垝鏄庣粏鐨勬牳鏌ユ椂闂村彲鑳芥槸 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();
+    }
 }

--
Gitblit v1.9.3