diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/dispatch/UserDispatchStatusService.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/dispatch/UserDispatchStatusService.java
index bd3059f..30ede0f 100644
--- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/dispatch/UserDispatchStatusService.java
+++ b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/dispatch/UserDispatchStatusService.java
@@ -151,4 +151,14 @@ public interface UserDispatchStatusService {
* @return 活跃工单数,无记录返回 0
*/
int getActiveOrderCount(Long userId);
+
+ /**
+ * 启动校准:从 DB 重建人员调度状态
+ *
+ * 扫描 Redis 中所有 ops:user:dispatch:* key,校验 currentOrderId 对应的工单是否仍在进行中,
+ * 并根据 DB 中实际活跃工单数修正 activeOrderCount / waitingTaskCount / status。
+ *
+ * @return 校准的用户数
+ */
+ int calibrateFromDb();
}
diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/dispatch/UserDispatchStatusServiceImpl.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/dispatch/UserDispatchStatusServiceImpl.java
index 4529cfb..9546a49 100644
--- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/dispatch/UserDispatchStatusServiceImpl.java
+++ b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/dispatch/UserDispatchStatusServiceImpl.java
@@ -1,6 +1,9 @@
package com.viewsh.module.ops.service.dispatch;
import com.viewsh.module.ops.api.dispatch.UserDispatchStatusDTO;
+import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO;
+import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper;
+import com.viewsh.module.ops.enums.WorkOrderStatusEnum;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@@ -9,6 +12,7 @@ import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import java.util.*;
+import java.util.stream.Collectors;
/**
* 通用人员调度状态服务 - Redis 实现
@@ -31,6 +35,9 @@ public class UserDispatchStatusServiceImpl implements UserDispatchStatusService
@Resource
private StringRedisTemplate stringRedisTemplate;
+ @Resource
+ private OpsOrderMapper opsOrderMapper;
+
// ==================== Lua 脚本 ====================
private DefaultRedisScript dispatchScript;
@@ -297,6 +304,107 @@ public class UserDispatchStatusServiceImpl implements UserDispatchStatusService
}
}
+ // ==================== 启动校准 ====================
+
+ @Override
+ public int calibrateFromDb() {
+ // 1. SCAN 所有 user dispatch key
+ Set keys = stringRedisTemplate.keys(KEY_PREFIX + "*");
+ if (keys == null || keys.isEmpty()) {
+ return 0;
+ }
+
+ int calibrated = 0;
+
+ for (String key : keys) {
+ try {
+ String userIdStr = key.substring(KEY_PREFIX.length());
+ Long userId = Long.parseLong(userIdStr);
+
+ // 2. 查 DB:该用户所有非终态、非保洁的活跃工单
+ List activeOrders = opsOrderMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper()
+ .eq(OpsOrderDO::getAssigneeId, userId)
+ .ne(OpsOrderDO::getOrderType, "CLEAN")
+ .notIn(OpsOrderDO::getStatus,
+ WorkOrderStatusEnum.COMPLETED.getStatus(),
+ WorkOrderStatusEnum.CANCELLED.getStatus())
+ );
+
+ if (activeOrders.isEmpty()) {
+ // 无活跃工单,但 Redis 中有记录 → 应该是 IDLE
+ Map