chore: 【ops】保洁员状态Service

This commit is contained in:
lzh
2026-01-06 10:52:57 +08:00
parent c07f864f7e
commit 2e28183b39
2 changed files with 312 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
package com.viewsh.module.ops.environment.service.cleaner;
import com.viewsh.module.ops.dal.dataobject.cleaner.OpsCleanerStatusDO;
import com.viewsh.module.ops.enums.CleanerStatusEnum;
import java.util.List;
/**
* 保洁员状态服务
* 属于保洁业务特定逻辑,放在 environment-biz 模块中
*
* @author lzh
*/
public interface CleanerStatusService {
/**
* 根据设备ID查询保洁员状态
*
* @param deviceId 设备ID
* @return 保洁员状态
*/
OpsCleanerStatusDO getByDeviceId(Long deviceId);
/**
* 处理设备离线
* 当IoT设备离线时调用由IoT模块的消息总线触发
*
* @param deviceId 设备ID
* @param reason 离线原因
*/
void handleDeviceOffline(Long deviceId, String reason);
/**
* 处理设备上线
* 当IoT设备上线时调用由IoT模块的消息总线触发
*
* @param deviceId 设备ID
*/
void handleDeviceOnline(Long deviceId);
/**
* 更新保洁员业务状态
* 用于业务逻辑更新(如接单、完成工单等)
*
* @param userId 保洁员ID
* @param newStatus 新状态
* @param remark 备注
*/
void updateStatus(Long userId, CleanerStatusEnum newStatus, String remark);
/**
* 更新保洁员当前所在区域
*
* @param userId 保洁员ID
* @param areaId 区域ID
* @param areaName 区域名称
*/
void updateCurrentArea(Long userId, Long areaId, String areaName);
/**
* 查询指定区域的保洁员列表
*
* @param areaId 区域ID
* @return 保洁员列表
*/
List<OpsCleanerStatusDO> listCleanersByArea(Long areaId);
/**
* 查询可接单的保洁员IDLE状态
*
* @param areaId 区域ID
* @return 可接单的保洁员列表
*/
List<OpsCleanerStatusDO> listAvailableCleaners(Long areaId);
/**
* 查询附近的保洁员(基于区域)
*
* @param areaId 区域ID
* @param radius 半径(米)
* @return 附近保洁员列表
*/
List<OpsCleanerStatusDO> findNearbyCleaners(Long areaId, Integer radius);
/**
* 检查保洁员是否在线
*
* @param userId 保洁员ID
* @return 是否在线
*/
boolean isOnline(Long userId);
/**
* 获取保洁员当前状态
*
* @param userId 保洁员ID
* @return 保洁员状态
*/
OpsCleanerStatusDO getStatus(Long userId);
/**
* 设置当前工单
* 当保洁员接单时调用
*
* @param userId 保洁员ID
* @param opsOrderId 工单ID
* @param opsOrderCode 工单编号
*/
void setCurrentWorkOrder(Long userId, Long opsOrderId, String opsOrderCode);
/**
* 清除当前工单
* 当工单完成或取消时调用
*
* @param userId 保洁员ID
*/
void clearCurrentWorkOrder(Long userId);
}

View File

