Просмотр исходного кода

feat:燃气管网-基础数据管理

null 1 месяц назад
Родитель
Сommit
d0846c24ec

+ 39 - 0
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/gasbasic/GasEquipmentController.java

@@ -1,7 +1,9 @@
 package com.zksy.web.controller.gasbasic;
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zksy.base.domain.EquipmentPointRel;
 import com.zksy.base.domain.EquipmentStatus;
+import com.zksy.base.domain.vo.EquipmentFullVO;
 import com.zksy.base.service.EquipmentBaseService;
 import com.zksy.base.mapper.EquipmentPointRelMapper;
 import com.zksy.base.mapper.EquipmentStatusMapper;
@@ -76,4 +78,41 @@ public class GasEquipmentController {
         boolean deleted = equipmentPointRelMapper.deleteById(relId) > 0;
         return deleted ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
     }
+
+    @GetMapping("/point-rel/by-point/{pointId}")
+    @ApiOperation("获取管点关联的设备")
+    @Anonymous
+    public AjaxResult getPointRelByPoint(@PathVariable String pointId) {
+        LambdaQueryWrapper<EquipmentPointRel> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(EquipmentPointRel::getPointId, pointId);
+        List<EquipmentPointRel> list = equipmentPointRelMapper.selectList(wrapper);
+        return AjaxResult.success(list);
+    }
+
+    @PostMapping("/point-rel/save-batch")
+    @ApiOperation("批量关联设备到管点")
+    @Anonymous
+    public AjaxResult savePointRelBatch(@RequestBody List<EquipmentPointRel> relList) {
+        if (relList == null || relList.isEmpty()) {
+            return AjaxResult.error("关联列表不能为空");
+        }
+        for (EquipmentPointRel rel : relList) {
+            equipmentPointRelMapper.insert(rel);
+        }
+        return AjaxResult.success("批量关联成功");
+    }
+
+    @GetMapping("/findFullByPage")
+    @ApiOperation("设备全信息分页查询(联查管点→管线→状态)")
+    @Anonymous
+    public AjaxResult findFullByPage(@RequestParam(defaultValue = "1") Long pageNum,
+                                     @RequestParam(defaultValue = "10") Long pageSize,
+                                     @RequestParam(required = false) String equipmentCode,
+                                     @RequestParam(required = false) String equipmentName,
+                                     @RequestParam(required = false) String equipmentModel,
+                                     @RequestParam(required = false) String manufacturer) {
+        Page<EquipmentFullVO> page = equipmentBaseService.findFullByPage(pageNum, pageSize,
+                equipmentCode, equipmentName, equipmentModel, manufacturer);
+        return AjaxResult.success(page);
+    }
 }

+ 129 - 0
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/gasbasic/GasPipePointController.java

