feat(ops,iot): 保洁前端 API 层和区域管理新增
新增保洁业务前端 API 接口层(工牌、工单、仪表盘)和运营区域管理完整功能,包含 Service/Controller/Test 三层结构。 主要功能: 1. IoT 设备查询 API(RPC 接口) - IotDeviceQueryApi: 提供设备简化信息查询 - IotDeviceSimpleRespDTO: 设备简化 DTO 2. 保洁工牌管理 - CleanBadgeService/Impl: 工牌通知、优先级调整、手动完成 - BadgeNotifyReqDTO/UpgradePriorityReqDTO/ManualCompleteOrderReqDTO 3. 保洁工单管理 - CleanWorkOrderService/Impl: 工单时间线查询 4. 保洁仪表盘 - CleanDashboardService/Impl: 快速统计(待处理/进行中/已完成/在线工牌数) - QuickStatsRespDTO: 快速统计 DTO 5. 运营区域管理(Ops Biz) - OpsBusAreaService/Impl: 区域 CRUD(支持树形结构、分页查询) - AreaDeviceRelationService/Impl: 区域设备关联管理(绑定/解绑/批量更新) - OpsBusAreaMapper/AreaDeviceRelationMapper: 扩展 MyBatis 批量方法 - 7 个 VO 类:CreateReqVO/UpdateReqVO/PageReqVO/RespVO/BindReqVO/RelationRespVO/DeviceUpdateReqVO 6. 前端 Controller(Ops Server) - OpsBusAreaController: 区域管理 REST API(11 个接口) - AreaDeviceRelationController: 设备关联 REST API(8 个接口) - CleanBadgeController: 工牌管理 REST API(5 个接口) - CleanDashboardController: 仪表盘 REST API(1 个接口) - CleanDeviceController: 设备管理 REST API(2 个接口) - CleanWorkOrderController: 工单管理 REST API(2 个接口) 7. 测试覆盖 - OpsBusAreaServiceTest: 区域服务测试(284 行) - AreaDeviceRelationServiceTest: 设备关联测试(240 行) - OpsBusAreaControllerTest: 区域 Controller 测试(186 行) - AreaDeviceRelationControllerTest: 设备关联 Controller 测试(182 行) 8. API 层扩展 - ErrorCodeConstants: 错误码常量(区域、设备关联) - NotifyTypeEnum: 通知类型枚举(语音、文本、震动) - 4 个 Badge/Order DTO: BadgeStatusRespDTO/BadgeRealtimeStatusRespDTO/OrderTimelineRespDTO 9. RPC 配置 - RpcConfiguration: 注入 IotDeviceQueryApi 影响模块:Ops API、Ops Biz、Ops Server、Ops Environment Biz、IoT API、IoT Server Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
package com.viewsh.module.ops.api.clean;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 工牌实时状态详情响应 DTO
|
||||
* <p>
|
||||
* 用于工牌详情页展示
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Schema(description = "管理后台 - 工牌实时状态详情 Response DTO")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BadgeRealtimeStatusRespDTO {
|
||||
|
||||
@Schema(description = "设备ID", example = "3001")
|
||||
private Long deviceId;
|
||||
|
||||
@Schema(description = "设备编码", example = "badge_001")
|
||||
private String deviceKey;
|
||||
|
||||
@Schema(description = "设备状态", example = "BUSY")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "电量(0-100)", example = "72")
|
||||
private Integer batteryLevel;
|
||||
|
||||
@Schema(description = "最后心跳时间", example = "2026-01-23 15:00:30")
|
||||
private String lastHeartbeatTime;
|
||||
|
||||
@Schema(description = "信号强度(dBm)", example = "-42")
|
||||
private Integer rssi;
|
||||
|
||||
@Schema(description = "是否在区域内", example = "true")
|
||||
private Boolean isInArea;
|
||||
|
||||
@Schema(description = "当前区域ID", example = "101")
|
||||
private Long areaId;
|
||||
|
||||
@Schema(description = "当前区域名称", example = "A区洗手间")
|
||||
private String areaName;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.viewsh.module.ops.api.clean;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 工牌状态响应 DTO
|
||||
* <p>
|
||||
* 用于工牌列表展示
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Schema(description = "管理后台 - 工牌状态 Response DTO")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BadgeStatusRespDTO {
|
||||
|
||||
@Schema(description = "设备ID", example = "3001")
|
||||
private Long deviceId;
|
||||
|
||||
@Schema(description = "设备编码", example = "badge_001")
|
||||
private String deviceKey;
|
||||
|
||||
@Schema(description = "状态(IDLE/BUSY/OFFLINE/PAUSED)", example = "IDLE")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "电量(0-100)", example = "85")
|
||||
private Integer batteryLevel;
|
||||
|
||||
@Schema(description = "最后心跳时间", example = "2026-01-23 14:30:25")
|
||||
private String lastHeartbeatTime;
|
||||
|
||||
@Schema(description = "当前所在区域ID", example = "100")
|
||||
private Long currentAreaId;
|
||||
|
||||
@Schema(description = "当前所在区域名称", example = "A区洗手间")
|
||||
private String currentAreaName;
|
||||
|
||||
@Schema(description = "今日完成工单数", example = "5")
|
||||
private Integer todayCompletedCount;
|
||||
|
||||
@Schema(description = "今日工作时长(分钟)", example = "180")
|
||||
private Integer todayWorkMinutes;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.viewsh.module.ops.api.clean;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 工单时间轴响应 DTO
|
||||
* <p>
|
||||
* 用于工单详情页时间轴展示
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Schema(description = "管理后台 - 工单时间轴 Response DTO")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class OrderTimelineRespDTO {
|
||||
|
||||
@Schema(description = "工单ID", example = "1001")
|
||||
private Long orderId;
|
||||
|
||||
@Schema(description = "当前状态", example = "ARRIVED")
|
||||
private String currentStatus;
|
||||
|
||||
@Schema(description = "时间轴节点列表")
|
||||
private List<TimelineItemDTO> timeline;
|
||||
|
||||
/**
|
||||
* 时间轴节点 DTO
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "时间轴节点")
|
||||
public static class TimelineItemDTO {
|
||||
|
||||
@Schema(description = "状态", example = "PENDING")
|
||||
private String status;
|
||||
|
||||
@Schema(description = "状态名称", example = "工单创建")
|
||||
private String statusName;
|
||||
|
||||
@Schema(description = "时间", example = "2026-01-23 14:30:25")
|
||||
private String time;
|
||||
|
||||
@Schema(description = "操作人", example = "系统")
|
||||
private String operator;
|
||||
|
||||
@Schema(description = "描述", example = "蓝牙信标触发自动创建")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "额外信息(如RSSI值、信标ID等)")
|
||||
private Map<String, Object> extra;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.viewsh.module.ops.api.clean;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 快速统计响应 DTO
|
||||
* <p>
|
||||
* 用于工单中心仪表盘快速统计展示
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@Schema(description = "管理后台 - 快速统计 Response DTO")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class QuickStatsRespDTO {
|
||||
|
||||
@Schema(description = "待分配数量", example = "8")
|
||||
private Integer pendingCount;
|
||||
|
||||
@Schema(description = "进行中数量", example = "15")
|
||||
private Integer inProgressCount;
|
||||
|
||||
@Schema(description = "今日完成数量", example = "42")
|
||||
private Integer completedTodayCount;
|
||||
|
||||
@Schema(description = "在线工牌数量", example = "12")
|
||||
private Integer onlineBadgeCount;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.viewsh.module.ops.enums;
|
||||
|
||||
import com.viewsh.framework.common.exception.ErrorCode;
|
||||
|
||||
/**
|
||||
* ops 错误码枚举类
|
||||
* <p>
|
||||
* ops 系统,使用 1-020-000-000 段
|
||||
*/
|
||||
public interface ErrorCodeConstants {
|
||||
|
||||
// ========== 业务区域 1-020-001-000 ============
|
||||
ErrorCode AREA_NOT_FOUND = new ErrorCode(1_020_001_000, "区域不存在");
|
||||
ErrorCode AREA_HAS_CHILDREN = new ErrorCode(1_020_001_001, "该区域下存在子区域,请先处理子区域");
|
||||
ErrorCode AREA_HAS_DEVICES = new ErrorCode(1_020_001_002, "该区域已绑定设备,请先解除绑定");
|
||||
ErrorCode AREA_PARENT_LOOP = new ErrorCode(1_020_001_003, "不能将父级设置为自己或子孙节点");
|
||||
ErrorCode AREA_CODE_EXISTS = new ErrorCode(1_020_001_004, "区域编码已存在");
|
||||
|
||||
// ========== 区域设备关联 1-020-002-000 ============
|
||||
ErrorCode DEVICE_NOT_FOUND = new ErrorCode(1_020_002_000, "设备不存在");
|
||||
ErrorCode DEVICE_ALREADY_BOUND = new ErrorCode(1_020_002_001, "该工牌已绑定至此区域");
|
||||
ErrorCode DEVICE_TYPE_ALREADY_BOUND = new ErrorCode(1_020_002_002, "该区域已绑定{},一个区域只能绑定一个");
|
||||
ErrorCode DEVICE_RELATION_NOT_FOUND = new ErrorCode(1_020_002_003, "设备关联关系不存在");
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.viewsh.module.ops.enums;
|
||||
|
||||
import com.viewsh.framework.common.core.ArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 工牌通知类型枚举
|
||||
* <p>
|
||||
* 用于工牌设备通知(语音、震动等)
|
||||
*
|
||||
* @author lzh
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum NotifyTypeEnum implements ArrayValuable<String> {
|
||||
|
||||
VOICE("VOICE", "语音通知"),
|
||||
VIBRATE("VIBRATE", "震动通知");
|
||||
|
||||
public static final String[] ARRAYS = Arrays.stream(values()).map(NotifyTypeEnum::getType).toArray(String[]::new);
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final String type;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
@Override
|
||||
public String[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型获取枚举
|
||||
*
|
||||
* @param type 类型
|
||||
* @return 枚举实例,未找到返回 null
|
||||
*/
|
||||
public static NotifyTypeEnum fromType(String type) {
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
return Arrays.stream(values())
|
||||
.filter(e -> e.getType().equals(type))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user