@@ -0,0 +1,194 @@
package com.viewsh.module.ops.environment.service.cleaner;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.viewsh.module.ops.dal.dataobject.cleaner.OpsCleanerStatusDO;
import com.viewsh.module.ops.dal.mysql.cleaner.OpsCleanerStatusMapper;
import com.viewsh.module.ops.enums.CleanerStatusEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
/**
* 保洁员状态服务实现
* 属于保洁业务特定逻辑,放在 environment-biz 模块中
*
* @author lzh
*/
@Service
@Slf4j
public class CleanerStatusServiceImpl implements CleanerStatusService {
@Resource
private OpsCleanerStatusMapper cleanerStatusMapper;
@Override
public OpsCleanerStatusDO getByDeviceId(Long deviceId) {
return cleanerStatusMapper.selectByDeviceId(deviceId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void handleDeviceOffline(Long deviceId, String reason) {
// 1. 根据设备ID查询保洁员
OpsCleanerStatusDO cleaner = getByDeviceId(deviceId);
if (cleaner == null) {
log.warn("设备未关联保洁员,忽略离线事件: deviceId={}", deviceId);
return;
}
// 2. 如果保洁员已经是OFFLINE状态则跳过
if (CleanerStatusEnum.OFFLINE.getCode().equals(cleaner.getStatus())) {
log.debug("保洁员已是OFFLINE状态无需更新: userId={}, deviceId={}",
cleaner.getUserId(), deviceId);
return;
}
// 3. 更新保洁员状态为OFFLINE
cleaner.setStatusEnum(CleanerStatusEnum.OFFLINE);
cleaner.setOfflineReason(reason);
cleaner.setStatusChangeTime(LocalDateTime.now());
cleaner.setLastDeviceSyncTime(LocalDateTime.now());
cleanerStatusMapper.updateById(cleaner);
// 4. 如果保洁员正在执行工单,需要记录日志
if (cleaner.getCurrentOpsOrderId() != null) {
log.warn("保洁员设备离线,正在执行的工单可能需要暂停: userId={}, orderId={}",
cleaner.getUserId(), cleaner.getCurrentOpsOrderId());
// TODO: 触发工单暂停逻辑(后续在派单引擎中实现)
}
log.info("保洁员已离线: userId={}, deviceId={}, reason={}",
cleaner.getUserId(), deviceId, reason);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void handleDeviceOnline(Long deviceId) {
// 1. 根据设备ID查询保洁员
OpsCleanerStatusDO cleaner = getByDeviceId(deviceId);
if (cleaner == null) {
log.warn("设备未关联保洁员,忽略上线事件: deviceId={}", deviceId);
return;
}
// 2. 如果保洁员之前是OFFLINE状态则恢复为IDLE
if (CleanerStatusEnum.OFFLINE.getCode().equals(cleaner.getStatus())) {
cleaner.setStatusEnum(CleanerStatusEnum.IDLE);
cleaner.setOfflineReason(null);
cleaner.setStatusChangeTime(LocalDateTime.now());
cleaner.setLastDeviceSyncTime(LocalDateTime.now());
cleanerStatusMapper.updateById(cleaner);
log.info("保洁员已上线: userId={}, deviceId={}", cleaner.getUserId(), deviceId);
} else {
log.debug("保洁员当前状态非OFFLINE无需更新: userId={}, status={}",
cleaner.getUserId(), cleaner.getStatus());
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateStatus(Long userId, CleanerStatusEnum newStatus, String remark) {
OpsCleanerStatusDO cleaner = cleanerStatusMapper.selectByUserId(userId);
if (cleaner == null) {
throw new RuntimeException("保洁员不存在: " + userId);
}
CleanerStatusEnum oldStatus = cleaner.getStatusEnum();
cleaner.setStatusEnum(newStatus);
cleaner.setRemark(remark);
cleaner.setStatusChangeTime(LocalDateTime.now());
cleanerStatusMapper.updateById(cleaner);
log.info("保洁员状态已更新: userId={}, oldStatus={}, newStatus={}, remark={}",
userId, oldStatus, newStatus, remark);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateCurrentArea(Long userId, Long areaId, String areaName) {
OpsCleanerStatusDO cleaner = cleanerStatusMapper.selectByUserId(userId);
if (cleaner == null) {
throw new RuntimeException("保洁员不存在: " + userId);
}
cleaner.setCurrentAreaId(areaId);
cleaner.setCurrentAreaName(areaName);
cleanerStatusMapper.updateById(cleaner);
log.info("保洁员位置已更新: userId={}, areaId={}, areaName={}",
userId, areaId, areaName);
}
@Override
public List<OpsCleanerStatusDO> listCleanersByArea(Long areaId) {
return cleanerStatusMapper.selectListByAreaId(areaId);
}
@Override
public List<OpsCleanerStatusDO> listAvailableCleaners(Long areaId) {
return cleanerStatusMapper.selectList(
new LambdaQueryWrapper<OpsCleanerStatusDO>()
.eq(OpsCleanerStatusDO::getCurrentAreaId, areaId)
.eq(OpsCleanerStatusDO::getStatus, CleanerStatusEnum.IDLE.getCode())
);
}
@Override
public List<OpsCleanerStatusDO> findNearbyCleaners(Long areaId, Integer radius) {
// TODO: 后续可以基于地理位置实现真实的附近查询
// 目前简化为按区域查询
return listCleanersByArea(areaId);
}
@Override
public boolean isOnline(Long userId) {
OpsCleanerStatusDO cleaner = cleanerStatusMapper.selectByUserId(userId);
if (cleaner == null) {
return false;
}
return !CleanerStatusEnum.OFFLINE.getCode().equals(cleaner.getStatus());
}
@Override
public OpsCleanerStatusDO getStatus(Long userId) {
return cleanerStatusMapper.selectByUserId(userId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void setCurrentWorkOrder(Long userId, Long opsOrderId, String opsOrderCode) {
OpsCleanerStatusDO cleaner = cleanerStatusMapper.selectByUserId(userId);
if (cleaner == null) {
throw new RuntimeException("保洁员不存在: " + userId);
}
cleaner.setCurrentOpsOrderId(opsOrderId);
cleaner.setCurrentOpsOrderCode(opsOrderCode);
cleanerStatusMapper.updateById(cleaner);
log.info("保洁员已接单: userId={}, orderId={}, orderCode={}",
userId, opsOrderId, opsOrderCode);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void clearCurrentWorkOrder(Long userId) {
OpsCleanerStatusDO cleaner = cleanerStatusMapper.selectByUserId(userId);
if (cleaner == null) {
throw new RuntimeException("保洁员不存在: " + userId);
}
log.info("保洁员已完成工单: userId={}, orderId={}, orderCode={}",
userId, cleaner.getCurrentOpsOrderId(), cleaner.getCurrentOpsOrderCode());
cleaner.setCurrentOpsOrderId(null);
cleaner.setCurrentOpsOrderCode(null);
cleanerStatusMapper.updateById(cleaner);
}
}