@@ -0,0 +1,129 @@
+package com.zksy.web.controller.gasbasic;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zksy.base.domain.GasPipePoint;
+import com.zksy.base.domain.GasPipePointDeviceRel;
+import com.zksy.base.dto.GasPipePointPageInDTO;
+import com.zksy.base.mapper.GasPipePointDeviceRelMapper;
+import com.zksy.base.service.GasPipePointService;
+import com.zksy.common.annotation.Anonymous;
+import com.zksy.common.annotation.Log;
+import com.zksy.common.core.domain.AjaxResult;
+import com.zksy.common.enums.BusinessType;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Slf4j
+@RestController
+@RequestMapping("/api/gas-pipe-point")
+@Api(tags = "燃气管点管理")
+public class GasPipePointController {
+
+    @Autowired
+    private GasPipePointService service;
+
+    @Autowired
+    private GasPipePointDeviceRelMapper deviceRelMapper;
+
+    @GetMapping("/findByPage")
+    @ApiOperation("管点分页查询")
+    @Anonymous
+    public AjaxResult findByPage(GasPipePointPageInDTO dto) {
+        Page<GasPipePoint> page = service.queryByPage(dto);
+        return AjaxResult.success(page);
+    }
+
+    @GetMapping("/getById/{id}")
+    @ApiOperation("根据ID查询管点")
+    @Anonymous
+    public AjaxResult getById(@PathVariable Long id) {
+        GasPipePoint entity = service.getById(id);
+        return entity != null ? AjaxResult.success(entity) : AjaxResult.error("管点信息不存在");
+    }
+
+    @GetMapping("/list-by-network/{networkId}")
+    @ApiOperation("按管线ID查询管点列表")
+    @Anonymous
+    public AjaxResult listByNetworkId(@PathVariable String networkId) {
+        return AjaxResult.success(service.listByNetworkId(networkId));
+    }
+
+    @GetMapping("/options")
+    @ApiOperation("管点下拉选项")
+    @Anonymous
+    public AjaxResult options() {
+        return AjaxResult.success(service.getOptions());
+    }
+
+    @PostMapping("/save")
+    @ApiOperation("新增管点")
+    @Log(title = "新增燃气管点", businessType = BusinessType.INSERT)
+    public AjaxResult save(@RequestBody GasPipePoint entity) {
+        boolean saved = service.saveWithCheck(entity);
+        return saved ? AjaxResult.success("新增成功", saved) : AjaxResult.error("新增失败");
+    }
+
+    @PutMapping("/updateById")
+    @ApiOperation("修改管点")
+    @Log(title = "修改燃气管点", businessType = BusinessType.UPDATE)
+    public AjaxResult updateById(@RequestBody GasPipePoint entity) {
+        boolean updated = service.updateWithCheck(entity);
+        return updated ? AjaxResult.success("修改成功", updated) : AjaxResult.error("修改失败");
+    }
+
+    @DeleteMapping("/deleteById")
+    @ApiOperation("删除管点")
+    @Log(title = "删除燃气管点", businessType = BusinessType.DELETE)
+    public AjaxResult deleteById(@RequestParam Long id) {
+        boolean deleted = service.removeWithCheck(id);
+        return deleted ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
+    }
+
+    // ============ 管点-设备关联 ============
+
+    @GetMapping("/device/list/{pointId}")
+    @ApiOperation("获取管点关联的设备列表")
+    @Anonymous
+    public AjaxResult listDevices(@PathVariable Long pointId) {
+        LambdaQueryWrapper<GasPipePointDeviceRel> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(GasPipePointDeviceRel::getPointId, pointId);
+        wrapper.orderByDesc(GasPipePointDeviceRel::getCreateTime);
+        List<GasPipePointDeviceRel> list = deviceRelMapper.selectList(wrapper);
+        return AjaxResult.success(list);
+    }
+
+    @PostMapping("/device/save")
+    @ApiOperation("关联设备到管点")
+    @Anonymous
+    public AjaxResult saveDeviceRel(@RequestBody GasPipePointDeviceRel rel) {
+        boolean saved = deviceRelMapper.insert(rel) > 0;
+        return saved ? AjaxResult.success("关联成功") : AjaxResult.error("关联失败");
+    }
+
+    @PostMapping("/device/save-batch")
+    @ApiOperation("批量关联设备到管点")
+    @Anonymous
+    public AjaxResult saveDeviceRelBatch(@RequestBody List<GasPipePointDeviceRel> relList) {
+        if (relList == null || relList.isEmpty()) {
+            return AjaxResult.error("关联列表不能为空");
+        }
+        for (GasPipePointDeviceRel rel : relList) {
+            deviceRelMapper.insert(rel);
+        }
+        return AjaxResult.success("批量关联成功");
+    }
+
+    @DeleteMapping("/device/delete")
+    @ApiOperation("删除管点设备关联")
+    @Anonymous
+    public AjaxResult deleteDeviceRel(@RequestParam Long relId) {
+        boolean deleted = deviceRelMapper.deleteById(relId) > 0;
+        return deleted ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
+    }
+}

+ 84 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/domain/GasPipePoint.java

