feat(ops): 工牌设备状态服务支持 nickname 透传

在工牌设备状态管理链路中全面支持 nickname 字段透传,从 IoT 事件接收到派单策略推荐均使用用户可读的昵称。

变更范围:
- IotDeviceStatusChangedEventDTO: 新增 nickname 字段
- BadgeDeviceStatusEventHandler: 接收并透传 nickname
- BadgeDeviceStatusService/Impl: updateBadgeOnlineStatus 增加 nickname 参数
- BadgeDeviceStatusSyncJob: 对账场景保留 Redis 已有 nickname
- BadgeDeviceAreaAssignStrategy: 推荐执行人时优先使用 nickname
- BadgeDeviceDispatchTest: 测试适配 nickname 参数

影响模块:Ops Environment Biz

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
lzh
2026-02-02 22:30:06 +08:00
parent b4fad17254
commit bccf992848
7 changed files with 25 additions and 6 deletions

View File

@@ -111,18 +111,20 @@ public class BadgeDeviceStatusEventHandler implements RocketMQListener<String> {
private void handleDeviceStatusChange(IotDeviceStatusChangedEventDTO event) {
Long deviceId = event.getDeviceId();
String deviceCode = event.getDeviceName();
String nickname = event.getNickname();
// 获取设备所属区域
Long areaId = getAreaIdByDeviceId(deviceId);
if (event.isOnline()) {
// 设备上线
log.info("[BadgeDeviceStatusEventHandler] 工牌设备上线: deviceId={}, deviceCode={}, areaId={}",
deviceId, deviceCode, areaId);
log.info("[BadgeDeviceStatusEventHandler] 工牌设备上线: deviceId={}, deviceCode={}, nickname={}, areaId={}",
deviceId, deviceCode, nickname, areaId);
badgeDeviceStatusService.updateBadgeOnlineStatus(
deviceId,
deviceCode,
nickname,
areaId,
BadgeDeviceStatusEnum.IDLE,
"设备上线");
@@ -135,6 +137,7 @@ public class BadgeDeviceStatusEventHandler implements RocketMQListener<String> {
badgeDeviceStatusService.updateBadgeOnlineStatus(
deviceId,
deviceCode,
nickname,
null,
BadgeDeviceStatusEnum.OFFLINE,
"设备离线");

View File

@@ -36,6 +36,11 @@ public class IotDeviceStatusChangedEventDTO {
*/
private String deviceName;
/**
* 设备昵称nickname用户可读的显示名称
*/
private String nickname;
/**
* 产品ID
*/

View File

@@ -160,6 +160,7 @@ public class BadgeDeviceStatusSyncJob {
badgeDeviceStatusService.updateBadgeOnlineStatus(
deviceId,
iotStatus.getDeviceCode(),
null, // nickname: 对账场景不更新昵称保留Redis中已有值
areaId,
BadgeDeviceStatusEnum.IDLE,
"定时对账修正-上线");
@@ -169,6 +170,7 @@ public class BadgeDeviceStatusSyncJob {
badgeDeviceStatusService.updateBadgeOnlineStatus(
deviceId,
iotStatus.getDeviceCode(),
null, // nickname: 对账场景不更新昵称保留Redis中已有值
null,
BadgeDeviceStatusEnum.OFFLINE,
"定时对账修正-离线");

View File

@@ -104,11 +104,12 @@ public interface BadgeDeviceStatusService {
*
* @param deviceId 设备ID
* @param deviceCode 设备编码
* @param nickname 设备昵称(用户可读的显示名称)
* @param areaId 区域ID可为null
* @param status 目标状态IDLE 或 OFFLINE
* @param reason 状态变更原因
*/
void updateBadgeOnlineStatus(Long deviceId, String deviceCode, Long areaId,
void updateBadgeOnlineStatus(Long deviceId, String deviceCode, String nickname, Long areaId,
BadgeDeviceStatusEnum status, String reason);
// ==================== 在线状态检查 ====================

View File

@@ -235,7 +235,7 @@ public class BadgeDeviceStatusServiceImpl implements BadgeDeviceStatusService, I
// ==================== 状态更新 (IoT 事件驱动) ====================
@Override
public void updateBadgeOnlineStatus(Long deviceId, String deviceCode, Long areaId,
public void updateBadgeOnlineStatus(Long deviceId, String deviceCode, String nickname, Long areaId,
BadgeDeviceStatusEnum status, String reason) {
if (deviceId == null || status == null) {
return;
@@ -271,6 +271,7 @@ public class BadgeDeviceStatusServiceImpl implements BadgeDeviceStatusService, I
Map<String, Object> statusMap = new HashMap<>();
statusMap.put("deviceId", deviceId);
statusMap.put("deviceCode", deviceCode != null ? deviceCode : currentMap.get("deviceCode"));
statusMap.put("nickname", nickname != null ? nickname : currentMap.get("nickname"));
statusMap.put("status", status.getCode());
statusMap.put("statusChangeTime", LocalDateTime.now().toString());
statusMap.put("statusChangeReason", reason);
@@ -529,6 +530,7 @@ public class BadgeDeviceStatusServiceImpl implements BadgeDeviceStatusService, I
dto.setDeviceId(getLong(map.get("deviceId")));
dto.setDeviceCode((String) map.get("deviceCode"));
dto.setNickname((String) map.get("nickname"));
String statusStr = (String) map.get("status");
dto.setStatus(BadgeDeviceStatusEnum.fromCode(statusStr));

View File

@@ -89,9 +89,11 @@ public class BadgeDeviceAreaAssignStrategy implements AssignStrategy {
if (selectedDevice != null) {
String reason = buildRecommendationReason(selectedDevice, context);
String assigneeName = selectedDevice.getNickname() != null
? selectedDevice.getNickname() : selectedDevice.getDeviceCode();
return AssigneeRecommendation.of(
selectedDevice.getDeviceId(),
selectedDevice.getDeviceCode(),
assigneeName,
calculateScore(selectedDevice),
reason
);
@@ -116,9 +118,11 @@ public class BadgeDeviceAreaAssignStrategy implements AssignStrategy {
.map(device -> {
int score = calculateScore(device);
String reason = buildRecommendationReason(device, context);
String assigneeName = device.getNickname() != null
? device.getNickname() : device.getDeviceCode();
return AssigneeRecommendation.of(
device.getDeviceId(),
device.getDeviceCode(),
assigneeName,
score,
reason
);

View File

@@ -118,6 +118,7 @@ public class BadgeDeviceDispatchTest {
badgeDeviceStatusService.updateBadgeOnlineStatus(
TEST_DEVICE_ID,
TEST_DEVICE_CODE,
null,
TEST_AREA_ID,
BadgeDeviceStatusEnum.IDLE,
"测试心跳");
@@ -126,6 +127,7 @@ public class BadgeDeviceDispatchTest {
verify(badgeDeviceStatusService).updateBadgeOnlineStatus(
eq(TEST_DEVICE_ID),
eq(TEST_DEVICE_CODE),
isNull(),
eq(TEST_AREA_ID),
eq(BadgeDeviceStatusEnum.IDLE),
eq("测试心跳"));