Kaynağa Gözat

feat(national-motion-module-system): 添加删除过期访客功能并定时执行

- 实现了删除已过期访客的功能,包括查询用户信息、筛选过期访客、构造删除请求体并发送请求
- 在定时任务服务中添加了每天凌晨1点执行删除过期访客的任务
- 优化了代码结构,提高了错误处理能力和日志记录详细度
SheepHy 3 hafta önce
ebeveyn
işleme
0baf362a7b

+ 62 - 4
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/hikiot/HikiotTool.java

@@ -1,6 +1,8 @@
 package org.jeecg.modules.hikiot;
 
 import cn.hutool.core.date.LocalDateTimeUtil;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import org.jeecg.common.exception.JeecgBootException;
@@ -18,6 +20,7 @@ import java.nio.charset.StandardCharsets;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 
 import static com.alibaba.dashscope.utils.JsonUtils.gson;
@@ -293,8 +296,63 @@ public class HikiotTool {
      * @Description 删除已过期的访客
      * @Date 15:09 2025/8/15
      **/
-    public static String deleteExpiredVisitors(String deviceSerial){
-        return sendPostRequest(QUERY_USER_INFO_URL, gson.toJson(queryUserInfo(deviceSerial)),setHeaders());
+    public static String deleteExpiredVisitors(String deviceSerial) {
+        try {
+            // 1. 查询访客信息
+            String userInfoResponse = queryUserInfo(deviceSerial);
+            JsonObject responseJson = JsonParser.parseString(userInfoResponse).getAsJsonObject();
+
+            if (responseJson.get("code").getAsInt() != 0) {
+                throw new JeecgBootException("查询用户信息失败: " + responseJson.get("msg").getAsString());
+            }
+
+            // 2. 解析并筛选过期访客
+            List<String> expiredEmployees = new ArrayList<>();
+            LocalDateTime now = LocalDateTime.now();
+            JsonArray dataArray = responseJson.getAsJsonArray("data");
+
+            for (JsonElement element : dataArray) {
+                JsonObject user = element.getAsJsonObject();
+                JsonObject valid = user.getAsJsonObject("Valid");
+
+                // 解析时间字段
+                String endTimeStr = valid.get("endTime").getAsString();
+                LocalDateTime endTime = LocalDateTime.parse(endTimeStr, DateTimeFormatter.ISO_DATE_TIME);
+
+                // 判断是否过期
+                if (endTime.isBefore(now)) {
+                    expiredEmployees.add(user.get("employeeNo").getAsString());
+                }
+            }
+
+            // 3. 构造删除请求体
+            if (expiredEmployees.isEmpty()) {
+                return "无过期访客需要删除";
+            }
+
+            JsonObject requestJson = new JsonObject();
+            requestJson.addProperty("deviceSerial", deviceSerial);  // deviceSerial在顶层
+
+            // 创建payload对象
+            JsonObject payload = new JsonObject();
+            JsonArray userInfoArray = new JsonArray();
+
+            // 添加userInfo数组
+            for (String employeeNo : expiredEmployees) {
+                JsonObject userInfoItem = new JsonObject();
+                userInfoItem.addProperty("employeeNo", employeeNo);
+                userInfoArray.add(userInfoItem);
+            }
+
+            payload.add("userInfo", userInfoArray);
+            requestJson.add("payload", payload);  // payload作为顶层字段
+
+            // 4. 发送删除请求
+            return sendPostRequest(BATCH_DELETE_USER_URL, requestJson.toString(), setHeaders());
+
+        } catch (Exception e) {
+            throw new JeecgBootException("删除过期访客失败", e);
+        }
     }
 
     /** 
@@ -486,8 +544,8 @@ public class HikiotTool {
     }
 
     public static void main(String[] args) throws IOException, InterruptedException {
-        queryUserInfo("FX0889961");
-//        addUser(new Date(),"FX0889961","Sheep","1001");
+        deleteExpiredVisitors("FX0889961");
+//        addUser(new Date(),"FX0889961","Sheep123","10011");
 //        addFace("FX0889961","1001","https://national-motion.oss-cn-beijing.aliyuncs.com/opt/upFiles/tmp_81fc8aa195d37dac70fd57221d82845e_1756361097600.jpg");
 //        addUser();
 //        addUserPlanTemplate();

+ 52 - 4
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/quartz/job/OrTeachingJobService.java

@@ -12,10 +12,8 @@ import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.util.DateUtils;
 import org.jeecg.modules.quartz.utils.HolidayUtil;
 import org.jeecg.modules.system.app.dto.TeachingDayDTO;
-import org.jeecg.modules.system.app.entity.AppSite;
-import org.jeecg.modules.system.app.entity.AppSitePlace;
-import org.jeecg.modules.system.app.entity.AppSitePriceRules;
-import org.jeecg.modules.system.app.entity.AppTeachingTime;
+import org.jeecg.modules.system.app.entity.*;
+import org.jeecg.modules.system.app.mapper.AppDeviceMapper;
 import org.jeecg.modules.system.app.service.IAppSitePlaceService;
 import org.jeecg.modules.system.app.service.IAppSitePriceRulesService;
 import org.jeecg.modules.system.app.service.IAppSiteService;
@@ -24,6 +22,7 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.annotation.Resource;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -31,6 +30,8 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 
+import static org.jeecg.modules.hikiot.HikiotTool.deleteExpiredVisitors;
+
 /**
  * @author wzq
  * @date 2025/7/15 10:28
@@ -49,6 +50,9 @@ public class OrTeachingJobService {
 
     private final IAppSiteService appSiteService;
 
+    @Resource
+    private AppDeviceMapper appDeviceMapper;
+
     @Scheduled(cron = "0 0 0 1 12 *")
     @Transactional(rollbackFor = Exception.class)
     public void execute() throws ParseException {
@@ -163,4 +167,48 @@ public class OrTeachingJobService {
             appSitePriceRulesService.insertList(appSitePriceRulesList);
         }
     }
+
+    @Scheduled(cron = "0 0 1 * * ?")
+    public void deleteExpiredVisitorsExecute(){
+        try {
+            // 获取所有设备列表
+            List<AppDevice> deviceList = appDeviceMapper.selectList(null);
+            if (deviceList == null || deviceList.isEmpty()) {
+                log.warn("未找到需要处理的设备");
+                return;
+            }
+
+            // 定义休眠时间(毫秒)
+            final long SLEEP_TIME = 3000; // 5秒,可根据实际情况调整
+
+            // 遍历设备处理
+            for (AppDevice device : deviceList) {
+                try {
+                    String deviceSerial = device.getDeviceSerial();
+                    log.info("开始处理设备:{}", deviceSerial);
+
+                    // 执行删除操作
+                    String result = deleteExpiredVisitors(deviceSerial);
+                    log.info("设备 {} 处理完成,结果:{}", deviceSerial, result);
+
+                    // 最后一次处理后不休眠
+                    if (!device.equals(deviceList.get(deviceList.size() - 1))) {
+                        log.info("休眠 {} 毫秒...", SLEEP_TIME);
+                        Thread.sleep(SLEEP_TIME);
+                    }
+                } catch (InterruptedException e) {
+                    // 恢复中断状态
+                    Thread.currentThread().interrupt();
+                    log.error("设备 {} 处理过程中发生中断异常", device.getDeviceSerial(), e);
+                    break; // 中断后停止处理
+                } catch (Exception e) {
+                    log.error("设备 {} 处理失败", device.getDeviceSerial(), e);
+                    // 记录失败设备信息
+                    continue; // 继续处理其他设备
+                }
+            }
+        } catch (Exception e) {
+            log.error("获取设备列表失败", e);
+        }
+    }
 }