@@ -0,0 +1,84 @@
+package com.zksy.base.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 燃气管点信息表
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("gas_pipe_point")
+public class GasPipePoint {
+
+    @TableId(value = "point_id", type = IdType.AUTO)
+    @ApiModelProperty("管点ID")
+    private Long pointId;
+
+    @ApiModelProperty("管点编码")
+    private String pointCode;
+
+    @ApiModelProperty("管点名称")
+    private String pointName;
+
+    @ApiModelProperty("所属管线ID")
+    private String networkId;
+
+    @ApiModelProperty("所属管线名称")
+    private String networkName;
+
+    @ApiModelProperty("管点类型(阀门/调压/计量/阴极保护/弯头/三通/其它)")
+    private String pointType;
+
+    @ApiModelProperty("经度")
+    private BigDecimal longitude;
+
+    @ApiModelProperty("纬度")
+    private BigDecimal latitude;
+
+    @ApiModelProperty("地址/位置描述")
+    private String address;
+
+    @ApiModelProperty("管径(毫米)")
+    private BigDecimal diameter;
+
+    @ApiModelProperty("材质")
+    private String material;
+
+    @ApiModelProperty("埋深(米)")
+    private BigDecimal depth;
+
+    @ApiModelProperty("建设日期")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private String buildDate;
+
+    @ApiModelProperty("状态(0-正常 1-异常 2-停用)")
+    private String status;
+
+    @ApiModelProperty("备注")
+    private String remark;
+
+    @ApiModelProperty("创建人")
+    private String createBy;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("更新人")
+    private String updateBy;
+
+    @ApiModelProperty("更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime updateTime;
+}

+ 42 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/domain/GasPipePointDeviceRel.java

@@ -0,0 +1,42 @@
+package com.zksy.base.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * 管点-设备关联表
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("gas_pipe_point_device_rel")
+public class GasPipePointDeviceRel {
+
+    @TableId(value = "rel_id", type = IdType.AUTO)
+    @ApiModelProperty("关联ID")
+    private Long relId;
+
+    @ApiModelProperty("管点ID")
+    private Long pointId;
+
+    @ApiModelProperty("设备ID")
+    private String equipmentId;
+
+    @ApiModelProperty("设备名称(冗余字段,便于列表展示)")
+    private String equipmentName;
+
+    @ApiModelProperty("设备类型(冗余字段)")
+    private String equipmentType;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+}

+ 124 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/domain/vo/EquipmentFullVO.java

@@ -0,0 +1,124 @@
+package com.zksy.base.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+/**
+ * 设备全信息VO — 联查管线→管点→设备→状态
+ */
+@Data
+public class EquipmentFullVO {
+
+    // ===== equipment_base =====
+    @ApiModelProperty("设备ID")
+    private String equipmentId;
+
+    @ApiModelProperty("设备编码")
+    private String equipmentCode;
+
+    @ApiModelProperty("设备名称")
+    private String equipmentName;
+
+    @ApiModelProperty("设备型号")
+    private String equipmentModel;
+
+    @ApiModelProperty("规格参数")
+    private String equipmentSpec;
+
+    @ApiModelProperty("制造商")
+    private String manufacturer;
+
+    @ApiModelProperty("生产日期")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date productionDate;
+
+    @ApiModelProperty("设备类别ID")
+    private String equipmentTypeId;
+
+    @ApiModelProperty("资产价值")
+    private Double assetValue;
+
+    @ApiModelProperty("使用年限")
+    private Integer useLife;
+
+    @ApiModelProperty("经度")
+    private BigDecimal longitude;
+
+    @ApiModelProperty("纬度")
+    private BigDecimal latitude;
+
+    @ApiModelProperty("安装位置")
+    private String equipmentLocation;
+
+    @ApiModelProperty("安装时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime installTime;
+
+    @ApiModelProperty("维护人员")
+    private String maintainer;
+
+    @ApiModelProperty("联系方式")
+    private String maintainerPhone;
+
+    @ApiModelProperty("备注")
+    private String remark;
+
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    // ===== equipment_status =====
+    @ApiModelProperty("设备当前状态:1-在用,2-闲置,3-维修,4-报废,5-待入库")
+    private Integer currentStatus;
+
+    @ApiModelProperty("报警状态:0-正常,1-报警")
+    private Integer alarmStatus;
+
+    @ApiModelProperty("在线状态:0-离线,1-在线")
+    private Integer onlineStatus;
+
+    @ApiModelProperty("最后一次维护日期")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    private Date lastMaintainDate;
+
+    @ApiModelProperty("下次预计维护日期")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime nextMaintainDate;
+
+    // ===== gas_pipe_point =====
+    @ApiModelProperty("管点ID")
+    private Long pointId;
+
+    @ApiModelProperty("管点编码")
+    private String pointCode;
+
+    @ApiModelProperty("管点名称")
+    private String pointName;
+
+    @ApiModelProperty("管点类型")
+    private String pointType;
+
+    @ApiModelProperty("管点地址")
+    private String pointAddress;
+
+    // ===== pipe_network_base =====
+    @ApiModelProperty("管线ID")
+    private String networkId;
+
+    @ApiModelProperty("管线编码")
+    private String networkCode;
+
+    @ApiModelProperty("管线名称")
+    private String networkName;
+
+    @ApiModelProperty("管线类型")
+    private String networkType;
+
+    @ApiModelProperty("管线等级")
+    private String networkLevel;
+}

+ 34 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/dto/GasPipePointPageInDTO.java

@@ -0,0 +1,34 @@
+package com.zksy.base.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@ApiModel(value = "管点分页查询入参", description = "管点分页查询入参")
+public class GasPipePointPageInDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "管点名称")
+    private String pointName;
+
+    @ApiModelProperty(value = "管点编码")
+    private String pointCode;
+
+    @ApiModelProperty(value = "所属管线ID")
+    private String networkId;
+
+    @ApiModelProperty(value = "管点类型")
+    private String pointType;
+
+    @ApiModelProperty(value = "状态")
+    private String status;
+
+    @ApiModelProperty(value = "当前记录起始索引", required = true)
+    private Long pageNum;
+
+    @ApiModelProperty(value = "每页显示记录数", required = true)
+    private Long pageSize;
+}

