feat(trajectory): 新增轨迹后台查询与实时位置接口

- 新增轨迹分页、时间线、统计摘要等查询 DTO\n- 提供轨迹后台控制器,支持工牌下拉、轨迹查询、实时位置查询\n- 接入 TrajectoryStateApi 的 Feign 配置,打通 Ops 对 IoT 实时位置状态的读取
This commit is contained in:
lzh
2026-03-31 22:56:49 +08:00
parent bf5aa21648
commit d3eecc63ef
8 changed files with 415 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
package com.viewsh.module.ops.service.trajectory.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 工牌设备精简 Response DTO下拉列表用
*
* @author lzh
*/
@Schema(description = "管理后台 - 工牌设备精简信息(下拉列表用)")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BadgeSimpleRespDTO {
@Schema(description = "设备ID", example = "31")
private Long deviceId;
@Schema(description = "设备Key", example = "09207455611")
private String deviceKey;
@Schema(description = "设备备注名称", example = "1号工牌")
private String nickname;
}

View File

@@ -0,0 +1,39 @@
package com.viewsh.module.ops.service.trajectory.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 设备实时位置 Response DTO
*
* @author lzh
*/
@Schema(description = "管理后台 - 设备实时位置 Response DTO")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DeviceCurrentLocationDTO {
@Schema(description = "设备ID", example = "31")
private Long deviceId;
@Schema(description = "当前所在区域ID", example = "1301")
private Long areaId;
@Schema(description = "区域名称", example = "A座2楼男卫")
private String areaName;
@Schema(description = "进入时间(毫秒时间戳)", example = "1711872600000")
private Long enterTime;
@Schema(description = "匹配的Beacon MAC", example = "F0:C8:60:1D:10:BB")
private String beaconMac;
@Schema(description = "是否在某区域内")
private Boolean inArea;
}

View File

@@ -0,0 +1,35 @@
package com.viewsh.module.ops.service.trajectory.dto;
import com.viewsh.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static com.viewsh.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 轨迹分页查询 Request DTO
*
* @author lzh
*/
@Schema(description = "管理后台 - 设备轨迹分页查询 Request DTO")
@Data
@EqualsAndHashCode(callSuper = true)
public class TrajectoryPageReqDTO extends PageParam {
@Schema(description = "设备ID", example = "31")
private Long deviceId;
@Schema(description = "区域ID", example = "1301")
private Long areaId;
@Schema(description = "进入时间范围(开始时间, 结束时间)")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Size(min = 2, max = 2, message = "进入时间范围必须包含开始时间和结束时间")
private LocalDateTime[] enterTime;
}

View File

@@ -0,0 +1,59 @@
package com.viewsh.module.ops.service.trajectory.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 轨迹记录 Response DTO
*
* @author lzh
*/
@Schema(description = "管理后台 - 设备轨迹记录 Response DTO")
@Data
public class TrajectoryRespDTO {
@Schema(description = "记录ID", example = "1")
private Long id;
@Schema(description = "设备ID", example = "31")
private Long deviceId;
@Schema(description = "设备名称", example = "badge_001")
private String deviceName;
@Schema(description = "设备备注名称", example = "1号工牌")
private String nickname;
@Schema(description = "区域ID", example = "1301")
private Long areaId;
@Schema(description = "区域名称", example = "A座2楼男卫")
private String areaName;
@Schema(description = "楼栋名称", example = "A栋")
private String buildingName;
@Schema(description = "楼层号", example = "2")
private Integer floorNo;
@Schema(description = "Beacon MAC", example = "F0:C8:60:1D:10:BB")
private String beaconMac;
@Schema(description = "进入时间")
private LocalDateTime enterTime;
@Schema(description = "离开时间")
private LocalDateTime leaveTime;
@Schema(description = "停留时长(秒)", example = "300")
private Integer durationSeconds;
@Schema(description = "离开原因", example = "SIGNAL_LOSS")
private String leaveReason;
@Schema(description = "进入时RSSI", example = "-65")
private Integer enterRssi;
}

View File

@@ -0,0 +1,41 @@
package com.viewsh.module.ops.service.trajectory.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 轨迹统计摘要 Response DTO
* <p>
* 用于 KPI 卡片展示
*
* @author lzh
*/
@Schema(description = "管理后台 - 轨迹统计摘要 Response DTO")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TrajectorySummaryDTO {
@Schema(description = "总轨迹记录数(含未关闭)", example = "42")
private Long totalRecords;
@Schema(description = "已完成记录数(有离开时间)", example = "38")
private Long completedRecords;
@Schema(description = "覆盖区域数", example = "8")
private Long coveredAreaCount;
@Schema(description = "总停留时长(秒)", example = "28800")
private Long totalDurationSeconds;
@Schema(description = "平均停留时长(秒)", example = "685")
private Long avgDurationSeconds;
@Schema(description = "最长单次停留(秒)", example = "3600")
private Long maxDurationSeconds;
}

View File

@@ -0,0 +1,28 @@
package com.viewsh.module.ops.service.trajectory.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
/**
* 轨迹时间线查询 Request DTO
*
* @author lzh
*/
@Schema(description = "管理后台 - 设备轨迹时间线查询 Request DTO")
@Data
public class TrajectoryTimelineReqDTO {
@Schema(description = "设备ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31")
@NotNull(message = "设备ID不能为空")
private Long deviceId;
@Schema(description = "查询日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "2026-03-30")
@NotNull(message = "查询日期不能为空")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
}