chore: 【ops】状态机实现/状态切换事件发布/保洁监听处理事件
This commit is contained in:
@@ -0,0 +1,603 @@
|
||||
package com.viewsh.module.ops.environment.handler;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import com.viewsh.module.ops.core.event.OrderCompletedEvent;
|
||||
import com.viewsh.module.ops.core.event.OrderCreatedEvent;
|
||||
import com.viewsh.module.ops.core.event.OrderStateChangedEvent;
|
||||
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderCleanExtDO;
|
||||
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO;
|
||||
import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderCleanExtMapper;
|
||||
import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper;
|
||||
import com.viewsh.module.ops.enums.WorkOrderStatusEnum;
|
||||
import com.viewsh.module.ops.environment.constants.CleanNotificationConstants;
|
||||
import com.viewsh.module.ops.environment.service.cleaner.CleanerStatusService;
|
||||
import com.viewsh.module.ops.environment.service.cleanorder.CleanOrderService;
|
||||
import com.viewsh.module.ops.environment.service.voice.VoiceBroadcastDeduplicationService;
|
||||
import com.viewsh.module.iot.api.device.IotDeviceControlApi;
|
||||
import com.viewsh.module.iot.api.device.dto.IotDeviceServiceInvokeReqDTO;
|
||||
import com.viewsh.module.system.api.notify.NotifyMessageSendApi;
|
||||
import com.viewsh.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 保洁工单事件处理器
|
||||
* <p>
|
||||
* 职责:
|
||||
* 1. 订阅工单状态变更事件,处理保洁业务特定逻辑
|
||||
* 2. 记录保洁扩展信息(到岗时间、完成时间、暂停时间等)
|
||||
* 3. 更新保洁员状态
|
||||
* 4. 发送通知(语音播报、站内信、IoT震动)
|
||||
* <p>
|
||||
* 设计说明:
|
||||
* - 使用 @EventListener 订阅领域事件
|
||||
* - 业务逻辑同步执行
|
||||
* - 通知逻辑异步执行(@Async)
|
||||
* - 消息内容使用 {@link CleanNotificationConstants} 统一管理
|
||||
* <p>
|
||||
* - 未来迁移 RocketMQ:只需修改 @EventListener 为 @RocketMQMessageListener
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class CleanOrderEventHandler {
|
||||
|
||||
@Resource
|
||||
private CleanerStatusService cleanerStatusService;
|
||||
|
||||
@Resource
|
||||
private OpsOrderCleanExtMapper cleanExtMapper;
|
||||
|
||||
@Resource
|
||||
private CleanOrderService cleanOrderService;
|
||||
|
||||
@Resource
|
||||
private OpsOrderMapper opsOrderMapper;
|
||||
|
||||
@Resource
|
||||
private VoiceBroadcastDeduplicationService voiceBroadcastDeduplicationService;
|
||||
|
||||
/**
|
||||
* 站内信发送 API(Feign 客户端,微服务架构下调用 system 服务)
|
||||
*/
|
||||
@Resource
|
||||
private NotifyMessageSendApi notifyMessageSendApi;
|
||||
|
||||
/**
|
||||
* IoT 设备控制 API(Feign 客户端,微服务架构下调用 IoT 服务)
|
||||
*/
|
||||
@Resource
|
||||
private IotDeviceControlApi iotDeviceControlApi;
|
||||
|
||||
/**
|
||||
* 订阅状态变更事件
|
||||
* <p>
|
||||
* 只处理保洁类型的工单(orderType = "CLEAN")
|
||||
*/
|
||||
@EventListener
|
||||
public void onStateChanged(OrderStateChangedEvent event) {
|
||||
// 只处理保洁类型的工单
|
||||
if (!"CLEAN".equals(event.getOrderType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("保洁工单状态变更: orderId={}, {} -> {}, operatorId={}",
|
||||
event.getOrderId(), event.getOldStatus(), event.getNewStatus(), event.getOperatorId());
|
||||
|
||||
switch (event.getNewStatus()) {
|
||||
case DISPATCHED:
|
||||
handleDispatched(event);
|
||||
break;
|
||||
case CONFIRMED:
|
||||
handleConfirmed(event);
|
||||
break;
|
||||
case ARRIVED:
|
||||
handleArrived(event);
|
||||
break;
|
||||
case PAUSED:
|
||||
handlePaused(event);
|
||||
break;
|
||||
case COMPLETED:
|
||||
handleCompleted(event);
|
||||
break;
|
||||
case CANCELLED:
|
||||
handleCancelled(event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅工单创建事件
|
||||
*/
|
||||
@EventListener
|
||||
public void onOrderCreated(OrderCreatedEvent event) {
|
||||
if (!"CLEAN".equals(event.getOrderType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("保洁工单已创建: orderId={}, orderCode={}, priority={}",
|
||||
event.getOrderId(), event.getOrderCode(), event.getPriority());
|
||||
|
||||
// 可以在这里触发自动派单逻辑
|
||||
// 但通常派单逻辑在工单创建时直接调用
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅工单完成事件
|
||||
*/
|
||||
@EventListener
|
||||
public void onOrderCompleted(OrderCompletedEvent event) {
|
||||
if (!"CLEAN".equals(event.getOrderType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("保洁工单已完成: orderId={}, assigneeId={}, workDuration={}秒",
|
||||
event.getOrderId(), event.getAssigneeId(), event.getWorkDuration());
|
||||
|
||||
// 自动推送下一个任务
|
||||
if (event.getAssigneeId() != null) {
|
||||
cleanOrderService.autoDispatchNextOrder(event.getOrderId(), event.getAssigneeId());
|
||||
}
|
||||
|
||||
// 发送完成通知(异步)
|
||||
sendOrderCompletedNotification(event.getOrderId());
|
||||
}
|
||||
|
||||
// ==================== 状态处理方法 ====================
|
||||
|
||||
/**
|
||||
* 处理已推送状态(工单已推送到工牌)
|
||||
*/
|
||||
private void handleDispatched(OrderStateChangedEvent event) {
|
||||
Long orderId = event.getOrderId();
|
||||
Long cleanerId = event.getOperatorId();
|
||||
|
||||
// 发送新工单通知(语音+震动+站内信)
|
||||
sendNewOrderNotification(cleanerId, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理已确认状态(保洁员按下确认按钮)
|
||||
*/
|
||||
private void handleConfirmed(OrderStateChangedEvent event) {
|
||||
Long cleanerId = event.getOperatorId();
|
||||
|
||||
// 更新保洁员状态为忙碌
|
||||
cleanerStatusService.updateStatus(cleanerId,
|
||||
com.viewsh.module.ops.enums.CleanerStatusEnum.BUSY,
|
||||
"确认工单");
|
||||
|
||||
log.info("保洁员已确认工单,状态更新为BUSY: cleanerId={}", cleanerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理到岗事件
|
||||
*/
|
||||
private void handleArrived(OrderStateChangedEvent event) {
|
||||
Long orderId = event.getOrderId();
|
||||
|
||||
// 1. 记录到岗时间到保洁扩展表
|
||||
OpsOrderCleanExtDO updateObj = new OpsOrderCleanExtDO();
|
||||
updateObj.setOpsOrderId(orderId);
|
||||
updateObj.setArrivedTime(LocalDateTime.now());
|
||||
cleanExtMapper.insertOnDuplicateKeyUpdate(updateObj);
|
||||
|
||||
log.info("保洁员已到岗: orderId={}", orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理暂停事件
|
||||
*/
|
||||
private void handlePaused(OrderStateChangedEvent event) {
|
||||
Long orderId = event.getOrderId();
|
||||
Long operatorId = event.getOperatorId();
|
||||
|
||||
// 检查是否是被P0任务打断
|
||||
String interruptReason = event.getPayloadString("interruptReason");
|
||||
if ("P0_TASK_INTERRUPT".equals(interruptReason)) {
|
||||
Long urgentOrderId = event.getPayloadLong("urgentOrderId");
|
||||
|
||||
log.warn("保洁任务被P0任务打断: orderId={}, urgentOrderId={}", orderId, urgentOrderId);
|
||||
|
||||
// 释放保洁员资源
|
||||
cleanerStatusService.clearCurrentWorkOrder(operatorId);
|
||||
|
||||
// 记录暂停开始时间
|
||||
recordPauseStartTime(orderId);
|
||||
} else {
|
||||
// 普通暂停
|
||||
log.info("保洁任务已暂停: orderId={}, operatorId={}", orderId, operatorId);
|
||||
recordPauseStartTime(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理完成事件
|
||||
*/
|
||||
private void handleCompleted(OrderStateChangedEvent event) {
|
||||
Long orderId = event.getOrderId();
|
||||
|
||||
// 计算作业时长
|
||||
Integer actualDuration = cleanOrderService.calculateActualDuration(orderId);
|
||||
log.info("保洁作业完成: orderId={}, actualDuration={}秒", orderId, actualDuration);
|
||||
|
||||
// 记录完成时间和时长到保洁扩展表
|
||||
OpsOrderCleanExtDO updateObj = new OpsOrderCleanExtDO();
|
||||
updateObj.setOpsOrderId(orderId);
|
||||
updateObj.setCompletedTime(LocalDateTime.now());
|
||||
cleanExtMapper.insertOnDuplicateKeyUpdate(updateObj);
|
||||
|
||||
// 保洁员状态恢复(由 autoDispatchNextOrder 处理)
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理取消事件
|
||||
*/
|
||||
private void handleCancelled(OrderStateChangedEvent event) {
|
||||
Long orderId = event.getOrderId();
|
||||
Long operatorId = event.getOperatorId();
|
||||
|
||||
log.info("保洁工单已取消: orderId={}, operatorId={}", orderId, operatorId);
|
||||
|
||||
// 清理保洁员当前工单
|
||||
if (operatorId != null) {
|
||||
cleanerStatusService.clearCurrentWorkOrder(operatorId);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 通知方法(异步)====================
|
||||
|
||||
/**
|
||||
* 发送新工单通知(语音播报 + 震动提醒 + 站内信)
|
||||
*
|
||||
* @param cleanerId 保洁员ID
|
||||
* @param orderId 工单ID
|
||||
*/
|
||||
@Async("ops-task-executor")
|
||||
public void sendNewOrderNotification(Long cleanerId, Long orderId) {
|
||||
try {
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
log.warn("[新工单通知] 工单不存在: orderId={}", orderId);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("[新工单通知] cleanerId={}, orderId={}", cleanerId, orderId);
|
||||
|
||||
// 1. 语音播报:使用常量
|
||||
playVoice(cleanerId, CleanNotificationConstants.VoiceMessage.NEW_ORDER);
|
||||
|
||||
// 2. 震动提醒:使用常量
|
||||
vibrate(cleanerId, CleanNotificationConstants.VibrationDuration.NORMAL);
|
||||
|
||||
// 3. 发送站内信
|
||||
sendNotifyMessageToMember(cleanerId,
|
||||
CleanNotificationConstants.TemplateCode.NEW_ORDER,
|
||||
CleanNotificationConstants.NotifyParamsBuilder.newOrderParams(
|
||||
order.getOrderCode(),
|
||||
order.getTitle(),
|
||||
getAreaName(order.getAreaId())
|
||||
));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[新工单通知] 发送失败: cleanerId={}, orderId={}", cleanerId, orderId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送待办增加通知(支持去重合并)
|
||||
*
|
||||
* @param cleanerId 保洁员ID
|
||||
* @param queueCount 当前待办数量
|
||||
*/
|
||||
@Async("ops-task-executor")
|
||||
public void sendQueuedOrderNotification(Long cleanerId, int queueCount) {
|
||||
try {
|
||||
log.info("[待办增加通知] cleanerId={}, queueCount={}", cleanerId, queueCount);
|
||||
|
||||
// 1. 使用去重服务合并播报
|
||||
voiceBroadcastDeduplicationService.recordAndBroadcast(cleanerId, 1, false);
|
||||
|
||||
// 2. 震动提醒(轻量震动):使用常量
|
||||
vibrate(cleanerId, CleanNotificationConstants.VibrationDuration.LIGHT);
|
||||
|
||||
// 3. 发送站内信(可选,避免频繁打扰)
|
||||
// 如果待办数量较多时才发送站内信
|
||||
if (queueCount >= 3) {
|
||||
sendNotifyMessageToMember(cleanerId,
|
||||
CleanNotificationConstants.TemplateCode.QUEUED_ORDER,
|
||||
CleanNotificationConstants.NotifyParamsBuilder.queuedOrderParams(queueCount, 1));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[待办增加通知] 发送失败: cleanerId={}", cleanerId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送下一个任务通知
|
||||
*
|
||||
* @param cleanerId 保洁员ID
|
||||
* @param queueCount 待办数量
|
||||
* @param orderTitle 任务标题
|
||||
*/
|
||||
@Async("ops-task-executor")
|
||||
public void sendNextTaskNotification(Long cleanerId, int queueCount, String orderTitle) {
|
||||
try {
|
||||
log.info("[下一任务通知] cleanerId={}, queueCount={}, title={}", cleanerId, queueCount, orderTitle);
|
||||
|
||||
// 1. 语音播报:使用常量类格式化
|
||||
String voiceMessage = CleanNotificationConstants.VoiceHelper.formatNextTask(queueCount, orderTitle);
|
||||
playVoice(cleanerId, voiceMessage);
|
||||
|
||||
// 2. 震动提醒:使用常量
|
||||
vibrate(cleanerId, CleanNotificationConstants.VibrationDuration.NORMAL);
|
||||
|
||||
// 3. 发送站内信
|
||||
sendNotifyMessageToMember(cleanerId,
|
||||
CleanNotificationConstants.TemplateCode.NEXT_TASK,
|
||||
CleanNotificationConstants.NotifyParamsBuilder.nextTaskParams(queueCount, orderTitle));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[下一任务通知] 发送失败: cleanerId={}", cleanerId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送P0紧急任务插队通知
|
||||
*
|
||||
* @param cleanerId 保洁员ID
|
||||
* @param orderCode 工单编号
|
||||
*/
|
||||
@Async("ops-task-executor")
|
||||
public void sendPriorityUpgradeNotification(Long cleanerId, String orderCode) {
|
||||
try {
|
||||
log.warn("[P0紧急通知] cleanerId={}, orderCode={}", cleanerId, orderCode);
|
||||
|
||||
// 1. 语音播报:使用常量类格式化
|
||||
String voiceMessage = CleanNotificationConstants.VoiceHelper.formatPriorityUpgrade(orderCode);
|
||||
playVoice(cleanerId, voiceMessage);
|
||||
|
||||
// 2. 强烈震动提醒:使用常量
|
||||
vibrate(cleanerId, CleanNotificationConstants.VibrationDuration.STRONG);
|
||||
|
||||
// 3. 发送站内信(高优先级)
|
||||
sendNotifyMessageToMember(cleanerId,
|
||||
CleanNotificationConstants.TemplateCode.PRIORITY_UPGRADE,
|
||||
CleanNotificationConstants.NotifyParamsBuilder.priorityUpgradeParams(orderCode, "P0紧急任务"));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[P0紧急通知] 发送失败: cleanerId={}", cleanerId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送任务恢复通知
|
||||
*
|
||||
* @param cleanerId 保洁员ID
|
||||
* @param areaName 区域名称
|
||||
*/
|
||||
@Async("ops-task-executor")
|
||||
public void sendTaskResumedNotification(Long cleanerId, String areaName) {
|
||||
try {
|
||||
log.info("[任务恢复通知] cleanerId={}, areaName={}", cleanerId, areaName);
|
||||
|
||||
// 1. 语音播报:使用常量类格式化
|
||||
String voiceMessage = CleanNotificationConstants.VoiceHelper.formatTaskResumed(areaName);
|
||||
playVoice(cleanerId, voiceMessage);
|
||||
|
||||
// 2. 震动提醒:使用常量
|
||||
vibrate(cleanerId, CleanNotificationConstants.VibrationDuration.NORMAL);
|
||||
|
||||
// 3. 发送站内信
|
||||
sendNotifyMessageToMember(cleanerId,
|
||||
CleanNotificationConstants.TemplateCode.TASK_RESUMED,
|
||||
CleanNotificationConstants.NotifyParamsBuilder.taskResumedParams(areaName));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[任务恢复通知] 发送失败: cleanerId={}", cleanerId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送工单完成通知(通知巡检员验收)
|
||||
*
|
||||
* @param orderId 工单ID
|
||||
*/
|
||||
@Async("ops-task-executor")
|
||||
public void sendOrderCompletedNotification(Long orderId) {
|
||||
try {
|
||||
OpsOrderDO order = opsOrderMapper.selectById(orderId);
|
||||
if (order == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("[工单完成通知] orderId={}, orderCode={}, areaId={}",
|
||||
orderId, order.getOrderCode(), order.getAreaId());
|
||||
|
||||
// TODO: 查询该区域的巡检员列表
|
||||
// List<Long> inspectorIds = inspectorService.listInspectorsByArea(order.getAreaId());
|
||||
// for (Long inspectorId : inspectorIds) {
|
||||
// // 发送站内信给巡检员
|
||||
// sendNotifyMessageToAdmin(inspectorId,
|
||||
// CleanNotificationConstants.TemplateCode.ORDER_COMPLETED,
|
||||
// CleanNotificationConstants.NotifyParamsBuilder.orderCompletedParams(
|
||||
// order.getOrderCode(), getAreaName(order.getAreaId()), order.getTitle()));
|
||||
// }
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[工单完成通知] 发送失败: orderId={}", orderId, e);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== IoT 设备操作方法 ====================
|
||||
|
||||
/**
|
||||
* 语音播报
|
||||
* <p>
|
||||
* 通过 RPC 调用 IoT 服务的设备控制接口
|
||||
*
|
||||
* @param cleanerId 保洁员ID
|
||||
* @param message 播报内容
|
||||
*/
|
||||
private void playVoice(Long cleanerId, String message) {
|
||||
try {
|
||||
// 获取保洁员关联的工牌设备ID
|
||||
Long deviceId = getBadgeDeviceId(cleanerId);
|
||||
if (deviceId == null) {
|
||||
log.warn("[语音播报] 保洁员无关联工牌设备: cleanerId={}", cleanerId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建服务调用请求
|
||||
IotDeviceServiceInvokeReqDTO reqDTO = new IotDeviceServiceInvokeReqDTO();
|
||||
reqDTO.setDeviceId(deviceId);
|
||||
reqDTO.setIdentifier("playVoice");
|
||||
reqDTO.setParams(MapUtil.<String, Object>builder()
|
||||
.put("text", message)
|
||||
.put("volume", 80)
|
||||
.build());
|
||||
|
||||
// 调用 IoT 服务
|
||||
iotDeviceControlApi.invokeService(reqDTO);
|
||||
log.info("[语音播报] 调用成功: cleanerId={}, deviceId={}, message={}", cleanerId, deviceId, message);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[语音播报] 调用失败: cleanerId={}, message={}", cleanerId, message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 震动提醒
|
||||
* <p>
|
||||
* 通过 RPC 调用 IoT 服务的设备控制接口
|
||||
*
|
||||
* @param cleanerId 保洁员ID
|
||||
* @param durationMs 震动时长(毫秒)
|
||||
*/
|
||||
private void vibrate(Long cleanerId, int durationMs) {
|
||||
try {
|
||||
// 获取保洁员关联的工牌设备ID
|
||||
Long deviceId = getBadgeDeviceId(cleanerId);
|
||||
if (deviceId == null) {
|
||||
log.warn("[震动提醒] 保洁员无关联工牌设备: cleanerId={}", cleanerId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建服务调用请求
|
||||
IotDeviceServiceInvokeReqDTO reqDTO = new IotDeviceServiceInvokeReqDTO();
|
||||
reqDTO.setDeviceId(deviceId);
|
||||
reqDTO.setIdentifier("vibrate");
|
||||
reqDTO.setParams(MapUtil.<String, Object>builder()
|
||||
.put("duration", durationMs)
|
||||
.put("intensity", 50)
|
||||
.build());
|
||||
|
||||
// 调用 IoT 服务
|
||||
iotDeviceControlApi.invokeService(reqDTO);
|
||||
log.info("[震动提醒] 调用成功: cleanerId={}, deviceId={}, durationMs={}", cleanerId, deviceId, durationMs);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[震动提醒] 调用失败: cleanerId={}, durationMs={}", cleanerId, durationMs, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取保洁员关联的工牌设备ID
|
||||
* <p>
|
||||
* TODO: 需要根据实际业务逻辑实现
|
||||
* - 方案1:在保洁员表维护关联的设备ID
|
||||
* - 方案2:通过用户ID查询设备表(设备表有userId字段)
|
||||
* - 方案3:通过中间表维护保洁员与设备的关系
|
||||
*
|
||||
* @param cleanerId 保洁员ID
|
||||
* @return 工牌设备ID,无关联返回null
|
||||
*/
|
||||
private Long getBadgeDeviceId(Long cleanerId) {
|
||||
// TODO: 实现获取保洁员关联的工牌设备ID
|
||||
// 当前返回null,实际使用时需要实现具体逻辑
|
||||
// 示例:
|
||||
// OpsCleanerDeviceDO device = cleanerDeviceMapper.selectByCleanerId(cleanerId);
|
||||
// return device != null ? device.getDeviceId() : null;
|
||||
|
||||
log.debug("[getBadgeDeviceId] 查询保洁员设备: cleanerId={}", cleanerId);
|
||||
return null;
|
||||
}
|
||||
|
||||
// ==================== 站内信发送方法 ====================
|
||||
|
||||
/**
|
||||
* 发送站内信给 Member 用户(保洁员)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param templateCode 模板代码
|
||||
* @param templateParams 模板参数
|
||||
*/
|
||||
private void sendNotifyMessageToMember(Long userId, String templateCode,
|
||||
java.util.Map<String, Object> templateParams) {
|
||||
try {
|
||||
NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO();
|
||||
reqDTO.setUserId(userId);
|
||||
reqDTO.setTemplateCode(templateCode);
|
||||
reqDTO.setTemplateParams(templateParams);
|
||||
|
||||
notifyMessageSendApi.sendSingleMessageToMember(reqDTO);
|
||||
log.info("[站内信发送成功] userId={}, templateCode={}", userId, templateCode);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[站内信发送失败] userId={}, templateCode={}", userId, templateCode, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送站内信给 Admin 用户(巡检员)
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param templateCode 模板代码
|
||||
* @param templateParams 模板参数
|
||||
*/
|
||||
private void sendNotifyMessageToAdmin(Long userId, String templateCode,
|
||||
java.util.Map<String, Object> templateParams) {
|
||||
try {
|
||||
NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO();
|
||||
reqDTO.setUserId(userId);
|
||||
reqDTO.setTemplateCode(templateCode);
|
||||
reqDTO.setTemplateParams(templateParams);
|
||||
|
||||
notifyMessageSendApi.sendSingleMessageToAdmin(reqDTO);
|
||||
log.info("[站内信发送成功] userId={}, templateCode={}", userId, templateCode);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[站内信发送失败] userId={}, templateCode={}", userId, templateCode, e);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 辅助方法 ====================
|
||||
|
||||
/**
|
||||
* 获取区域名称
|
||||
*/
|
||||
private String getAreaName(Long areaId) {
|
||||
// TODO: 从区域服务获取区域名称
|
||||
return "某区域";
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录暂停开始时间
|
||||
*/
|
||||
private void recordPauseStartTime(Long orderId) {
|
||||
OpsOrderCleanExtDO updateObj = new OpsOrderCleanExtDO();
|
||||
updateObj.setOpsOrderId(orderId);
|
||||
updateObj.setPauseStartTime(LocalDateTime.now());
|
||||
cleanExtMapper.insertOnDuplicateKeyUpdate(updateObj);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user