Sfoglia il codice sorgente

完善相关接口

hanzhengyi 1 settimana fa
parent
commit
b99f18630c

+ 30 - 9
service-sas/service-sas-biz/src/main/java/com/usky/sas/controller/web/SasMapController.java

@@ -7,6 +7,8 @@ import com.usky.sas.service.vo.MapDeviceBindRequest;
 import com.usky.sas.service.vo.MapListItem;
 import com.usky.sas.service.vo.MapPageRequest;
 import com.usky.sas.service.vo.MapSaveRequest;
+import com.usky.sas.service.vo.MapSaveWithDevicesRequest;
+import com.usky.sas.service.vo.MapTreeItem;
 import lombok.Data;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.DeleteMapping;
@@ -19,15 +21,17 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 /**
- * 电子地图配置接口
- *
- * 对应 API 文档:
- * GET /prod-api/service-sas/map
- * POST /prod-api/service-sas/map
- * PUT /prod-api/service-sas/map/{id}
- * DELETE /prod-api/service-sas/map/{id}
- * POST /prod-api/service-sas/map/{mapId}/device
- * DELETE /prod-api/service-sas/map/{mapId}/device/{deviceId}
+     * 电子地图配置接口
+     *
+     * 对应 API 文档:
+     * GET /prod-api/service-sas/map
+     * POST /prod-api/service-sas/map
+     * PUT /prod-api/service-sas/map/{id}
+     * DELETE /prod-api/service-sas/map/{id}
+     * POST /prod-api/service-sas/map/{mapId}/device
+     * DELETE /prod-api/service-sas/map/{mapId}/device/{deviceId}
+     * GET /prod-api/service-sas/map/tree
+     * POST /prod-api/service-sas/map/saveMapInfo
  */
 @RestController
 @RequestMapping("/map")
@@ -77,6 +81,23 @@ public class SasMapController {
         return ApiResult.success();
     }
 