+ 9 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/mapper/GasPipePointDeviceRelMapper.java

@@ -0,0 +1,9 @@
+package com.zksy.base.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zksy.base.domain.GasPipePointDeviceRel;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface GasPipePointDeviceRelMapper extends BaseMapper<GasPipePointDeviceRel> {
+}

+ 9 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/mapper/GasPipePointMapper.java

@@ -0,0 +1,9 @@
+package com.zksy.base.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zksy.base.domain.GasPipePoint;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface GasPipePointMapper extends BaseMapper<GasPipePoint> {
+}

+ 5 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/EquipmentBaseService.java

@@ -3,6 +3,7 @@ package com.zksy.base.service;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.zksy.base.domain.EquipmentBase;
+import com.zksy.base.domain.vo.EquipmentFullVO;
 import com.zksy.manhole.dto.in.ManholeDeviceListInDTO;
 import com.zksy.manhole.dto.in.ManholeDevicePageInDTO;
 import com.zksy.manhole.dto.out.EquipmentBaseOutDTO;
@@ -13,6 +14,10 @@ import java.util.Map;
 
 public interface EquipmentBaseService extends IService<EquipmentBase> {
 
+    Page<EquipmentFullVO> findFullByPage(long pageNum, long pageSize,
+                                         String equipmentCode, String equipmentName,
+                                         String equipmentModel, String manufacturer);
+
     Page<EquipmentBase> findByPage(long pageNum, long pageSize,
                                    String equipmentCode, String equipmentName,
                                    String equipmentModel, String manufacturer);

+ 23 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/GasPipePointService.java

@@ -0,0 +1,23 @@
+package com.zksy.base.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zksy.base.domain.GasPipePoint;
+import com.zksy.base.dto.GasPipePointPageInDTO;
+
+import java.util.List;
+
+public interface GasPipePointService extends IService<GasPipePoint> {
+
+    Page<GasPipePoint> queryByPage(GasPipePointPageInDTO dto);
+
+    List<GasPipePoint> listByNetworkId(String networkId);
+
+    List<GasPipePoint> getOptions();
+
+    boolean saveWithCheck(GasPipePoint entity);
+
+    boolean updateWithCheck(GasPipePoint entity);
+
+    boolean removeWithCheck(Long pointId);
+}

+ 118 - 8
pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/impl/EquipmentBaseServiceImpl.java

@@ -11,16 +11,11 @@ import com.zksy.base.domain.*;
 import com.zksy.base.mapper.*;
 import com.zksy.base.alarm.domain.WarningThreshold;
 import com.zksy.base.alarm.mapper.WarningThresholdMapper;
-import com.zksy.base.domain.EquipmentBase;
-import com.zksy.base.domain.EquipmentMaintain;
-import com.zksy.base.domain.EquipmentStatus;
-import com.zksy.base.domain.EquipmentType;
+import com.zksy.base.domain.*;
+import com.zksy.base.domain.vo.EquipmentFullVO;
 import com.zksy.base.manhole.domain.ManholeData;
 import com.zksy.base.manhole.mapper.ManholeDataMapper;
-import com.zksy.base.mapper.EquipmentBaseMapper;
-import com.zksy.base.mapper.EquipmentMaintainMapper;
-import com.zksy.base.mapper.EquipmentStatusMapper;
-import com.zksy.base.mapper.EquipmentTypeMapper;
+import com.zksy.base.mapper.*;
 import com.zksy.base.service.EquipmentBaseService;
 import com.zksy.common.exception.ServiceException;
 import com.zksy.manhole.dto.in.ManholeDeviceListInDTO;
@@ -66,6 +61,15 @@ public class EquipmentBaseServiceImpl extends ServiceImpl<EquipmentBaseMapper, E
     @Autowired
     private ManholeDataMapper manholeDataMapper;
 
+    @Autowired
+    private GasPipePointDeviceRelMapper gasPipePointDeviceRelMapper;
+
+    @Autowired
+    private GasPipePointMapper gasPipePointMapper;
+
+    @Autowired
+    private PipeNetworkBaseMapper pipeNetworkBaseMapper;
+
     @Override
     public Page<EquipmentBase> findByPage(long pageNum, long pageSize,
                                           String equipmentCode, String equipmentName,
@@ -484,6 +488,112 @@ public class EquipmentBaseServiceImpl extends ServiceImpl<EquipmentBaseMapper, E
         return result;
     }
 
+    @Override
+    public Page<EquipmentFullVO> findFullByPage(long pageNum, long pageSize,
+                                                String equipmentCode, String equipmentName,
+                                                String equipmentModel, String manufacturer) {
+        // 1. 分页查询设备基础信息
+        Page<EquipmentBase> page = new Page<>(pageNum, pageSize);
+        LambdaQueryWrapper<EquipmentBase> qw = new LambdaQueryWrapper<>();
+        if (equipmentCode != null && !equipmentCode.isEmpty()) {
+            qw.like(EquipmentBase::getEquipmentCode, equipmentCode);
+        }
+        if (equipmentName != null && !equipmentName.isEmpty()) {
+            qw.like(EquipmentBase::getEquipmentName, equipmentName);
+        }
+        if (equipmentModel != null && !equipmentModel.isEmpty()) {
+            qw.like(EquipmentBase::getEquipmentModel, equipmentModel);
+        }
+        if (manufacturer != null && !manufacturer.isEmpty()) {
+            qw.like(EquipmentBase::getManufacturer, manufacturer);
+        }
+        qw.orderByDesc(EquipmentBase::getCreateTime);
+        Page<EquipmentBase> basePage = this.page(page, qw);
+        List<EquipmentBase> equipmentList = basePage.getRecords();
+        if (CollUtil.isEmpty(equipmentList)) {
+            Page<EquipmentFullVO> emptyPage = new Page<>(pageNum, pageSize, 0);
+            emptyPage.setRecords(new ArrayList<>());
+            return emptyPage;
+        }
+
+        List<String> equipmentIds = equipmentList.stream()
+                .map(EquipmentBase::getEquipmentId).collect(Collectors.toList());
+
+        // 2. 批量查设备状态
+        List<EquipmentStatus> statusList = equipmentStatusMapper.selectList(
+                new LambdaQueryWrapper<EquipmentStatus>().in(EquipmentStatus::getEquipmentId, equipmentIds));
+        Map<String, EquipmentStatus> statusMap = statusList.stream()
+                .collect(Collectors.toMap(EquipmentStatus::getEquipmentId, Function.identity(), (a, b) -> a));
+
+        // 3. 批量查管点-设备关联 (gas_pipe_point_device_rel)
+        List<GasPipePointDeviceRel> allRels = gasPipePointDeviceRelMapper.selectList(
+                new LambdaQueryWrapper<GasPipePointDeviceRel>().in(GasPipePointDeviceRel::getEquipmentId, equipmentIds));
+        Map<String, GasPipePointDeviceRel> relMap = allRels.stream()
+                .collect(Collectors.toMap(GasPipePointDeviceRel::getEquipmentId, Function.identity(), (a, b) -> a));
+
+        // 4. 批量查管点
+        List<Long> pointIds = allRels.stream().map(GasPipePointDeviceRel::getPointId).distinct().collect(Collectors.toList());
+        Map<Long, GasPipePoint> pointMap = new HashMap<>();
+        if (CollUtil.isNotEmpty(pointIds)) {
+            List<GasPipePoint> pointList = gasPipePointMapper.selectBatchIds(pointIds);
+            pointMap = pointList.stream()
+                    .collect(Collectors.toMap(GasPipePoint::getPointId, Function.identity(), (a, b) -> a));
+        }
+
+        // 5. 批量查管线
+        List<String> networkIds = pointMap.values().stream()
+                .map(GasPipePoint::getNetworkId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
+        Map<String, PipeNetworkBase> networkMap = new HashMap<>();
+        if (CollUtil.isNotEmpty(networkIds)) {
+            List<PipeNetworkBase> networkList = pipeNetworkBaseMapper.selectBatchIds(networkIds);
+            networkMap = networkList.stream()
+                    .collect(Collectors.toMap(PipeNetworkBase::getNetworkId, Function.identity(), (a, b) -> a));
+        }
+
+        // 6. 组装VO
+        List<EquipmentFullVO> voList = new ArrayList<>();
+        for (EquipmentBase equip : equipmentList) {
+            EquipmentFullVO vo = new EquipmentFullVO();
+            BeanUtil.copyProperties(equip, vo);
+
+            EquipmentStatus status = statusMap.get(equip.getEquipmentId());
+            if (status != null) {
+                vo.setCurrentStatus(status.getCurrentStatus());
+                vo.setAlarmStatus(status.getAlarmStatus());
+                vo.setOnlineStatus(status.getOnlineStatus());
+                vo.setLastMaintainDate(status.getLastMaintainDate());
+                vo.setNextMaintainDate(status.getNextMaintainDate());
+            }
+
+            GasPipePointDeviceRel rel = relMap.get(equip.getEquipmentId());
+            if (rel != null) {
+                GasPipePoint point = pointMap.get(rel.getPointId());
+                if (point != null) {
+                    vo.setPointId(point.getPointId());
+                    vo.setPointCode(point.getPointCode());
+                    vo.setPointName(point.getPointName());
+                    vo.setPointType(point.getPointType());
+                    vo.setPointAddress(point.getAddress());
+
+                    PipeNetworkBase network = networkMap.get(point.getNetworkId());
+                    if (network != null) {
+                        vo.setNetworkId(network.getNetworkId());
+                        vo.setNetworkCode(network.getNetworkCode());
+                        vo.setNetworkName(network.getNetworkName());
+                        vo.setNetworkType(network.getNetworkType());
+                        vo.setNetworkLevel(network.getNetworkLevel());
+                    }
+                }
+            }
+
+            voList.add(vo);
+        }
+
+        Page<EquipmentFullVO> resultPage = new Page<>(pageNum, pageSize, basePage.getTotal());
+        resultPage.setRecords(voList);
+        return resultPage;
+    }
+
     @Override
     public List<EquipmentBase> getEquipmentByPoint(String pointId) {
         LambdaQueryWrapper<EquipmentPointRel> relWrapper = new LambdaQueryWrapper<>();

+ 89 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/service/impl/GasPipePointServiceImpl.java

@@ -0,0 +1,89 @@
+package com.zksy.base.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zksy.base.domain.GasPipePoint;
+import com.zksy.base.dto.GasPipePointPageInDTO;
+import com.zksy.base.mapper.GasPipePointMapper;
+import com.zksy.base.service.GasPipePointService;
+import com.zksy.common.exception.ServiceException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Slf4j
+@Service
+public class GasPipePointServiceImpl extends ServiceImpl<GasPipePointMapper, GasPipePoint>
+        implements GasPipePointService {
+
+    @Override
+    public Page<GasPipePoint> queryByPage(GasPipePointPageInDTO dto) {
+        Page<GasPipePoint> page = new Page<>(dto.getPageNum(), dto.getPageSize());
+        LambdaQueryWrapper<GasPipePoint> wrapper = new LambdaQueryWrapper<>();
+        wrapper.like(dto.getPointName() != null && !dto.getPointName().isEmpty(), GasPipePoint::getPointName, dto.getPointName());
+        wrapper.like(dto.getPointCode() != null && !dto.getPointCode().isEmpty(), GasPipePoint::getPointCode, dto.getPointCode());
+        wrapper.eq(dto.getNetworkId() != null && !dto.getNetworkId().isEmpty(), GasPipePoint::getNetworkId, dto.getNetworkId());
+        wrapper.eq(dto.getPointType() != null && !dto.getPointType().isEmpty(), GasPipePoint::getPointType, dto.getPointType());
+        wrapper.eq(dto.getStatus() != null && !dto.getStatus().isEmpty(), GasPipePoint::getStatus, dto.getStatus());
+        wrapper.orderByDesc(GasPipePoint::getCreateTime);
+        return this.page(page, wrapper);
+    }
+
+    @Override
+    public List<GasPipePoint> listByNetworkId(String networkId) {
+        LambdaQueryWrapper<GasPipePoint> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(GasPipePoint::getNetworkId, networkId);
+        wrapper.orderByAsc(GasPipePoint::getPointCode);
+        return this.list(wrapper);
+    }
+
+    @Override
+    public List<GasPipePoint> getOptions() {
+        LambdaQueryWrapper<GasPipePoint> wrapper = new LambdaQueryWrapper<>();
+        wrapper.select(GasPipePoint::getPointId, GasPipePoint::getPointName, GasPipePoint::getPointCode);
+        wrapper.orderByAsc(GasPipePoint::getPointName);
+        return this.list(wrapper);
+    }
+
+    @Override
+    public boolean saveWithCheck(GasPipePoint entity) {
+        LambdaQueryWrapper<GasPipePoint> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(GasPipePoint::getPointCode, entity.getPointCode());
+        if (this.count(wrapper) > 0) {
+            throw new ServiceException("管点编码已存在:" + entity.getPointCode());
+        }
+        return this.save(entity);
+    }
+
+    @Override
+    @Transactional
+    public boolean updateWithCheck(GasPipePoint entity) {
+        Long pointId = entity.getPointId();
+        if (this.getById(pointId) == null) {
+            throw new ServiceException("管点不存在:" + pointId);
+        }
+        String newCode = entity.getPointCode();
+        if (newCode != null) {
+            LambdaQueryWrapper<GasPipePoint> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(GasPipePoint::getPointCode, newCode)
+                    .ne(GasPipePoint::getPointId, pointId);
+            if (this.count(wrapper) > 0) {
+                throw new ServiceException("管点编码已被使用:" + newCode);
+            }
+        }
+        return this.updateById(entity);
+    }
+
+    @Override
+    @Transactional
+    public boolean removeWithCheck(Long pointId) {
+        GasPipePoint point = this.getById(pointId);
+        if (point == null) {
+            throw new ServiceException("管点不存在:" + pointId);
+        }
+        return this.baseMapper.deleteById(pointId) > 0;
+    }
+}