feat(ops): 新增通用人员调度状态服务 UserDispatchStatusService
基于 Redis Hash 维护人员维度的调度状态,供安保/工程/客服业务线共用。
与保洁的 BadgeDeviceStatusService(设备维度)并行。
核心设计:
- Redis Key: ops:user:dispatch:{userId},存储 status/activeOrderCount/waitingTaskCount 等
- 所有写操作使用 Lua 脚本原子执行,保证多业务线并发安全
- 事件监听器 @EventListener(事务内同步)自动排除 CLEAN 类型
- Redis 丢数据时降级为 IDLE,下一次事件自动重建(自愈)
新增文件:
- UserDispatchStatusDTO (ops-api)
- UserDispatchStatusService 接口 (ops-biz)
- UserDispatchStatusServiceImpl - Lua 脚本实现 (ops-biz)
- UserDispatchStatusEventListener - 通用事件监听 (ops-biz)
- UserAssigneeStatusAdapter - AssigneeStatus 适配器 (ops-biz)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
package com.viewsh.module.ops.api.dispatch;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 人员调度状态 DTO
|
||||
* <p>
|
||||
* 对应 Redis Hash: ops:user:dispatch:{userId}
|
||||
* <p>
|
||||
* 适用于安保、工程、客服等人员维度的业务线。
|
||||
* 保洁使用设备维度的 {@code BadgeDeviceStatusDTO}。
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserDispatchStatusDTO {
|
||||
|
||||
/**
|
||||
* 人员ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 调度状态:IDLE / BUSY / PAUSED
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 当前执行中的工单ID(DISPATCHED/CONFIRMED/ARRIVED 状态)
|
||||
*/
|
||||
private Long currentOrderId;
|
||||
|
||||
/**
|
||||
* 当前工单类型(SECURITY / REPAIR / SERVICE)
|
||||
*/
|
||||
private String currentOrderType;
|
||||
|
||||
/**
|
||||
* 当前工单状态(DISPATCHED / CONFIRMED / ARRIVED)
|
||||
*/
|
||||
private String currentOrderStatus;
|
||||
|
||||
/**
|
||||
* 活跃工单总数(含直接派单 + 排队中,不依赖队列记录)
|
||||
*/
|
||||
private Integer activeOrderCount;
|
||||
|
||||
/**
|
||||
* 队列中 WAITING 状态的任务数
|
||||
*/
|
||||
private Integer waitingTaskCount;
|
||||
|
||||
/**
|
||||
* 最后更新时间戳(毫秒)
|
||||
*/
|
||||
private Long lastUpdateTime;
|
||||
|
||||
public boolean isIdle() {
|
||||
return "IDLE".equals(status) || status == null;
|
||||
}
|
||||
|
||||
public boolean isBusy() {
|
||||
return "BUSY".equals(status);
|
||||
}
|
||||
|
||||
public boolean isPaused() {
|
||||
return "PAUSED".equals(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取活跃工单数(null 安全)
|
||||
*/
|
||||
public int getActiveOrderCountSafe() {
|
||||
return activeOrderCount != null ? activeOrderCount : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取等待任务数(null 安全)
|
||||
*/
|
||||
public int getWaitingTaskCountSafe() {
|
||||
return waitingTaskCount != null ? waitingTaskCount : 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user