+    /**
+     * 保存电子地图及设备点位(批量)
+     */
+    @PostMapping("/saveMapInfo")
+    public ApiResult<Void> saveMapInfo(@RequestBody MapSaveWithDevicesRequest request) {
+        sasMapService.saveMapInfo(request);
+        return ApiResult.success();
+    }
+
+    /**
+     * 获取地图导航树形列表
+     */
+    @GetMapping("/tree")
+    public ApiResult<java.util.List<MapTreeItem>> getMapTree() {
+        return ApiResult.success(sasMapService.getMapTree());
+    }
+
     @Data
     public static class CreateMapResponse {
         private String id;

+ 2 - 1
service-sas/service-sas-biz/src/main/java/com/usky/sas/domain/SasMaps.java

@@ -1,5 +1,6 @@
 package com.usky.sas.domain;
 
+import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
@@ -18,7 +19,7 @@ public class SasMaps implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id")
+    @TableId(value = "id", type = IdType.INPUT)
     private String id;
 
     private String name;

+ 12 - 0
service-sas/service-sas-biz/src/main/java/com/usky/sas/service/SasMapService.java

@@ -7,6 +7,8 @@ import com.usky.sas.service.vo.MapListItem;
 import com.usky.sas.service.vo.MapDeviceBindRequest;
 import com.usky.sas.service.vo.MapPageRequest;
 import com.usky.sas.service.vo.MapSaveRequest;
+import com.usky.sas.service.vo.MapSaveWithDevicesRequest;
+import com.usky.sas.service.vo.MapTreeItem;
 
 public interface SasMapService extends CrudService<SasMaps> {
 
@@ -21,5 +23,15 @@ public interface SasMapService extends CrudService<SasMaps> {
     String bindDevice(String mapId, MapDeviceBindRequest request);
 
     void unbindDevice(String mapId, String deviceId);
+
+    /**
+     * 保存电子地图及其设备点位(批量新增/更新/删除)
+     */
+    void saveMapInfo(MapSaveWithDevicesRequest request);
+
+    /**
+     * 获取地图导航树形列表
+     */
+    java.util.List<MapTreeItem> getMapTree();
 }
 

+ 156 - 0
service-sas/service-sas-biz/src/main/java/com/usky/sas/service/impl/SasMapServiceImpl.java

@@ -14,14 +14,19 @@ import com.usky.sas.service.vo.MapDeviceBindRequest;
 import com.usky.sas.service.vo.MapListItem;
 import com.usky.sas.service.vo.MapPageRequest;
 import com.usky.sas.service.vo.MapSaveRequest;
+import com.usky.sas.service.vo.MapSaveWithDevicesRequest;
+import com.usky.sas.service.vo.MapTreeItem;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
@@ -152,6 +157,157 @@ public class SasMapServiceImpl extends AbstractCrudService<SasMapsMapper, SasMap
         mapDeviceMapper.delete(wrapper);
     }
 
+    @Override
+    public void saveMapInfo(MapSaveWithDevicesRequest request) {
+        // 保存或更新地图基础信息
+        SasMaps map = null;
+        if (request.getId() != null && !request.getId().isEmpty()) {
+            map = this.getById(request.getId());
+        }
+        LocalDateTime now = LocalDateTime.now();
+        if (map == null) {
+            map = new SasMaps();
+            String id = request.getId() != null && !request.getId().isEmpty()
+                    ? request.getId()
+                    : UUID.randomUUID().toString();
+            map.setId(id);
+            map.setCreateTime(now);
+        }
+        // 复用 applyMap 逻辑
+        MapSaveRequest saveReq = new MapSaveRequest();
+        saveReq.setName(request.getName());
+        saveReq.setType(request.getType());
+        saveReq.setRemark(request.getRemark());
+        saveReq.setParentId(request.getParentId());
+        saveReq.setWidth(request.getWidth());
+        saveReq.setHeight(request.getHeight());
+        saveReq.setIsMask(request.getIsMask());
+        saveReq.setBackImgId(request.getBackImgId());
+        applyMap(map, saveReq);
+        map.setUpdateTime(now);
+        this.saveOrUpdate(map);
+
+        String mapId = map.getId();
+
+        // 处理地图下设备点位:删除已不存在的,新增或更新现有的
+        LambdaQueryWrapper<SasMapDevice> query = new LambdaQueryWrapper<>();
+        query.eq(SasMapDevice::getMapId, mapId);
+        List<SasMapDevice> dbDevices = mapDeviceMapper.selectList(query);
+
+        Set<String> dbIds = new HashSet<>();
+        if (dbDevices != null) {
+            for (SasMapDevice d : dbDevices) {
+                if (d.getId() != null) {
+                    dbIds.add(d.getId());
+                }
+            }
+        }
+
+        Set<String> newIds = new HashSet<>();
+        if (request.getDevices() != null) {
+            request.getDevices().stream()
+                    .map(MapSaveWithDevicesRequest.MapDeviceItem::getId)
+                    .filter(id -> id != null && !id.isEmpty())
+                    .forEach(newIds::add);
+        }
+
+        // 需要删除的设备ID = 数据库已有 - 新请求中的
+        dbIds.removeAll(newIds);
+        if (!dbIds.isEmpty()) {
+            mapDeviceMapper.deleteBatchIds(dbIds);
+        }
+
+        // 新增或更新设备点位
+        if (request.getDevices() != null && !request.getDevices().isEmpty()) {
+            for (MapSaveWithDevicesRequest.MapDeviceItem item : request.getDevices()) {
+                SasMapDevice entity;
+                boolean exists = item.getId() != null && !item.getId().isEmpty();
+                if (exists) {
+                    entity = mapDeviceMapper.selectById(item.getId());
+                    if (entity == null) {
+                        entity = new SasMapDevice();
+                        entity.setId(item.getId());
+                        entity.setCreateTime(now);
+                    }
+                } else {
+                    entity = new SasMapDevice();
+                    entity.setId(UUID.randomUUID().toString());
+                    entity.setCreateTime(now);
+                }
+                entity.setMapId(mapId);
+                entity.setDeviceId(item.getDeviceId());
+                entity.setImgId(item.getImgId());
+                entity.setType(item.getType());
+                if (item.getX() != null) {
+                    entity.setX(BigDecimal.valueOf(item.getX()));
+                } else {
+                    entity.setX(null);
+                }
+                if (item.getY() != null) {
+                    entity.setY(BigDecimal.valueOf(item.getY()));
+                } else {
+                    entity.setY(null);
+                }
+                entity.setWidth(item.getWidth());
+                entity.setHeight(item.getHeight());
+                entity.setAngle(item.getAngle());
+                entity.setText(item.getText());
+                entity.setUpdateTime(now);
+
+                if (exists && mapDeviceMapper.selectById(entity.getId()) != null) {
+                    mapDeviceMapper.updateById(entity);
+                } else {
+                    mapDeviceMapper.insert(entity);
+                }
+            }
+        }
+    }
+
+    @Override
+    public List<MapTreeItem> getMapTree() {
+        // 查询所有地图节点
+        List<SasMaps> maps = this.list();
+        if (maps == null || maps.isEmpty()) {
+            return Collections.emptyList();
+        }
+
+        // 先将所有节点转换为 MapTreeItem,并放入 map 方便后续组装 children
+        Map<String, MapTreeItem> nodeMap = new HashMap<>();
+        for (SasMaps m : maps) {
+            MapTreeItem node = new MapTreeItem();
+            node.setId(m.getId());
+            node.setName(m.getName());
+            node.setType(m.getType());
+            node.setRemark(m.getRemark());
+            node.setParentId(m.getParentId());
+            node.setWidth(m.getWidth());
+            node.setHeight(m.getHeight());
+            node.setIsMask(m.getIsMask());
+            node.setBackImgId(m.getBackImgId());
+            node.setCreateTime(m.getCreateTime());
+            node.setUpdateTime(m.getUpdateTime());
+            nodeMap.put(m.getId(), node);
+        }
+
+        // 组装树结构
+        List<MapTreeItem> roots = new java.util.ArrayList<>();
+        for (SasMaps m : maps) {
+            MapTreeItem node = nodeMap.get(m.getId());
+            if (m.getParentId() == null || m.getParentId().isEmpty()) {
+                roots.add(node);
+            } else {
+                MapTreeItem parent = nodeMap.get(m.getParentId());
+                if (parent != null) {
+                    parent.getChildren().add(node);
+                } else {
+                    // 若找不到父节点,则作为根节点返回,避免数据丢失
+                    roots.add(node);
+                }
+            }
+        }
+        return roots;
+    }
+
     /**
      * 递归删除地图及其子地图,同时删除绑定设备
      */

+ 130 - 12
service-sas/service-sas-biz/src/main/java/com/usky/sas/service/impl/SasOneStandardSixRealitiesServiceImpl.java

@@ -13,6 +13,8 @@ import com.usky.sas.domain.SasVillage;
 import com.usky.sas.domain.SasEquip;
 import com.usky.sas.domain.SasEquipCode;
 import com.usky.sas.domain.SasEntrance;
+import com.usky.sas.domain.SasCredentialTypeCode;
+import com.usky.sas.domain.SasSystemConfig;
 import com.usky.sas.mapper.SasBuildingMapper;
 import com.usky.sas.mapper.SasHouseMapper;
 import com.usky.sas.mapper.SasPersonMapper;
@@ -23,6 +25,8 @@ import com.usky.sas.mapper.SasEquipMapper;
 import com.usky.sas.mapper.SasEquipCodeMapper;
 import com.usky.sas.mapper.SasEntranceMapper;
 import com.usky.sas.mapper.SasGisMapper;
+import com.usky.sas.mapper.SasCredentialTypeCodeMapper;
+import com.usky.sas.mapper.SasSystemConfigMapper;
 import com.usky.sas.domain.SasGis;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -38,6 +42,7 @@ import com.usky.sas.service.dto.agbox.BuildingVO;
 import com.usky.sas.service.dto.agbox.HouseVo;
 import com.usky.sas.service.vo.*;
 import cn.hutool.http.HttpRequest;
+import cn.hutool.core.util.IdcardUtil;
 import cn.hutool.json.JSONUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -91,21 +96,66 @@ public class SasOneStandardSixRealitiesServiceImpl implements SasOneStandardSixR
     @Autowired
     private SasEntranceMapper sasEntranceMapper;
 
+    @Autowired
+    private SasCredentialTypeCodeMapper sasCredentialTypeCodeMapper;
+
+    @Autowired
+    private SasSystemConfigMapper sasSystemConfigMapper;
+
     @Override
     public CommonPage<PowerListItem> powerPage(OneStandardSixRealitiesPageRequest request) {
-        IPage<SasPerson> page = new Page<>(request.getCurrent(), request.getSize());
-        LambdaQueryWrapper<SasPerson> wrapper = new LambdaQueryWrapper<>();
-        // 这里简单按 power_code 是否非空作为实有力量筛选,占位实现
-        wrapper.isNotNull(SasPerson::getPowerCode);
-        page = sasPersonMapper.selectPage(page, wrapper);
-        List<SasPerson> records = page.getRecords();
-        if (records == null) {
-            records = Collections.emptyList();
+        // 先尝试从 AG 获取实有力量分页,失败或未配置时回退到本地人员表
+        com.usky.sas.domain.SasConfig config = sasConfigService.getConfig();
+        if (config == null || config.getKeyds() == null || config.getHost() == null) {
+            log.debug("实有力量分页:未配置 AG,走本地人员表");
+            return localPowerPage(request);
+        }
+
+        String villageCode = request.getVillageCode();
+        if (villageCode == null || villageCode.isEmpty()) {
+            villageCode = getVillageCodeForSync();
+        }
+        if (villageCode == null || villageCode.isEmpty()) {
+            log.debug("实有力量分页:无可用地块编码,走本地人员表");
+            return localPowerPage(request);
+        }
+
+        int pageNo = request.getCurrent() != null ? request.getCurrent() : 1;
+        int pageSize = request.getSize() != null ? request.getSize() : 10;
+
+        try {
+            String baseUrl = buildAgboxBaseUrl(config.getHost(), null);
+            String villageUrl = baseUrl + AGBOX_VILLAGE_PATH;
+            Map<String, Object> params = new HashMap<>();
+            params.put("page", pageNo);
+            params.put("pageSize", pageSize);
+            params.put("code", villageCode);
+            JsonRpcRequest getPowerJson = new JsonRpcRequest("getPower", params, null);
+            Map<String, Object> requestBody = new HashMap<>();
+            requestBody.put("key", config.getKeyds());
+            requestBody.put("json", JSONUtil.toJsonStr(getPowerJson));
+            log.info("请求AG实有力量分页(getPower):page={}, pageSize={}, code={}", pageNo, pageSize, villageCode);
+
+            ObjectMapper mapper = new ObjectMapper();
+            String resultStr = postWithRetry(villageUrl, requestBody);
+            PowerVo powerVo = mapper.readValue(resultStr, PowerVo.class);
+            PowerVo.PowerResult result = powerVo != null ? powerVo.getResult() : null;
+            List<PowerVo.Power> powerList = (result != null && result.getPowerList() != null)
+                    ? result.getPowerList() : Collections.emptyList();
+
+            SasSystemConfig systemConfig = sasSystemConfigMapper.selectOne(new LambdaQueryWrapper<SasSystemConfig>().last("limit 1"));
+            boolean maskIdCard = systemConfig != null && Boolean.TRUE.equals(systemConfig.getMaskIdCardNo());
+
+            List<PowerListItem> list = powerList.stream()
+                    .map(p -> fromPowerToListItem(p, maskIdCard))
+                    .collect(Collectors.toList());
+
+            long total = (result != null && result.getCount() != null) ? result.getCount() : 0L;
+            return new CommonPage<>(list, total, (long) pageNo, (long) pageSize);
+        } catch (Exception e) {
+            log.warn("实有力量分页请求 AG 失败,回退本地人员表:{}", e.getMessage());
+            return localPowerPage(request);
         }
-        List<PowerListItem> list = records.stream()
-                .map(this::fromPersonToPower)
-                .collect(Collectors.toList());
-        return new CommonPage<>(list, page.getTotal(), page.getCurrent(), page.getSize());
     }
 
     @Override
@@ -1049,6 +1099,11 @@ public class SasOneStandardSixRealitiesServiceImpl implements SasOneStandardSixR
         PowerListItem item = new PowerListItem();
         item.setPersonCode(p.getPersonCode());
         item.setName(p.getName());
+        item.setCredentialType(p.getCredentialType());
+        item.setCredentialNo(p.getCredentialNo());
+        item.setPhone1(p.getPhone1());
+        item.setPhone2(p.getPhone2());
+        item.setPhone3(p.getPhone3());
         item.setPowerCode(p.getPowerCode());
         item.setPowerName(null);
         item.setSecurityCardNo(p.getSecurityCardNo());
@@ -1057,6 +1112,69 @@ public class SasOneStandardSixRealitiesServiceImpl implements SasOneStandardSixR
         return item;
     }
 
+    /**
+     * AG Power 数据转列表项
+     */
+    private PowerListItem fromPowerToListItem(PowerVo.Power power, boolean maskIdCard) {
+        PowerListItem item = new PowerListItem();
+        item.setPersonCode(power.getPersonCode());
+        item.setName(power.getName());
+        item.setCredentialType(power.getCredentialType());
+        if (power.getCredentialType() != null) {
+            SasCredentialTypeCode ct = sasCredentialTypeCodeMapper.selectById(power.getCredentialType());
+            if (ct != null) {
+                item.setCredentialTypeName(ct.getName());
+            }
+        }
+        if (power.getCredentialNo() != null) {
+            String no = power.getCredentialNo();
+            if (maskIdCard && no.length() > 8) {
+                item.setCredentialNo(IdcardUtil.hide(no, 4, no.length() - 4));
+            } else {
+                item.setCredentialNo(no);
+            }
+        }
+        // 电话列表拆分到 phone1/2/3
+        if (power.getPhone() != null && !power.getPhone().isEmpty()) {
+            if (power.getPhone().size() >= 1) item.setPhone1(power.getPhone().get(0));
+            if (power.getPhone().size() >= 2) item.setPhone2(power.getPhone().get(1));
+            if (power.getPhone().size() >= 3) item.setPhone3(power.getPhone().get(2));
+        }
+        item.setPowerCode(power.getPowerCode());
+        item.setPowerName(null);
+        item.setSecurityCardNo(power.getSecurityCardNo());
+        item.setSecurityDutiesCode(power.getSecurityDutiesCode() == null ? null : String.valueOf(power.getSecurityDutiesCode()));
+        if (power.getUpdateTime() != null && !power.getUpdateTime().isEmpty()) {
+            try {
+                item.setUpdateTime(LocalDateTime.parse(
+                        power.getUpdateTime(),
+                        java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+            } catch (Exception ignored) {
+                // ignore parse error, keep null
+            }
+        }
+        return item;
+    }
+
+    /**
+     * 本地人员表分页作为回退策略
+     */
+    private CommonPage<PowerListItem> localPowerPage(OneStandardSixRealitiesPageRequest request) {
+        IPage<SasPerson> page = new Page<>(request.getCurrent(), request.getSize());
+        LambdaQueryWrapper<SasPerson> wrapper = new LambdaQueryWrapper<>();
+        // 这里简单按 power_code 是否非空作为实有力量筛选
+        wrapper.isNotNull(SasPerson::getPowerCode);
+        page = sasPersonMapper.selectPage(page, wrapper);
+        List<SasPerson> records = page.getRecords();
+        if (records == null) {
+            records = Collections.emptyList();
+        }
+        List<PowerListItem> list = records.stream()
+                .map(this::fromPersonToPower)
+                .collect(Collectors.toList());
+        return new CommonPage<>(list, page.getTotal(), page.getCurrent(), page.getSize());
+    }
+
     private AreaListItem fromBuildingToArea(SasBuilding b) {
         AreaListItem item = new AreaListItem();
         item.setBuildingCode(b.getBuildingCode());

+ 62 - 0
service-sas/service-sas-biz/src/main/java/com/usky/sas/service/vo/MapSaveWithDevicesRequest.java

@@ -0,0 +1,62 @@
+package com.usky.sas.service.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 电子地图保存请求:包含地图基础信息及设备点位列表
+ */
+@Data
+public class MapSaveWithDevicesRequest {
+
+    /** 地图主键ID,若为空则视为新建 */
+    private String id;
+
+    private String name;
+
+    private Integer type;
+
+    private String remark;
+
+    private String parentId;
+
+    private Double width;
+
+    private Double height;
+
+    private Boolean isMask;
+
+    private String backImgId;
+
+    /**
+     * 地图下的设备点位列表
+     */
+    private List<MapDeviceItem> devices;
+
+    @Data
+    public static class MapDeviceItem {
+
+        /** 地图设备主键ID,空表示新建 */
+        private String id;
+
+        private String deviceId;
+
+        private String imgId;
+
+        private String type;
+
+        private Double x;
+
+        private Double y;
+
+        private Double width;
+
+        private Double height;
+
+        private Double angle;
+
+        private String text;
+    }
+}
+

+ 42 - 0
service-sas/service-sas-biz/src/main/java/com/usky/sas/service/vo/MapTreeItem.java

@@ -0,0 +1,42 @@
+package com.usky.sas.service.vo;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 地图导航树节点
+ */
+@Data
+public class MapTreeItem {
+
+    private String id;
+
+    private String name;
+
+    private Integer type;
+
+    private String remark;
+
+    private String parentId;
+
+    private Double width;
+
+    private Double height;
+
+    private Boolean isMask;
+
+    private String backImgId;
+
+    private LocalDateTime createTime;
+
+    private LocalDateTime updateTime;
+
+    /**
+     * 子地图列表
+     */
+    private List<MapTreeItem> children = new ArrayList<>();
+}
+

+ 18 - 0
service-sas/service-sas-biz/src/main/java/com/usky/sas/service/vo/PowerListItem.java

@@ -14,6 +14,24 @@ public class PowerListItem {
 
     private String name;
 
+    /** 证件类型编码 */
+    private Integer credentialType;
+
+    /** 证件类型名称 */
+    private String credentialTypeName;
+
+    /** 证件号码(按系统配置可能脱敏) */
+    private String credentialNo;
+
+    /** 电话1 */
+    private String phone1;
+
+    /** 电话2 */
+    private String phone2;
+
+    /** 电话3 */
+    private String phone3;
+
     private String powerCode;
 
     private String powerName;