diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/DetectedBeaconVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/DetectedBeaconVO.java
deleted file mode 100644
index d828f92..0000000
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/DetectedBeaconVO.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.viewsh.module.ops.environment.controller.admin.inspection.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import lombok.Data;
-
-@Schema(description = "蓝牙信标检测数据")
-@Data
-public class DetectedBeaconVO {
-
- @Schema(description = "信标MAC地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "F0:C8:60:1D:10:BB")
- @NotBlank(message = "信标MAC地址不能为空")
- private String mac;
-
- @Schema(description = "信号强度(RSSI)", requiredMode = Schema.RequiredMode.REQUIRED, example = "-65")
- @NotNull(message = "信号强度不能为空")
- private Integer rssi;
-
-}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionBeaconConfigVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionBeaconConfigVO.java
new file mode 100644
index 0000000..c47ceed
--- /dev/null
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionBeaconConfigVO.java
@@ -0,0 +1,42 @@
+package com.viewsh.module.ops.environment.controller.admin.inspection.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * 巡检 - 蓝牙信标扫描配置 VO
+ *
boundBeacons;
+
+ @Schema(description = "RSSI 阈值(信号强度低于此值视为不在范围内)", example = "-70")
+ private Integer rssiThreshold;
+
+ @Schema(description = "扫描超时时间(毫秒),超时未匹配则标记位置异常", example = "15000")
+ private Integer timeoutMs;
+
+}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionBoundBeaconVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionBoundBeaconVO.java
new file mode 100644
index 0000000..a6e309b
--- /dev/null
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionBoundBeaconVO.java
@@ -0,0 +1,25 @@
+package com.viewsh.module.ops.environment.controller.admin.inspection.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 巡检 - 区域绑定的信标特征 VO
+ *
+ * 下发给前端做本地位置匹配(major + minor 唯一标识一个信标)
+ */
+@Schema(description = "巡检 - 区域绑定信标特征")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class InspectionBoundBeaconVO {
+
+ @Schema(description = "iBeacon Major 值", example = "1")
+ private Integer major;
+
+ @Schema(description = "iBeacon Minor 值", example = "100")
+ private Integer minor;
+
+}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionFormRespVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionFormRespVO.java
new file mode 100644
index 0000000..a9401a2
--- /dev/null
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionFormRespVO.java
@@ -0,0 +1,33 @@
+package com.viewsh.module.ops.environment.controller.admin.inspection.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 管理后台 - 巡检表单(扫码后返回)Response VO
+ */
+@Schema(description = "管理后台 - 巡检表单 Response VO")
+@Data
+public class InspectionFormRespVO {
+
+ @Schema(description = "区域ID", example = "1024")
+ private Long areaId;
+
+ @Schema(description = "区域名称", example = "男卫")
+ private String areaName;
+
+ @Schema(description = "区域全路径名称", example = "A园区/1号楼/2层/男卫")
+ private String areaFullName;
+
+ @Schema(description = "功能类型", example = "MALE_TOILET")
+ private String functionType;
+
+ @Schema(description = "检查项列表")
+ private List items;
+
+ @Schema(description = "蓝牙信标扫描配置(null 表示该区域无信标,跳过位置校验)")
+ private InspectionBeaconConfigVO beaconConfig;
+
+}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordDetailRespVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordDetailRespVO.java
new file mode 100644
index 0000000..fc41e91
--- /dev/null
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordDetailRespVO.java
@@ -0,0 +1,31 @@
+package com.viewsh.module.ops.environment.controller.admin.inspection.vo;
+
+import com.viewsh.framework.web.core.presign.annotation.OssPresignUrl;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+/**
+ * 管理后台 - 巡检记录详情 Response VO(含明细项)
+ */
+@Schema(description = "管理后台 - 巡检记录详情 Response VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class InspectionRecordDetailRespVO extends InspectionRecordRespVO {
+
+ @Schema(description = "备注", example = "卫生间地面有污渍")
+ private String remark;
+
+ @Schema(description = "快捷标签", example = "[\"地面污渍\",\"垃圾未清理\"]")
+ private List tags;
+
+ @OssPresignUrl
+ @Schema(description = "巡检照片URL列表", example = "[\"https://oss.example.com/a.jpg\"]")
+ private List photos;
+
+ @Schema(description = "巡检明细项列表")
+ private List items;
+
+}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordItemRespVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordItemRespVO.java
new file mode 100644
index 0000000..547c46f
--- /dev/null
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordItemRespVO.java
@@ -0,0 +1,36 @@
+package com.viewsh.module.ops.environment.controller.admin.inspection.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 管理后台 - 巡检明细项 Response VO
+ */
+@Schema(description = "管理后台 - 巡检明细项 Response VO")
+@Data
+public class InspectionRecordItemRespVO {
+
+ @Schema(description = "明细ID", example = "1")
+ private Long id;
+
+ @Schema(description = "模板检查项ID", example = "501")
+ private Long templateId;
+
+ @Schema(description = "检查项标题", example = "地面洁净度")
+ private String itemTitle;
+
+ @Schema(description = "检查项描述", example = "基本无污渍、水渍")
+ private String itemDescription;
+
+ @Schema(description = "是否合格", example = "true")
+ private Boolean isPassed;
+
+ @Schema(description = "备注", example = "地面有明显污渍")
+ private String remark;
+
+ @Schema(description = "快捷标签", example = "[\"地面污渍\"]")
+ private List tags;
+
+}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordRespVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordRespVO.java
index 6f04f1e..6fd5dac 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordRespVO.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionRecordRespVO.java
@@ -4,8 +4,10 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
-import java.util.List;
+/**
+ * 管理后台 - 巡检记录(列表页)Response VO
+ */
@Schema(description = "管理后台 - 巡检记录 Response VO")
@Data
public class InspectionRecordRespVO {
@@ -16,28 +18,28 @@ public class InspectionRecordRespVO {
@Schema(description = "区域ID", example = "1")
private Long areaId;
+ @Schema(description = "区域全路径名称", example = "A园区/1号楼/2层/男卫")
+ private String areaFullName;
+
@Schema(description = "巡检员用户ID", example = "100")
private Long inspectorId;
+ @Schema(description = "巡检员姓名", example = "张三")
+ private String inspectorName;
+
@Schema(description = "位置是否异常(0正常 1异常)", example = "0")
private Integer isLocationException;
@Schema(description = "巡检结果,参见 InspectionResultEnum(0不合格 1合格)", example = "1")
private Integer resultStatus;
- @Schema(description = "备注", example = "检查完成")
- private String remark;
-
@Schema(description = "归属判定结果,参见 InspectionAttributionEnum(1个人责任 2突发状况 3正常)", example = "3")
private Integer attributionResult;
@Schema(description = "整改工单ID", example = "2048")
private Long generatedOrderId;
- @Schema(description = "快捷标签", example = "[\"地面污渍\",\"垃圾未清理\"]")
- private List tags;
-
- @Schema(description = "创建时间")
+ @Schema(description = "巡检时间")
private LocalDateTime createTime;
}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionSubmitReqVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionSubmitReqVO.java
index 039ac1c..454c817 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionSubmitReqVO.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionSubmitReqVO.java
@@ -28,6 +28,10 @@ public class InspectionSubmitReqVO {
@Size(max = 10, message = "标签数量不能超过10个")
private List<@Size(max = 32, message = "单个标签长度不能超过32") String> tags;
+ @Schema(description = "巡检照片URL列表", example = "[\"https://oss.example.com/a.jpg\"]")
+ @Size(max = 9, message = "照片数量不能超过9张")
+ private List photos;
+
@Schema(description = "巡检明细项列表", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "巡检明细项不能为空")
@Valid
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionTemplateRespVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionTemplateRespVO.java
index f9c6f35..19d8a55 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionTemplateRespVO.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionTemplateRespVO.java
@@ -15,9 +15,12 @@ public class InspectionTemplateRespVO {
@Schema(description = "功能类型", example = "TOILET")
private String functionType;
- @Schema(description = "检查项标题", example = "地面是否干净")
+ @Schema(description = "检查项标题", example = "地面洁净度")
private String itemTitle;
+ @Schema(description = "检查项描述(合格标准说明)", example = "基本无污渍、水渍")
+ private String itemDescription;
+
@Schema(description = "排序序号", example = "1")
private Integer sortOrder;
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionTemplateSaveReqVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionTemplateSaveReqVO.java
index 1b516bd..0e80005 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionTemplateSaveReqVO.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/InspectionTemplateSaveReqVO.java
@@ -16,10 +16,13 @@ public class InspectionTemplateSaveReqVO {
@NotBlank(message = "功能类型不能为空")
private String functionType;
- @Schema(description = "检查项标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "地面是否干净")
+ @Schema(description = "检查项标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "地面洁净度")
@NotBlank(message = "检查项标题不能为空")
private String itemTitle;
+ @Schema(description = "检查项描述(合格标准说明)", example = "基本无污渍、水渍")
+ private String itemDescription;
+
@Schema(description = "排序序号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "排序序号不能为空")
private Integer sortOrder;
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/LocationVerifyResultVO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/LocationVerifyResultVO.java
deleted file mode 100644
index 4a466f9..0000000
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/controller/admin/inspection/vo/LocationVerifyResultVO.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.viewsh.module.ops.environment.controller.admin.inspection.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Schema(description = "蓝牙位置校验结果")
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class LocationVerifyResultVO {
-
- @Schema(description = "校验是否通过")
- private Boolean passed;
-
- @Schema(description = "校验消息")
- private String message;
-
- public static LocationVerifyResultVO success() {
- return new LocationVerifyResultVO(true, "位置校验通过");
- }
-
- public static LocationVerifyResultVO fail(String message) {
- return new LocationVerifyResultVO(false, message);
- }
-
-}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/dal/dataobject/inspection/OpsInspectionRecordDO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/dal/dataobject/inspection/OpsInspectionRecordDO.java
index 6bb3678..8910cc3 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/dal/dataobject/inspection/OpsInspectionRecordDO.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/dal/dataobject/inspection/OpsInspectionRecordDO.java
@@ -69,5 +69,10 @@ public class OpsInspectionRecordDO extends BaseDO {
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List tags;
+ /**
+ * 巡检照片 URL 列表
+ */
+ @TableField(typeHandler = JacksonTypeHandler.class)
+ private List photos;
}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/dal/dataobject/inspection/OpsInspectionTemplateDO.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/dal/dataobject/inspection/OpsInspectionTemplateDO.java
index 5d2913a..5d5dcbd 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/dal/dataobject/inspection/OpsInspectionTemplateDO.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/dal/dataobject/inspection/OpsInspectionTemplateDO.java
@@ -32,6 +32,10 @@ public class OpsInspectionTemplateDO extends BaseDO {
* 检查项标题
*/
private String itemTitle;
+ /**
+ * 检查项描述(合格标准说明)
+ */
+ private String itemDescription;
/**
* 排序序号
*/
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionLocationService.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionLocationService.java
deleted file mode 100644
index f2edb10..0000000
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionLocationService.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.viewsh.module.ops.environment.service.inspection;
-
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.DetectedBeaconVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.LocationVerifyResultVO;
-
-import java.util.List;
-
-/**
- * 巡检蓝牙位置校验 Service
- */
-public interface InspectionLocationService {
-
- /**
- * 校验巡检人员是否在指定区域
- *
- * 逻辑:查询该区域绑定的 BEACON 类型设备,
- * 匹配检测到的蓝牙信标列表,至少1个绑定信标匹配且 RSSI 大于阈值即通过
- *
- * @param areaId 区域ID
- * @param detectedBeacons 检测到的蓝牙信标列表
- * @return 校验结果
- */
- LocationVerifyResultVO verifyLocation(Long areaId, List detectedBeacons);
-
-}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionLocationServiceImpl.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionLocationServiceImpl.java
deleted file mode 100644
index c46bbd9..0000000
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionLocationServiceImpl.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.viewsh.module.ops.environment.service.inspection;
-
-import com.viewsh.module.ops.dal.dataobject.area.OpsAreaDeviceRelationDO;
-import com.viewsh.module.ops.dal.mysql.area.OpsAreaDeviceRelationMapper;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.DetectedBeaconVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.LocationVerifyResultVO;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * 巡检蓝牙位置校验 Service 实现
- */
-@Service
-@Validated
-@Slf4j
-public class InspectionLocationServiceImpl implements InspectionLocationService {
-
- private static final String RELATION_TYPE_BEACON = "BEACON";
- private static final int DEFAULT_RSSI_THRESHOLD = -70;
-
- @Resource
- private OpsAreaDeviceRelationMapper areaDeviceRelationMapper;
-
- @Override
- public LocationVerifyResultVO verifyLocation(Long areaId, List detectedBeacons) {
- if (detectedBeacons == null || detectedBeacons.isEmpty()) {
- return LocationVerifyResultVO.fail("未检测到蓝牙信标");
- }
-
- // 查询该区域绑定的 BEACON 设备
- List beaconRelations =
- areaDeviceRelationMapper.selectListByAreaIdAndRelationType(areaId, RELATION_TYPE_BEACON);
- if (beaconRelations.isEmpty()) {
- // 区域未绑定信标,视为不需要位置校验,直接通过
- log.info("[verifyLocation] 区域 {} 未绑定蓝牙信标,跳过位置校验", areaId);
- return LocationVerifyResultVO.success();
- }
-
- // 匹配逻辑:至少1个绑定信标匹配且 RSSI > 阈值
- for (OpsAreaDeviceRelationDO relation : beaconRelations) {
- String boundBeaconMac = extractBeaconMac(relation);
- if (boundBeaconMac == null) {
- continue;
- }
- int rssiThreshold = extractRssiThreshold(relation);
-
- for (DetectedBeaconVO detected : detectedBeacons) {
- if (boundBeaconMac.equalsIgnoreCase(detected.getMac())
- && detected.getRssi() >= rssiThreshold) {
- log.info("[verifyLocation] 区域 {} 位置校验通过,匹配信标 {},RSSI={}",
- areaId, detected.getMac(), detected.getRssi());
- return LocationVerifyResultVO.success();
- }
- }
- }
-
- return LocationVerifyResultVO.fail("未匹配到该区域的蓝牙信标,请确认是否在正确位置");
- }
-
- /**
- * 从设备关联的 configData 中提取信标 MAC 地址
- */
- private String extractBeaconMac(OpsAreaDeviceRelationDO relation) {
- Map configData = relation.getConfigData();
- if (configData == null) {
- // 退回到 deviceKey 作为 MAC 标识
- return relation.getDeviceKey();
- }
- Object beaconMac = configData.get("beaconMac");
- if (beaconMac != null) {
- return beaconMac.toString();
- }
- return relation.getDeviceKey();
- }
-
- /**
- * 从设备关联的 configData 中提取 RSSI 阈值
- */
- @SuppressWarnings("unchecked")
- private int extractRssiThreshold(OpsAreaDeviceRelationDO relation) {
- Map configData = relation.getConfigData();
- if (configData == null) {
- return DEFAULT_RSSI_THRESHOLD;
- }
- Object enter = configData.get("enter");
- if (enter instanceof Map) {
- Object threshold = ((Map) enter).get("rssiThreshold");
- if (threshold instanceof Number) {
- return ((Number) threshold).intValue();
- }
- }
- return DEFAULT_RSSI_THRESHOLD;
- }
-
-}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRecordService.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRecordService.java
index b92876a..9dbbfd4 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRecordService.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRecordService.java
@@ -1,10 +1,7 @@
package com.viewsh.module.ops.environment.service.inspection;
import com.viewsh.framework.common.pojo.PageResult;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionRecordPageReqVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionStatsReqVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionStatsRespVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionSubmitReqVO;
+import com.viewsh.module.ops.environment.controller.admin.inspection.vo.*;
import com.viewsh.module.ops.environment.dal.dataobject.inspection.OpsInspectionRecordDO;
/**
@@ -22,12 +19,20 @@ public interface InspectionRecordService {
Long submitInspection(InspectionSubmitReqVO submitReqVO, Long inspectorId);
/**
- * 获得巡检记录分页
+ * 获得巡检记录分页(含区域名称、巡检员姓名)
*
* @param pageReqVO 分页查询
* @return 巡检记录分页
*/
- PageResult getRecordPage(InspectionRecordPageReqVO pageReqVO);
+ PageResult getRecordPage(InspectionRecordPageReqVO pageReqVO);
+
+ /**
+ * 获得巡检记录详情(含明细项)
+ *
+ * @param id 巡检记录ID
+ * @return 巡检记录详情
+ */
+ InspectionRecordDetailRespVO getRecordDetail(Long id);
/**
* 获得巡检统计(合格率、不合格热点区域)
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRecordServiceImpl.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRecordServiceImpl.java
index a3a2b5a..89259c4 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRecordServiceImpl.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionRecordServiceImpl.java
@@ -2,19 +2,26 @@ package com.viewsh.module.ops.environment.service.inspection;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.viewsh.framework.common.pojo.PageResult;
+import com.viewsh.framework.common.util.http.HttpUtils;
import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.viewsh.module.ops.enums.InspectionResultEnum;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionRecordPageReqVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionStatsReqVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionStatsRespVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionSubmitItemVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionSubmitReqVO;
+import com.viewsh.framework.common.util.object.BeanUtils;
+import com.viewsh.module.ops.environment.controller.admin.inspection.vo.*;
+import com.viewsh.module.ops.environment.dal.dataobject.inspection.OpsInspectionTemplateDO;
+import com.viewsh.module.ops.environment.dal.mysql.inspection.OpsInspectionTemplateMapper;
+import com.viewsh.module.ops.dal.dataobject.area.OpsBusAreaDO;
+import com.viewsh.module.ops.dal.mysql.area.OpsBusAreaMapper;
+import com.viewsh.module.system.api.user.AdminUserApi;
+import com.viewsh.module.system.api.user.dto.AdminUserRespDTO;
import com.viewsh.module.ops.environment.dal.dataobject.inspection.OpsInspectionRecordDO;
import com.viewsh.module.ops.environment.dal.dataobject.inspection.OpsInspectionRecordItemDO;
import com.viewsh.module.ops.environment.dal.mysql.inspection.OpsInspectionRecordItemMapper;
import com.viewsh.module.ops.environment.dal.mysql.inspection.OpsInspectionRecordMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
+
+import static com.viewsh.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static com.viewsh.module.ops.enums.ErrorCodeConstants.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
@@ -23,8 +30,8 @@ import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.math.RoundingMode;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* 巡检记录 Service 实现
@@ -40,12 +47,24 @@ public class InspectionRecordServiceImpl implements InspectionRecordService {
@Resource
private OpsInspectionRecordItemMapper inspectionRecordItemMapper;
+ @Resource
+ private OpsBusAreaMapper opsBusAreaMapper;
+
+ @Resource
+ private OpsInspectionTemplateMapper inspectionTemplateMapper;
+
+ @Resource
+ private AdminUserApi adminUserApi;
+
@Resource
private InspectionAsyncHandler inspectionAsyncHandler;
@Override
@Transactional(rollbackFor = Exception.class)
public Long submitInspection(InspectionSubmitReqVO submitReqVO, Long inspectorId) {
+ // 0. 前置校验:区域是否存在且启用
+ validateArea(submitReqVO.getAreaId());
+
// 1. 判定巡检结果:任一项不合格 → 整体不合格
boolean allPassed = submitReqVO.getItems().stream()
.allMatch(InspectionSubmitItemVO::getIsPassed);
@@ -59,6 +78,7 @@ public class InspectionRecordServiceImpl implements InspectionRecordService {
.resultStatus(resultStatus)
.remark(submitReqVO.getRemark())
.tags(submitReqVO.getTags())
+ .photos(normalizePhotoUrls(submitReqVO.getPhotos()))
.build();
inspectionRecordMapper.insert(record);
@@ -90,13 +110,41 @@ public class InspectionRecordServiceImpl implements InspectionRecordService {
}
@Override
- public PageResult getRecordPage(InspectionRecordPageReqVO pageReqVO) {
- return inspectionRecordMapper.selectPage(pageReqVO, new LambdaQueryWrapperX()
- .eqIfPresent(OpsInspectionRecordDO::getAreaId, pageReqVO.getAreaId())
- .eqIfPresent(OpsInspectionRecordDO::getInspectorId, pageReqVO.getInspectorId())
- .eqIfPresent(OpsInspectionRecordDO::getResultStatus, pageReqVO.getResultStatus())
- .betweenIfPresent(OpsInspectionRecordDO::getCreateTime, pageReqVO.getCreateTime())
- .orderByDesc(OpsInspectionRecordDO::getId));
+ public PageResult getRecordPage(InspectionRecordPageReqVO pageReqVO) {
+ PageResult pageResult = inspectionRecordMapper.selectPage(pageReqVO,
+ new LambdaQueryWrapperX()
+ .eqIfPresent(OpsInspectionRecordDO::getAreaId, pageReqVO.getAreaId())
+ .eqIfPresent(OpsInspectionRecordDO::getInspectorId, pageReqVO.getInspectorId())
+ .eqIfPresent(OpsInspectionRecordDO::getResultStatus, pageReqVO.getResultStatus())
+ .betweenIfPresent(OpsInspectionRecordDO::getCreateTime, pageReqVO.getCreateTime())
+ .orderByDesc(OpsInspectionRecordDO::getId));
+
+ List records = pageResult.getList();
+ if (records.isEmpty()) {
+ return new PageResult<>(Collections.emptyList(), pageResult.getTotal());
+ }
+
+ // 批量查区域,一次性拼全路径名称(避免 N+1)
+ Set areaIds = records.stream().map(OpsInspectionRecordDO::getAreaId).collect(Collectors.toSet());
+ List areas = opsBusAreaMapper.selectBatchIds(areaIds);
+ Map areaFullNameMap = opsBusAreaMapper.buildAreaFullNameMap(areas);
+
+ // 批量查巡检员姓名
+ Set inspectorIds = records.stream().map(OpsInspectionRecordDO::getInspectorId).collect(Collectors.toSet());
+ Map userMap = adminUserApi.getUserMap(inspectorIds);
+
+ // 组装 VO
+ List voList = records.stream().map(record -> {
+ InspectionRecordRespVO vo = BeanUtils.toBean(record, InspectionRecordRespVO.class);
+ vo.setAreaFullName(areaFullNameMap.get(record.getAreaId()));
+ AdminUserRespDTO user = userMap.get(record.getInspectorId());
+ if (user != null) {
+ vo.setInspectorName(user.getNickname());
+ }
+ return vo;
+ }).toList();
+
+ return new PageResult<>(voList, pageResult.getTotal());
}
@Override
@@ -151,4 +199,78 @@ public class InspectionRecordServiceImpl implements InspectionRecordService {
.build();
}
+ @Override
+ public InspectionRecordDetailRespVO getRecordDetail(Long id) {
+ // 1. 查主记录
+ OpsInspectionRecordDO record = inspectionRecordMapper.selectById(id);
+ if (record == null) {
+ throw exception(INSPECTION_RECORD_NOT_FOUND);
+ }
+
+ // 2. 转换基础字段
+ InspectionRecordDetailRespVO detailVO = BeanUtils.toBean(record, InspectionRecordDetailRespVO.class);
+
+ // 3. 区域全路径名称
+ OpsBusAreaDO area = opsBusAreaMapper.selectById(record.getAreaId());
+ if (area != null) {
+ detailVO.setAreaFullName(opsBusAreaMapper.buildAreaFullName(area));
+ }
+
+ // 4. 巡检员姓名(降级处理,避免远程调用失败导致整个详情接口不可用)
+ try {
+ Map userMap = adminUserApi.getUserMap(Set.of(record.getInspectorId()));
+ AdminUserRespDTO user = userMap.get(record.getInspectorId());
+ if (user != null) {
+ detailVO.setInspectorName(user.getNickname());
+ }
+ } catch (Exception e) {
+ log.warn("[getRecordDetail] 查询巡检员姓名失败: inspectorId={}", record.getInspectorId(), e);
+ }
+
+ // 5. 查询明细项 + 关联模板标题
+ List items = inspectionRecordItemMapper.selectListByRecordId(id);
+ // 批量查模板
+ Set templateIds = items.stream().map(OpsInspectionRecordItemDO::getTemplateId).collect(Collectors.toSet());
+ Map templateMap = templateIds.isEmpty()
+ ? Collections.emptyMap()
+ : inspectionTemplateMapper.selectBatchIds(templateIds).stream()
+ .collect(Collectors.toMap(OpsInspectionTemplateDO::getId, t -> t));
+
+ List itemVOs = items.stream().map(item -> {
+ InspectionRecordItemRespVO itemVO = BeanUtils.toBean(item, InspectionRecordItemRespVO.class);
+ OpsInspectionTemplateDO template = templateMap.get(item.getTemplateId());
+ if (template != null) {
+ itemVO.setItemTitle(template.getItemTitle());
+ itemVO.setItemDescription(template.getItemDescription());
+ }
+ return itemVO;
+ }).toList();
+ detailVO.setItems(itemVOs);
+
+ return detailVO;
+ }
+
+ /**
+ * 校验区域是否存在且已启用
+ */
+ private void validateArea(Long areaId) {
+ OpsBusAreaDO area = opsBusAreaMapper.selectById(areaId);
+ if (area == null) {
+ throw exception(AREA_NOT_FOUND);
+ }
+ if (!Boolean.TRUE.equals(area.getIsActive())) {
+ throw exception(INSPECTION_AREA_NOT_ACTIVE);
+ }
+ }
+
+ private List normalizePhotoUrls(List photos) {
+ if (photos == null || photos.isEmpty()) {
+ return photos;
+ }
+ return photos.stream()
+ .filter(Objects::nonNull)
+ .map(HttpUtils::removeUrlQuery)
+ .toList();
+ }
+
}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionTemplateService.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionTemplateService.java
index 9f55997..d16a141 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionTemplateService.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionTemplateService.java
@@ -3,6 +3,7 @@ package com.viewsh.module.ops.environment.service.inspection;
import com.viewsh.framework.common.pojo.PageResult;
import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionTemplatePageReqVO;
import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionTemplateSaveReqVO;
+import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionFormRespVO;
import com.viewsh.module.ops.environment.dal.dataobject.inspection.OpsInspectionTemplateDO;
import java.util.List;
@@ -59,13 +60,13 @@ public interface InspectionTemplateService {
List getTemplateListByFunctionType(String functionType);
/**
- * 按区域ID获取动态巡检表单(检查项列表)
+ * 按区域ID获取巡检表单(区域信息 + 检查项列表)
*
- * 流程: area_id → 查 ops_bus_area 获取 function_type → 查 ops_inspection_template 加载检查项
+ * 流程: area_id → 校验区域 → 查 function_type → 加载检查项 → 拼装区域全路径名称
*
* @param areaId 区域ID
- * @return 检查项列表(按 sortOrder 排序)
+ * @return 巡检表单(含区域信息和检查项列表)
*/
- List getTemplateListByAreaId(Long areaId);
+ InspectionFormRespVO getInspectionFormByAreaId(Long areaId);
}
diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionTemplateServiceImpl.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionTemplateServiceImpl.java
index 2b07f1b..ac4cdf9 100644
--- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionTemplateServiceImpl.java
+++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/inspection/InspectionTemplateServiceImpl.java
@@ -3,10 +3,12 @@ package com.viewsh.module.ops.environment.service.inspection;
import com.viewsh.framework.common.pojo.PageResult;
import com.viewsh.framework.common.util.object.BeanUtils;
import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionTemplatePageReqVO;
-import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionTemplateSaveReqVO;
+import com.viewsh.module.ops.environment.controller.admin.inspection.vo.*;
import com.viewsh.module.ops.dal.dataobject.area.OpsBusAreaDO;
+import com.viewsh.module.ops.dal.dataobject.area.OpsAreaDeviceRelationDO;
import com.viewsh.module.ops.dal.mysql.area.OpsBusAreaMapper;
+import com.viewsh.module.ops.dal.mysql.area.OpsAreaDeviceRelationMapper;
+import lombok.extern.slf4j.Slf4j;
import com.viewsh.module.ops.environment.dal.dataobject.inspection.OpsInspectionTemplateDO;
import com.viewsh.module.ops.environment.dal.mysql.inspection.OpsInspectionTemplateMapper;
import jakarta.annotation.Resource;
@@ -14,26 +16,35 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
import static com.viewsh.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.viewsh.module.ops.enums.ErrorCodeConstants.AREA_NOT_FOUND;
+import static com.viewsh.module.ops.enums.ErrorCodeConstants.INSPECTION_AREA_NOT_ACTIVE;
import static com.viewsh.module.ops.enums.ErrorCodeConstants.INSPECTION_TEMPLATE_NOT_FOUND;
/**
* 巡检检查项模板 Service 实现
*/
+@Slf4j
@Service
@Validated
public class InspectionTemplateServiceImpl implements InspectionTemplateService {
+ private static final String RELATION_TYPE_BEACON = "BEACON";
+ private static final int DEFAULT_RSSI_THRESHOLD = -70;
+ private static final int DEFAULT_TIMEOUT_MS = 15000;
+
@Resource
private OpsInspectionTemplateMapper inspectionTemplateMapper;
@Resource
private OpsBusAreaMapper opsBusAreaMapper;
+ @Resource
+ private OpsAreaDeviceRelationMapper areaDeviceRelationMapper;
+
@Override
@Transactional(rollbackFor = Exception.class)
public Long createTemplate(InspectionTemplateSaveReqVO createReqVO) {
@@ -83,16 +94,121 @@ public class InspectionTemplateServiceImpl implements InspectionTemplateService
}
@Override
- public List getTemplateListByAreaId(Long areaId) {
+ public InspectionFormRespVO getInspectionFormByAreaId(Long areaId) {
+ // 1. 校验区域
OpsBusAreaDO area = opsBusAreaMapper.selectById(areaId);
if (area == null) {
throw exception(AREA_NOT_FOUND);
}
- String functionType = area.getFunctionType();
- if (functionType == null || functionType.isEmpty()) {
- return Collections.emptyList();
+ if (!Boolean.TRUE.equals(area.getIsActive())) {
+ throw exception(INSPECTION_AREA_NOT_ACTIVE);
}
- return inspectionTemplateMapper.selectListByFunctionType(functionType);
+
+ // 2. 查询检查项
+ String functionType = area.getFunctionType();
+ List templates = (functionType == null || functionType.isEmpty())
+ ? Collections.emptyList()
+ : inspectionTemplateMapper.selectListByFunctionType(functionType);
+
+ // 3. 查询区域绑定的信标设备,拼装扫描配置
+ InspectionBeaconConfigVO beaconConfig = buildBeaconConfig(areaId);
+
+ // 4. 拼装返回
+ InspectionFormRespVO formVO = new InspectionFormRespVO();
+ formVO.setAreaId(area.getId());
+ formVO.setAreaName(area.getAreaName());
+ formVO.setAreaFullName(opsBusAreaMapper.buildAreaFullName(area));
+ formVO.setFunctionType(functionType);
+ formVO.setItems(BeanUtils.toBean(templates, InspectionTemplateRespVO.class));
+ formVO.setBeaconConfig(beaconConfig);
+ return formVO;
+ }
+
+ /**
+ * 构建信标扫描配置
+ *
+ * 查询区域绑定的 BEACON 设备,从 configData.beaconPresence 中提取配置,
+ * 返回 null 表示该区域无信标,前端应跳过位置校验。
+ */
+ private InspectionBeaconConfigVO buildBeaconConfig(Long areaId) {
+ List beaconRelations =
+ areaDeviceRelationMapper.selectListByAreaIdAndRelationType(areaId, RELATION_TYPE_BEACON);
+ if (beaconRelations.isEmpty()) {
+ return null;
+ }
+
+ String uuid = null;
+ List boundBeacons = new ArrayList<>();
+ int rssiThreshold = DEFAULT_RSSI_THRESHOLD;
+
+ for (OpsAreaDeviceRelationDO relation : beaconRelations) {
+ Map presence = extractBeaconPresenceMap(relation.getConfigData());
+ if (presence == null) {
+ continue;
+ }
+
+ // UUID(所有信标共用,取第一个有效值)
+ String beaconUuid = (String) presence.get("beaconUuid");
+ if (uuid == null && beaconUuid != null) {
+ uuid = beaconUuid;
+ }
+
+ // major + minor
+ Integer major = toInteger(presence.get("major"));
+ Integer minor = toInteger(presence.get("minor"));
+ if (major != null && minor != null) {
+ boundBeacons.add(new InspectionBoundBeaconVO(major, minor));
+ }
+
+ // RSSI 阈值:多个信标取最小值(即最宽松),确保巡检员在任一信标附近即算到位。
+ // RSSI 越小(越负)表示信号越弱,取最小值意味着允许最弱信号通过。
+ @SuppressWarnings("unchecked")
+ Map enter = (Map) presence.get("enter");
+ if (enter != null) {
+ Integer threshold = toInteger(enter.get("rssiThreshold"));
+ if (threshold != null && threshold < rssiThreshold) {
+ rssiThreshold = threshold;
+ }
+ }
+ }
+
+ if (uuid == null || boundBeacons.isEmpty()) {
+ log.warn("[buildBeaconConfig] 区域 {} 绑定了 BEACON 设备但缺少 beaconUuid/major/minor 配置", areaId);
+ return null;
+ }
+
+ return InspectionBeaconConfigVO.builder()
+ .uuid(uuid)
+ .boundBeacons(boundBeacons)
+ .rssiThreshold(rssiThreshold)
+ .timeoutMs(DEFAULT_TIMEOUT_MS)
+ .build();
+ }
+
+ /**
+ * 从 configData 中提取 beaconPresence 节点
+ */
+ @SuppressWarnings("unchecked")
+ private Map extractBeaconPresenceMap(Map configData) {
+ if (configData == null || !configData.containsKey("beaconPresence")) {
+ return null;
+ }
+ Object value = configData.get("beaconPresence");
+ if (value instanceof Map) {
+ return (Map) value;
+ }
+ log.warn("[extractBeaconPresenceMap] beaconPresence 类型不是 Map: {}", value.getClass().getName());
+ return null;
+ }
+
+ private static Integer toInteger(Object value) {
+ if (value instanceof Integer) {
+ return (Integer) value;
+ }
+ if (value instanceof Number) {
+ return ((Number) value).intValue();
+ }
+ return null;
}
private void validateTemplateExists(Long id) {
diff --git a/viewsh-module-ops/viewsh-module-ops-api/src/main/java/com/viewsh/module/ops/enums/ErrorCodeConstants.java b/viewsh-module-ops/viewsh-module-ops-api/src/main/java/com/viewsh/module/ops/enums/ErrorCodeConstants.java
index 2204d69..2c2359a 100644
--- a/viewsh-module-ops/viewsh-module-ops-api/src/main/java/com/viewsh/module/ops/enums/ErrorCodeConstants.java
+++ b/viewsh-module-ops/viewsh-module-ops-api/src/main/java/com/viewsh/module/ops/enums/ErrorCodeConstants.java
@@ -29,8 +29,9 @@ public interface ErrorCodeConstants {
ErrorCode DEVICE_RELATION_NOT_FOUND = new ErrorCode(1_020_002_003, "设备关联关系不存在");
ErrorCode IOT_SERVICE_UNAVAILABLE = new ErrorCode(1_020_002_004, "IoT 设备服务不可用,请稍后重试");
- // ========== 巡检模块 1-020-003-000 ============
- ErrorCode INSPECTION_TEMPLATE_NOT_FOUND = new ErrorCode(1_020_003_000, "巡检模板不存在");
- ErrorCode INSPECTION_RECORD_NOT_FOUND = new ErrorCode(1_020_003_001, "巡检记录不存在");
+ // ========== 巡检模块 1-020-004-000 ============
+ ErrorCode INSPECTION_TEMPLATE_NOT_FOUND = new ErrorCode(1_020_004_000, "巡检模板不存在");
+ ErrorCode INSPECTION_RECORD_NOT_FOUND = new ErrorCode(1_020_004_001, "巡检记录不存在");
+ ErrorCode INSPECTION_AREA_NOT_ACTIVE = new ErrorCode(1_020_004_002, "该区域未启用,无法巡检");
}
diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/dal/mysql/area/OpsBusAreaMapper.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/dal/mysql/area/OpsBusAreaMapper.java
index 6f026c5..f79ed14 100644
--- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/dal/mysql/area/OpsBusAreaMapper.java
+++ b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/dal/mysql/area/OpsBusAreaMapper.java
@@ -6,7 +6,8 @@ import com.viewsh.module.ops.dal.dataobject.area.OpsBusAreaDO;
import com.viewsh.module.ops.dal.dataobject.vo.area.OpsBusAreaPageReqVO;
import org.apache.ibatis.annotations.Mapper;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
/**
* 业务区域 Mapper
@@ -103,4 +104,91 @@ public interface OpsBusAreaMapper extends BaseMapperX {
return selectCount(OpsBusAreaDO::getParentId, parentId);
}
+ // ==================== 区域全路径名称 ====================
+
+ /**
+ * 拼接区域全路径名称(如 "A园区/1号楼/2层/男卫")
+ *
+ * @param area 区域对象
+ * @return 全路径名称
+ */
+ default String buildAreaFullName(OpsBusAreaDO area) {
+ if (area.getParentPath() == null || area.getParentPath().isEmpty()) {
+ return area.getAreaName();
+ }
+ List ancestorIds = Arrays.stream(area.getParentPath().split("/"))
+ .filter(s -> !s.isEmpty())
+ .map(Long::valueOf)
+ .collect(Collectors.toList());
+ if (ancestorIds.isEmpty()) {
+ return area.getAreaName();
+ }
+ Map nameMap = selectBatchIds(ancestorIds).stream()
+ .collect(Collectors.toMap(OpsBusAreaDO::getId, OpsBusAreaDO::getAreaName));
+ StringBuilder sb = new StringBuilder();
+ for (Long ancestorId : ancestorIds) {
+ String name = nameMap.get(ancestorId);
+ if (name != null) {
+ if (!sb.isEmpty()) {
+ sb.append("/");
+ }
+ sb.append(name);
+ }
+ }
+ sb.append("/").append(area.getAreaName());
+ return sb.toString();
+ }
+
+ /**
+ * 批量构建区域全路径名称(优化 N+1 查询,一次性查出所有祖先节点)
+ *
+ * @param areas 区域列表
+ * @return area.id → 全路径名称
+ */
+ default Map buildAreaFullNameMap(Collection areas) {
+ if (areas == null || areas.isEmpty()) {
+ return Collections.emptyMap();
+ }
+ // 收集所有祖先 ID,一次性批量查询
+ Set allAncestorIds = new HashSet<>();
+ for (OpsBusAreaDO area : areas) {
+ if (area.getParentPath() != null && !area.getParentPath().isEmpty()) {
+ Arrays.stream(area.getParentPath().split("/"))
+ .filter(s -> !s.isEmpty())
+ .map(Long::valueOf)
+ .forEach(allAncestorIds::add);
+ }
+ }
+ Map ancestorNameMap = allAncestorIds.isEmpty()
+ ? Collections.emptyMap()
+ : selectBatchIds(allAncestorIds).stream()
+ .collect(Collectors.toMap(OpsBusAreaDO::getId, OpsBusAreaDO::getAreaName));
+
+ // 拼装每个区域的全路径
+ Map result = new HashMap<>(areas.size());
+ for (OpsBusAreaDO area : areas) {
+ if (area.getParentPath() == null || area.getParentPath().isEmpty()) {
+ result.put(area.getId(), area.getAreaName());
+ continue;
+ }
+ List ancestorIds = Arrays.stream(area.getParentPath().split("/"))
+ .filter(s -> !s.isEmpty())
+ .map(Long::valueOf)
+ .toList();
+ StringBuilder sb = new StringBuilder();
+ for (Long ancestorId : ancestorIds) {
+ String name = ancestorNameMap.get(ancestorId);
+ if (name != null) {
+ if (!sb.isEmpty()) {
+ sb.append("/");
+ }
+ sb.append(name);
+ }
+ }
+ sb.append("/").append(area.getAreaName());
+ result.put(area.getId(), sb.toString());
+ }
+ return result;
+ }
+
}
diff --git a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/inspection/InspectionController.java b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/inspection/InspectionController.java
index 40eebcf..7186f2f 100644
--- a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/inspection/InspectionController.java
+++ b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/inspection/InspectionController.java
@@ -2,11 +2,8 @@ package com.viewsh.module.ops.controller.admin.inspection;
import com.viewsh.framework.common.pojo.CommonResult;
import com.viewsh.framework.common.pojo.PageResult;
-import com.viewsh.framework.common.util.object.BeanUtils;
import com.viewsh.framework.security.core.util.SecurityFrameworkUtils;
import com.viewsh.module.ops.environment.controller.admin.inspection.vo.*;
-import com.viewsh.module.ops.environment.dal.dataobject.inspection.OpsInspectionRecordDO;
-import com.viewsh.module.ops.environment.service.inspection.InspectionLocationService;
import com.viewsh.module.ops.environment.service.inspection.InspectionRecordService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -17,8 +14,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
-import java.util.List;
-
import static com.viewsh.framework.common.pojo.CommonResult.success;
/**
@@ -30,36 +25,30 @@ import static com.viewsh.framework.common.pojo.CommonResult.success;
@Validated
public class InspectionController {
- @Resource
- private InspectionLocationService inspectionLocationService;
-
@Resource
private InspectionRecordService inspectionRecordService;
- @PostMapping("/verify-location")
- @Operation(summary = "蓝牙位置校验")
- @Parameter(name = "areaId", description = "区域ID", required = true)
- @PreAuthorize("@ss.hasPermission('ops:inspection:create')")
- public CommonResult verifyLocation(
- @RequestParam("areaId") Long areaId,
- @Valid @RequestBody List detectedBeacons) {
- return success(inspectionLocationService.verifyLocation(areaId, detectedBeacons));
- }
-
@PostMapping("/submit")
@Operation(summary = "提交巡检结果")
- @PreAuthorize("@ss.hasPermission('ops:inspection:create')")
+ @PreAuthorize("@ss.hasPermission('ops:inspection:create') and @ss.hasRole('inspector')")
public CommonResult submitInspection(@Valid @RequestBody InspectionSubmitReqVO submitReqVO) {
Long inspectorId = SecurityFrameworkUtils.getLoginUserId();
return success(inspectionRecordService.submitInspection(submitReqVO, inspectorId));
}
+ @GetMapping("/record/get")
+ @Operation(summary = "获得巡检记录详情")
+ @Parameter(name = "id", description = "巡检记录ID", required = true)
+ @PreAuthorize("@ss.hasPermission('ops:inspection:query')")
+ public CommonResult getRecord(@RequestParam("id") Long id) {
+ return success(inspectionRecordService.getRecordDetail(id));
+ }
+
@GetMapping("/record/page")
@Operation(summary = "获得巡检记录分页")
@PreAuthorize("@ss.hasPermission('ops:inspection:query')")
public CommonResult> getRecordPage(@Valid InspectionRecordPageReqVO pageReqVO) {
- PageResult pageResult = inspectionRecordService.getRecordPage(pageReqVO);
- return success(BeanUtils.toBean(pageResult, InspectionRecordRespVO.class));
+ return success(inspectionRecordService.getRecordPage(pageReqVO));
}
@GetMapping("/record/stats")
diff --git a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/inspection/InspectionTemplateController.java b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/inspection/InspectionTemplateController.java
index 09418a4..42f73ad 100644
--- a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/inspection/InspectionTemplateController.java
+++ b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/controller/admin/inspection/InspectionTemplateController.java
@@ -3,6 +3,7 @@ package com.viewsh.module.ops.controller.admin.inspection;
import com.viewsh.framework.common.pojo.CommonResult;
import com.viewsh.framework.common.pojo.PageResult;
import com.viewsh.framework.common.util.object.BeanUtils;
+import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionFormRespVO;
import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionTemplatePageReqVO;
import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionTemplateRespVO;
import com.viewsh.module.ops.environment.controller.admin.inspection.vo.InspectionTemplateSaveReqVO;
@@ -75,12 +76,11 @@ public class InspectionTemplateController {
}
@GetMapping("/list-by-area")
- @Operation(summary = "按区域获取巡检检查项列表(动态表单)")
+ @Operation(summary = "按区域获取巡检表单(扫码后调用)")
@Parameter(name = "areaId", description = "区域ID", required = true)
- @PreAuthorize("@ss.hasPermission('ops:inspection-template:query')")
- public CommonResult> getTemplateListByArea(@RequestParam("areaId") Long areaId) {
- List list = inspectionTemplateService.getTemplateListByAreaId(areaId);
- return success(BeanUtils.toBean(list, InspectionTemplateRespVO.class));
+ @PreAuthorize("@ss.hasPermission('ops:inspection-template:query') and @ss.hasRole('inspector')")
+ public CommonResult getInspectionFormByArea(@RequestParam("areaId") Long areaId) {
+ return success(inspectionTemplateService.getInspectionFormByAreaId(areaId));
}
}
diff --git a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/framework/rpc/config/RpcConfiguration.java b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/framework/rpc/config/RpcConfiguration.java
index a9b6bc9..5e0ba65 100644
--- a/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/framework/rpc/config/RpcConfiguration.java
+++ b/viewsh-module-ops/viewsh-module-ops-server/src/main/java/com/viewsh/module/ops/framework/rpc/config/RpcConfiguration.java
@@ -5,12 +5,14 @@ import com.viewsh.module.iot.api.device.IotDeviceControlApi;
import com.viewsh.module.iot.api.device.IotDeviceQueryApi;
import com.viewsh.module.iot.api.device.IotDeviceStatusQueryApi;
import com.viewsh.module.system.api.notify.NotifyMessageSendApi;
+import com.viewsh.module.system.api.user.AdminUserApi;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Configuration;
@Configuration(value = "opsRpcConfiguration", proxyBeanMethods = false)
@EnableFeignClients(clients = {
NotifyMessageSendApi.class,
+ AdminUserApi.class,
IotDeviceControlApi.class,
IotDeviceQueryApi.class,
IotDeviceStatusQueryApi.class,