chore: 【ops】保洁员状态Service
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user