feat(trajectory): 新增轨迹事件消费与落库模型
- 新增 ops_device_trajectory 表及轨迹数据对象、Mapper\n- 消费 trajectory-enter / trajectory-leave 事件并做幂等处理\n- 落地设备进入/离开区域记录,补充停留时长与离开原因字段\n- 在服务层封装轨迹写入、关闭未离场记录等核心逻辑
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
package com.viewsh.module.ops.dal.dataobject.trajectory;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.viewsh.framework.tenant.core.db.TenantBaseDO;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 设备轨迹记录 DO
|
||||
* <p>
|
||||
* 记录工牌设备进出各区域的轨迹
|
||||
* 一条记录表示一次"进入-离开"周期
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@TableName("ops_device_trajectory")
|
||||
@KeySequence("ops_device_trajectory_seq")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OpsDeviceTrajectoryDO extends TenantBaseDO {
|
||||
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 工牌设备ID
|
||||
*/
|
||||
private Long deviceId;
|
||||
|
||||
/**
|
||||
* 设备名称(冗余)
|
||||
*/
|
||||
private String deviceName;
|
||||
|
||||
/**
|
||||
* 设备备注名称(冗余)
|
||||
*/
|
||||
private String nickname;
|
||||
|
||||
/**
|
||||
* 人员ID(预留)
|
||||
*/
|
||||
private Long personId;
|
||||
|
||||
/**
|
||||
* 人员名称(预留)
|
||||
*/
|
||||
private String personName;
|
||||
|
||||
/**
|
||||
* 区域ID
|
||||
*/
|
||||
private Long areaId;
|
||||
|
||||
/**
|
||||
* 区域名称(冗余)
|
||||
*/
|
||||
private String areaName;
|
||||
|
||||
/**
|
||||
* 匹配的 Beacon MAC
|
||||
*/
|
||||
private String beaconMac;
|
||||
|
||||
/**
|
||||
* 进入时间
|
||||
*/
|
||||
private LocalDateTime enterTime;
|
||||
|
||||
/**
|
||||
* 离开时间
|
||||
*/
|
||||
private LocalDateTime leaveTime;
|
||||
|
||||
/**
|
||||
* 停留时长(秒)
|
||||
*/
|
||||
private Integer durationSeconds;
|
||||
|
||||
/**
|
||||
* 离开原因
|
||||
* <p>
|
||||
* SIGNAL_LOSS - 信号丢失
|
||||
* AREA_SWITCH - 切换到其他区域
|
||||
* DEVICE_OFFLINE - 设备离线
|
||||
*/
|
||||
private String leaveReason;
|
||||
|
||||
/**
|
||||
* 进入时 RSSI
|
||||
*/
|
||||
private Integer enterRssi;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.viewsh.module.ops.dal.mysql.trajectory;
|
||||
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.viewsh.module.ops.dal.dataobject.trajectory.OpsDeviceTrajectoryDO;
|
||||
import com.viewsh.module.ops.service.trajectory.dto.TrajectoryPageReqDTO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 设备轨迹记录 Mapper
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Mapper
|
||||
public interface OpsDeviceTrajectoryMapper extends BaseMapperX<OpsDeviceTrajectoryDO> {
|
||||
|
||||
/**
|
||||
* 查询设备在某区域最近一条未关闭的轨迹记录
|
||||
*/
|
||||
default OpsDeviceTrajectoryDO selectOpenRecord(Long deviceId, Long areaId) {
|
||||
return selectOne(new LambdaQueryWrapperX<OpsDeviceTrajectoryDO>()
|
||||
.eq(OpsDeviceTrajectoryDO::getDeviceId, deviceId)
|
||||
.eq(OpsDeviceTrajectoryDO::getAreaId, areaId)
|
||||
.isNull(OpsDeviceTrajectoryDO::getLeaveTime)
|
||||
.orderByDesc(OpsDeviceTrajectoryDO::getEnterTime)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备在某区域未关闭的轨迹记录(加锁,防止并发竞态)
|
||||
*/
|
||||
default OpsDeviceTrajectoryDO selectOpenRecordForUpdate(Long deviceId, Long areaId) {
|
||||
return selectOne(new LambdaQueryWrapperX<OpsDeviceTrajectoryDO>()
|
||||
.eq(OpsDeviceTrajectoryDO::getDeviceId, deviceId)
|
||||
.eq(OpsDeviceTrajectoryDO::getAreaId, areaId)
|
||||
.isNull(OpsDeviceTrajectoryDO::getLeaveTime)
|
||||
.orderByDesc(OpsDeviceTrajectoryDO::getEnterTime)
|
||||
.last("LIMIT 1 FOR UPDATE"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询设备在某区域、按进入时间精确匹配的未关闭轨迹记录(加锁)
|
||||
*/
|
||||
default OpsDeviceTrajectoryDO selectOpenRecordByEnterTimeForUpdate(Long deviceId, Long areaId,
|
||||
LocalDateTime enterTime) {
|
||||
return selectOne(new LambdaQueryWrapperX<OpsDeviceTrajectoryDO>()
|
||||
.eq(OpsDeviceTrajectoryDO::getDeviceId, deviceId)
|
||||
.eq(OpsDeviceTrajectoryDO::getAreaId, areaId)
|
||||
.eq(OpsDeviceTrajectoryDO::getEnterTime, enterTime)
|
||||
.isNull(OpsDeviceTrajectoryDO::getLeaveTime)
|
||||
.last("LIMIT 1 FOR UPDATE"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询轨迹记录
|
||||
*/
|
||||
default PageResult<OpsDeviceTrajectoryDO> selectPage(TrajectoryPageReqDTO req) {
|
||||
return selectPage(req, new LambdaQueryWrapperX<OpsDeviceTrajectoryDO>()
|
||||
.eqIfPresent(OpsDeviceTrajectoryDO::getDeviceId, req.getDeviceId())
|
||||
.eqIfPresent(OpsDeviceTrajectoryDO::getAreaId, req.getAreaId())
|
||||
.betweenIfPresent(OpsDeviceTrajectoryDO::getEnterTime, req.getEnterTime())
|
||||
.orderByDesc(OpsDeviceTrajectoryDO::getEnterTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询某设备某天的轨迹时间线(不分页,按进入时间升序)
|
||||
*/
|
||||
default List<OpsDeviceTrajectoryDO> selectTimeline(Long deviceId, LocalDate date) {
|
||||
LocalDateTime start = date.atStartOfDay();
|
||||
LocalDateTime end = date.plusDays(1).atStartOfDay();
|
||||
return selectList(new LambdaQueryWrapperX<OpsDeviceTrajectoryDO>()
|
||||
.eq(OpsDeviceTrajectoryDO::getDeviceId, deviceId)
|
||||
.ge(OpsDeviceTrajectoryDO::getEnterTime, start)
|
||||
.lt(OpsDeviceTrajectoryDO::getEnterTime, end)
|
||||
.orderByAsc(OpsDeviceTrajectoryDO::getEnterTime));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user