Преглед на файлове

- 添加WaterPipeInfo供水管网信息数据接口
- 在ApplicationConfig中添加指定要扫描的Mapper类的包的路径"com.zksy.WaterSupply.**.mapper"
-在zksy-admin目录下的yml文件添加MyBatis-Plus框架使用delFlag 字段作为逻辑删除标记,0 表示数据正常,2 表示数据已删除。

Kazerin преди 2 месеца
родител
ревизия
f44a0626a6

+ 286 - 0
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/WaterSupply/WaterPipeInfo/WaterPipeInfoController.java

@@ -0,0 +1,286 @@
+package com.zksy.web.controller.WaterSupply.WaterPipeInfo;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zksy.WaterSupply.WaterPipeInfo.domain.WaterPipeInfo;
+import com.zksy.WaterSupply.WaterPipeInfo.service.IWaterPipeInfoService;
+import com.zksy.common.annotation.Anonymous;
+import com.zksy.common.core.domain.AjaxResult;
+import com.zksy.common.utils.SecurityUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 管网数据统计分析接口
+ */
+@RestController
+@RequestMapping("/api/water/pipe")
+@Api(tags = "供水管网-管网信息数据接口")
+@Anonymous
+public class WaterPipeInfoController {
+
+    private static final Logger log = LoggerFactory.getLogger(WaterPipeInfoController.class);
+
+    @Autowired
+    private IWaterPipeInfoService waterPipeInfoService;
+
+    // -------------------------- 基础CRUD接口 --------------------------
+    @GetMapping("/page")
+    @ApiOperation(value = "分页查询管网数据", notes = "支持按管网编号、名称、材质、状态模糊查询")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "查询成功", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,查询失败", response = AjaxResult.class)
+    })
+    public AjaxResult queryPage(
+            @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam(value = "每页大小", defaultValue = "10") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam(value = "管网编号") @RequestParam(required = false) String pipeCode,
+            @ApiParam(value = "管网名称") @RequestParam(required = false) String pipeName,
+            @ApiParam(value = "管网材质") @RequestParam(required = false) String pipeMaterial,
+            @ApiParam(value = "状态(0正常 1停用)") @RequestParam(required = false) String status) {
+        try {
+            Page<WaterPipeInfo> page = new Page<>(pageNum, pageSize);
+            IPage<WaterPipeInfo> resultPage = waterPipeInfoService.queryPage(page, pipeCode, pipeName, pipeMaterial, status);
+            return AjaxResult.success("查询成功", resultPage);
+        } catch (Exception e) {
+            log.error("分页查询管网数据异常", e);
+            return AjaxResult.error("查询失败:" + e.getMessage());
+        }
+    }
+
+    @GetMapping("/{id}")
+    @ApiOperation(value = "根据ID查询管网详情", notes = "传入管网ID获取完整信息")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "查询成功", response = AjaxResult.class),
+            @ApiResponse(code = 404, message = "未找到指定ID的管网信息", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,查询失败", response = AjaxResult.class)
+    })
+    public AjaxResult getById(
+            @ApiParam(value = "管网ID", required = true, example = "1") @PathVariable Long id) {
+        try {
+            WaterPipeInfo data = waterPipeInfoService.getById(id);
+            return data == null ? AjaxResult.warn("未找到该管网信息") : AjaxResult.success("查询成功", data);
+        } catch (Exception e) {
+            log.error("查询管网详情异常", e);
+            return AjaxResult.error("查询失败:" + e.getMessage());
+        }
+    }
+
+    @PostMapping
+    @ApiOperation(value = "新增管网信息", notes = "传入管网实体对象进行新增")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "新增成功", response = AjaxResult.class),
+            @ApiResponse(code = 400, message = "请求参数错误", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,新增失败", response = AjaxResult.class)
+    })
+    public AjaxResult add(@RequestBody WaterPipeInfo waterPipeInfo) {
+        try {
+            waterPipeInfo.setDelFlag("0");
+            try {
+                waterPipeInfo.setCreateBy(SecurityUtils.getUsername());
+            } catch (Exception e) {
+                waterPipeInfo.setCreateBy("system");
+            }
+            waterPipeInfo.setCreateTime(LocalDateTime.now());
+            boolean result = waterPipeInfoService.save(waterPipeInfo);
+            return result ? AjaxResult.success("新增成功") : AjaxResult.error("新增失败");
+        } catch (Exception e) {
+            log.error("新增管网信息异常", e);
+            return AjaxResult.error("新增失败:" + e.getMessage());
+        }
+    }
+
+    @PutMapping
+    @ApiOperation(value = "修改管网信息", notes = "传入管网实体对象进行修改,仅更新非空字段")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "修改成功", response = AjaxResult.class),
+            @ApiResponse(code = 400, message = "请求参数错误", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,修改失败", response = AjaxResult.class)
+    })
+    public AjaxResult update(@RequestBody WaterPipeInfo waterPipeInfo) {
+        try {
+            // 禁止修改关键字段
+            waterPipeInfo.setDelFlag(null);
+            waterPipeInfo.setCreateBy(null);
+            waterPipeInfo.setCreateTime(null);
+
+            try {
+                waterPipeInfo.setUpdateBy(SecurityUtils.getUsername());
+            } catch (Exception e) {
+                waterPipeInfo.setUpdateBy("system");
+            }
+            waterPipeInfo.setUpdateTime(LocalDateTime.now());
+
+            boolean result = waterPipeInfoService.updateById(waterPipeInfo);
+            return result ? AjaxResult.success("修改成功") : AjaxResult.error("修改失败");
+        } catch (Exception e) {
+            log.error("修改管网信息异常", e);
+            return AjaxResult.error("修改失败:" + e.getMessage());
+        }
+    }
+
+    @DeleteMapping("/{ids}")
+    @ApiOperation(value = "批量逻辑删除管网信息", notes = "多个ID用逗号分隔,逻辑删除(移入回收站),不物理删除数据")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "修改成功", response = AjaxResult.class),
+            @ApiResponse(code = 400, message = "请求参数错误", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,修改失败", response = AjaxResult.class)
+    })
+    public AjaxResult remove(
+            @ApiParam(value = "管网ID数组,多个用逗号分隔", required = true, example = "1,2,3") @PathVariable Long[] ids) {
+        try {
+            log.info("开始删除管网数据,ids: {}", (Object) ids);
+            boolean result = waterPipeInfoService.removeByIds(List.of(ids));
+            return result
+                    ? AjaxResult.success("删除成功,已移入回收站,共删除 " + ids.length + " 条数据")
+                    : AjaxResult.error("删除失败");
+        } catch (Exception e) {
+            log.error("删除管网数据异常", e);
+            return AjaxResult.error("删除失败:" + e.getMessage());
+        }
+    }
+
+    // -------------------------- 统计分析接口 --------------------------
+    @GetMapping("/latest")
+    @ApiOperation(value = "获取最新添加的管网信息", notes = "返回创建时间最晚的一条管网数据")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "查询成功", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,查询失败", response = AjaxResult.class)
+    })
+    public AjaxResult getLatestPipe() {
+        try {
+            WaterPipeInfo data = waterPipeInfoService.getLatestPipe();
+            return data == null ? AjaxResult.warn("未查询到管网数据") : AjaxResult.success("查询成功", data);
+        } catch (Exception e) {
+            log.error("查询最新管网异常", e);
+            return AjaxResult.error("查询失败:" + e.getMessage());
+        }
+    }
+
+    @GetMapping("/visualization/stat/status")
+    @ApiOperation(value = "按状态统计管网数据", notes = "统计正常和停用状态的管网数量")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "统计成功", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,统计失败", response = AjaxResult.class)
+    })
+    public AjaxResult statPipeByStatus() {
+        try {
+            return AjaxResult.success("统计成功", waterPipeInfoService.statPipeByStatus());
+        } catch (Exception e) {
+            log.error("按状态统计管网异常", e);
+            return AjaxResult.error("统计失败:" + e.getMessage());
+        }
+    }
+
+    @GetMapping("/visualization/stat/material")
+    @ApiOperation(value = "按材质统计管网数据", notes = "统计不同材质管网的数量和总长度")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "统计成功", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,统计失败", response = AjaxResult.class)
+    })
+    public AjaxResult statPipeByMaterial() {
+        try {
+            return AjaxResult.success("统计成功", waterPipeInfoService.statPipeByMaterial());
+        } catch (Exception e) {
+            log.error("按材质统计管网异常", e);
+            return AjaxResult.error("统计失败:" + e.getMessage());
+        }
+    }
+
+    @GetMapping("/visualization/stat/overall")
+    @ApiOperation(value = "获取管网整体统计数据", notes = "返回总管网数、总长度、运行中数量、停用数量")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "统计成功", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,统计失败", response = AjaxResult.class)
+    })
+    public AjaxResult getOverallStatistics() {
+        try {
+            return AjaxResult.success("统计成功", waterPipeInfoService.getPipeOverallStatistics());
+        } catch (Exception e) {
+            log.error("获取整体统计异常", e);
+            return AjaxResult.error("统计失败:" + e.getMessage());
+        }
+    }
+
+    // -------------------------- 回收站接口 --------------------------
+    @GetMapping("/recycle/list")
+    @ApiOperation(value = "查询回收站数据", notes = "分页查询已删除的管网数据,支持筛选")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "统计成功", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,统计失败", response = AjaxResult.class)
+    })
+    public AjaxResult recycleList(
+            @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam(value = "每页大小", defaultValue = "10") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam(value = "管网编号") @RequestParam(required = false) String pipeCode,
+            @ApiParam(value = "管网名称") @RequestParam(required = false) String pipeName,
+            @ApiParam(value = "管网材质") @RequestParam(required = false) String pipeMaterial) {
+        try {
+            Page<WaterPipeInfo> page = new Page<>(pageNum, pageSize);
+            IPage<WaterPipeInfo> resultPage = waterPipeInfoService.queryDeletedPage(page, pipeCode, pipeName, pipeMaterial);
+            return AjaxResult.success("查询成功", resultPage);
+        } catch (Exception e) {
+            log.error("查询回收站数据异常", e);
+            return AjaxResult.error("查询失败:" + e.getMessage());
+        }
+    }
+
+    @PostMapping("/recycle/restore/{ids}")
+    @ApiOperation(value = "批量恢复已删除数据", notes = "多个ID用逗号分隔,将数据从回收站恢复为正常状态")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "恢复成功", response = AjaxResult.class),
+            @ApiResponse(code = 400, message = "请选择要恢复的数据", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,恢复失败", response = AjaxResult.class)
+    })
+    public AjaxResult restore(
+            @ApiParam(value = "管网ID数组,多个用逗号分隔", required = true, example = "3,4") @PathVariable Long[] ids) {
+        try {
+            log.info("开始恢复管网数据,ids: {}", (Object) ids);
+            String updateBy = "system";
+            try {
+                updateBy = SecurityUtils.getUsername();
+            } catch (Exception e) {
+                log.warn("未获取到登录用户,使用默认值system");
+            }
+
+            boolean result = waterPipeInfoService.restoreByIds(List.of(ids), updateBy);
+            return result
+                    ? AjaxResult.success("恢复成功,共恢复 " + ids.length + " 条数据")
+                    : AjaxResult.error("恢复失败");
+        } catch (Exception e) {
+            log.error("恢复数据异常", e);
+            return AjaxResult.error("恢复失败:" + e.getMessage());
+        }
+    }
+
+    @DeleteMapping("/recycle/delete/{ids}")
+    @ApiOperation(value = "批量彻底删除数据(不可恢复)", notes = "多个ID用逗号分隔,物理删除数据库中的数据,谨慎使用")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "恢复成功", response = AjaxResult.class),
+            @ApiResponse(code = 400, message = "请选择要恢复的数据", response = AjaxResult.class),
+            @ApiResponse(code = 500, message = "服务器内部错误,恢复失败", response = AjaxResult.class)
+    })
+    public AjaxResult deletePhysically(
+            @ApiParam(value = "管网ID数组,多个用逗号分隔", required = true, example = "5") @PathVariable Long[] ids) {
+        try {
+            log.info("开始彻底删除管网数据,ids: {}", (Object) ids);
+            boolean result = waterPipeInfoService.deleteByIdsPhysically(List.of(ids));
+            return result
+                    ? AjaxResult.success("彻底删除成功,共删除 " + ids.length + " 条数据")
+                    : AjaxResult.error("彻底删除失败");
+        } catch (Exception e) {
+            log.error("彻底删除数据异常", e);
+            return AjaxResult.error("彻底删除失败:" + e.getMessage());
+        }
+    }
+}

+ 8 - 1
pipe-network-service/zksy-admin/src/main/resources/application-dev.yml

@@ -4,4 +4,11 @@ minio:
   secretKey: minio123
   bucket: pipe
   readPath: http://192.168.110.30:9000
-imgAddress: D:/Temp/%s.jpg
+imgAddress: D:/Temp/%s.jpg
+
+mybatis-plus:
+  global-config:
+    db-config:
+      logic-delete-field: delFlag
+      logic-delete-value: "2"
+      logic-not-delete-value: "0"

+ 8 - 1
pipe-network-service/zksy-admin/src/main/resources/application-prod.yml

@@ -4,4 +4,11 @@ minio:
     secretKey: minio123
     bucket: pipe
     readPath: http://47.107.107.47:9000
-imgAddress: /home/img-repository/%s.jpg
+imgAddress: /home/img-repository/%s.jpg
+
+mybatis-plus:
+    global-config:
+        db-config:
+            logic-delete-field: delFlag
+            logic-delete-value: "2"
+            logic-not-delete-value: "0"

+ 1 - 1
pipe-network-service/zksy-framework/src/main/java/com/zksy/framework/config/ApplicationConfig.java

@@ -17,7 +17,7 @@ import java.util.TimeZone;
 // 表示通过aop框架暴露该代理对象,AopContext能够访问
 @EnableAspectJAutoProxy(exposeProxy = true)
 // 指定要扫描的Mapper类的包的路径
-@MapperScan({"com.zksy.base.**.mapper", "com.zksy.system.**.mapper", "com.zksy.quartz.**.mapper", "com.zksy.generator.**.mapper"})
+@MapperScan({"com.zksy.base.**.mapper", "com.zksy.system.**.mapper", "com.zksy.quartz.**.mapper", "com.zksy.generator.**.mapper", "com.zksy.WaterSupply.**.mapper"})
 public class ApplicationConfig
 {
     /**

+ 82 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/WaterSupply/WaterPipeInfo/domain/WaterPipeInfo.java

@@ -0,0 +1,82 @@
+package com.zksy.WaterSupply.WaterPipeInfo.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 管网信息实体
+ */
+@Data
+@TableName("water_pipe_info")
+@ApiModel(value = "WaterPipeInfo", description = "管网信息对象")
+public class WaterPipeInfo {
+
+    @ApiModelProperty(value = "主键ID", example = "1", position = 1)
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "管网编号", example = "P001", required = true, position = 2)
+    private String pipeCode;
+
+    @ApiModelProperty(value = "管网名称", example = "XX路主管网", required = true, position = 3)
+    private String pipeName;
+
+    @ApiModelProperty(value = "管道材质(铸铁/PE/钢管等)", example = "PE", position = 4)
+    private String pipeMaterial;
+
+    @ApiModelProperty(value = "管径(mm)", example = "200", position = 5)
+    private Integer pipeDiameter;
+
+    @ApiModelProperty(value = "管道长度(m)", example = "120.50", position = 6)
+    private BigDecimal pipeLength;
+
+    @ApiModelProperty(value = "起点位置", example = "XX路1号", position = 7)
+    private String startPoint;
+
+    @ApiModelProperty(value = "终点位置", example = "XX路100号", position = 8)
+    private String endPoint;
+
+    @ApiModelProperty(value = "铺设年份", example = "2026", position = 9)
+    private Integer layingYear;
+
+    @ApiModelProperty(value = "设计压力(MPa)", example = "1.60", position = 10)
+    private BigDecimal pressureRating;
+
+    @ApiModelProperty(value = "运行状态(0正常 1停用)", example = "0", allowableValues = "0,1", position = 11)
+    private String status;
+
+    @ApiModelProperty(value = "备注", example = "主干管道", position = 12)
+    private String remark;
+
+    @ApiModelProperty(value = "删除标志(0存在 2删除)", example = "0", allowableValues = "0,2", hidden = true, position = 13)
+    @TableLogic
+    private String delFlag;
+
+    @ApiModelProperty(value = "创建者", example = "admin", hidden = true, position = 14)
+    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+    private String createBy;
+
+    @ApiModelProperty(value = "创建时间", example = "2026-05-18 10:00:00", hidden = true, position = 15)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "更新者", example = "admin", hidden = true, position = 16)
+    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.UPDATE)
+    private String updateBy;
+
+    @ApiModelProperty(value = "更新时间", example = "2026-05-18 14:00:00", hidden = true, position = 17)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @TableField(fill = com.baomidou.mybatisplus.annotation.FieldFill.UPDATE)
+    private LocalDateTime updateTime;
+}

+ 59 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/WaterSupply/WaterPipeInfo/mapper/WaterPipeInfoMapper.java

@@ -0,0 +1,59 @@
+package com.zksy.WaterSupply.WaterPipeInfo.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zksy.WaterSupply.WaterPipeInfo.domain.WaterPipeInfo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+public interface WaterPipeInfoMapper extends BaseMapper<WaterPipeInfo> {
+
+    /**
+     * 分页条件查询
+     */
+    List<WaterPipeInfo> selectPipeList(@Param("pipeCode") String pipeCode,
+                                       @Param("pipeName") String pipeName,
+                                       @Param("pipeMaterial") String pipeMaterial,
+                                       @Param("status") String status);
+
+    /**
+     * 按状态统计管网
+     */
+    List<Map<String, Object>> statPipeByStatus();
+
+    /**
+     * 按材质统计管网
+     */
+    List<Map<String, Object>> statPipeByMaterial();
+
+    /**
+     * 获取最新管网
+     */
+    WaterPipeInfo getLatestPipe();
+
+    /**
+     * 整体统计
+     */
+    Map<String, Object> getPipeOverallStatistics();
+
+    /**
+     * 查询已删除的管网数据
+     */
+    List<WaterPipeInfo> selectDeletedList(@Param("pipeCode") String pipeCode,
+                                          @Param("pipeName") String pipeName,
+                                          @Param("pipeMaterial") String pipeMaterial);
+
+    /**
+     * 批量恢复已删除数据
+     */
+    int restoreByIds(@Param("ids") List<Long> ids, @Param("updateBy") String updateBy);
+
+    /**
+     * 批量彻底物理删除数据
+     */
+    int deleteByIdsPhysically(@Param("ids") List<Long> ids);
+}

+ 62 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/WaterSupply/WaterPipeInfo/service/IWaterPipeInfoService.java

@@ -0,0 +1,62 @@
+package com.zksy.WaterSupply.WaterPipeInfo.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zksy.WaterSupply.WaterPipeInfo.domain.WaterPipeInfo;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 管网信息 服务层接口
+ */
+public interface IWaterPipeInfoService extends IService<WaterPipeInfo> {
+
+    /**
+     * 分页条件查询
+     */
+    IPage<WaterPipeInfo> queryPage(Page<WaterPipeInfo> page,
+                                   String pipeCode,
+                                   String pipeName,
+                                   String pipeMaterial,
+                                   String status);
+
+    /**
+     * 按状态统计管网
+     */
+    List<Map<String, Object>> statPipeByStatus();
+
+    /**
+     * 按材质统计管网
+     */
+    List<Map<String, Object>> statPipeByMaterial();
+
+    /**
+     * 获取最新管网
+     */
+    WaterPipeInfo getLatestPipe();
+
+    /**
+     * 整体统计
+     */
+    Map<String, Object> getPipeOverallStatistics();
+
+    /**
+     * 分页查询回收站数据
+     */
+    IPage<WaterPipeInfo> queryDeletedPage(Page<WaterPipeInfo> page,
+                                          String pipeCode,
+                                          String pipeName,
+                                          String pipeMaterial);
+
+    /**
+     * 批量恢复已删除数据
+     */
+    boolean restoreByIds(List<Long> ids, String updateBy);
+
+    /**
+     * 批量彻底物理删除数据
+     */
+    boolean deleteByIdsPhysically(List<Long> ids);
+}

+ 92 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/WaterSupply/WaterPipeInfo/service/impl/WaterPipeInfoServiceImpl.java

@@ -0,0 +1,92 @@
+package com.zksy.WaterSupply.WaterPipeInfo.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zksy.WaterSupply.WaterPipeInfo.domain.WaterPipeInfo;
+import com.zksy.WaterSupply.WaterPipeInfo.mapper.WaterPipeInfoMapper;
+import com.zksy.WaterSupply.WaterPipeInfo.service.IWaterPipeInfoService;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Service
+public class WaterPipeInfoServiceImpl extends ServiceImpl<WaterPipeInfoMapper, WaterPipeInfo>
+        implements IWaterPipeInfoService {
+
+    @Override
+    public IPage<WaterPipeInfo> queryPage(Page<WaterPipeInfo> page,
+                                          String pipeCode,
+                                          String pipeName,
+                                          String pipeMaterial,
+                                          String status) {
+        LambdaQueryWrapper<WaterPipeInfo> wrapper = new LambdaQueryWrapper<>();
+        if (StringUtils.hasText(pipeCode)) {
+            wrapper.like(WaterPipeInfo::getPipeCode, pipeCode);
+        }
+        if (StringUtils.hasText(pipeName)) {
+            wrapper.like(WaterPipeInfo::getPipeName, pipeName);
+        }
+        if (StringUtils.hasText(pipeMaterial)) {
+            wrapper.eq(WaterPipeInfo::getPipeMaterial, pipeMaterial);
+        }
+        if (StringUtils.hasText(status)) {
+            wrapper.eq(WaterPipeInfo::getStatus, status);
+        }
+        wrapper.eq(WaterPipeInfo::getDelFlag, "0");
+        wrapper.orderByDesc(WaterPipeInfo::getCreateTime);
+        return this.page(page, wrapper);
+    }
+
+    @Override
+    public List<Map<String, Object>> statPipeByStatus() {
+        return baseMapper.statPipeByStatus();
+    }
+
+    @Override
+    public List<Map<String, Object>> statPipeByMaterial() {
+        return baseMapper.statPipeByMaterial();
+    }
+
+    @Override
+    public WaterPipeInfo getLatestPipe() {
+        return baseMapper.getLatestPipe();
+    }
+
+    @Override
+    public Map<String, Object> getPipeOverallStatistics() {
+        return baseMapper.getPipeOverallStatistics();
+    }
+
+    @Override
+    public IPage<WaterPipeInfo> queryDeletedPage(Page<WaterPipeInfo> page,
+                                                 String pipeCode,
+                                                 String pipeName,
+                                                 String pipeMaterial) {
+        List<WaterPipeInfo> list = baseMapper.selectDeletedList(pipeCode, pipeName, pipeMaterial);
+        page.setRecords(list);
+        page.setTotal(list.size());
+        return page;
+    }
+
+    @Override
+    public boolean restoreByIds(List<Long> ids, String updateBy) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        // 直接传递List,不需要再转字符串
+        return baseMapper.restoreByIds(ids, updateBy) > 0;
+    }
+
+    @Override
+    public boolean deleteByIdsPhysically(List<Long> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        return baseMapper.deleteByIdsPhysically(ids) > 0;
+    }
+}

+ 121 - 0
pipe-network-service/zksy-system/src/main/resources/mapper/WaterSupply/WaterPipeInfo/WaterPipeInfoMapper.xml

@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zksy.WaterSupply.WaterPipeInfo.mapper.WaterPipeInfoMapper">
+
+    <resultMap id="BaseResultMap" type="com.zksy.WaterSupply.WaterPipeInfo.domain.WaterPipeInfo">
+        <id column="id" property="id"/>
+        <result column="pipe_code" property="pipeCode"/>
+        <result column="pipe_name" property="pipeName"/>
+        <result column="pipe_material" property="pipeMaterial"/>
+        <result column="pipe_diameter" property="pipeDiameter"/>
+        <result column="pipe_length" property="pipeLength"/>
+        <result column="start_point" property="startPoint"/>
+        <result column="end_point" property="endPoint"/>
+        <result column="laying_year" property="layingYear"/>
+        <result column="pressure_rating" property="pressureRating"/>
+        <result column="status" property="status"/>
+        <result column="remark" property="remark"/>
+        <result column="del_flag" property="delFlag"/>
+        <result column="create_by" property="createBy"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_by" property="updateBy"/>
+        <result column="update_time" property="updateTime"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id, pipe_code, pipe_name, pipe_material, pipe_diameter, pipe_length,
+        start_point, end_point, laying_year, pressure_rating, status, remark,
+        del_flag, create_by, create_time, update_by, update_time
+    </sql>
+
+    <select id="selectPipeList" resultMap="BaseResultMap">
+        SELECT <include refid="Base_Column_List"/>
+        FROM water_pipe_info
+        WHERE del_flag = '0'
+        <if test="pipeCode != null and pipeCode != ''">
+            AND pipe_code LIKE CONCAT('%', #{pipeCode}, '%')
+        </if>
+        <if test="pipeName != null and pipeName != ''">
+            AND pipe_name LIKE CONCAT('%', #{pipeName}, '%')
+        </if>
+        <if test="pipeMaterial != null and pipeMaterial != ''">
+            AND pipe_material = #{pipeMaterial}
+        </if>
+        <if test="status != null and status != ''">
+            AND status = #{status}
+        </if>
+        ORDER BY create_time DESC
+    </select>
+
+    <select id="statPipeByStatus" resultType="java.util.Map">
+        SELECT
+        status,
+        COUNT(*) AS pipeCount
+        FROM water_pipe_info
+        WHERE del_flag = '0'
+        GROUP BY status
+    </select>
+
+    <select id="statPipeByMaterial" resultType="java.util.Map">
+        SELECT
+        pipe_material AS pipeMaterial,
+        COUNT(*) AS pipeCount,
+        SUM(pipe_length) AS totalLength
+        FROM water_pipe_info
+        WHERE del_flag = '0'
+        GROUP BY pipe_material
+    </select>
+
+    <select id="getLatestPipe" resultMap="BaseResultMap">
+        SELECT <include refid="Base_Column_List"/>
+        FROM water_pipe_info
+        WHERE del_flag = '0'
+        ORDER BY create_time DESC
+        LIMIT 1
+    </select>
+
+    <select id="getPipeOverallStatistics" resultType="java.util.Map">
+        SELECT
+        COUNT(*) AS totalPipeCount,
+        SUM(pipe_length) AS totalLength,
+        SUM(CASE WHEN status = '0' THEN 1 ELSE 0 END) AS runningCount,
+        SUM(CASE WHEN status = '1' THEN 1 ELSE 0 END) AS stopCount
+        FROM water_pipe_info
+        WHERE del_flag = '0'
+    </select>
+
+    <select id="selectDeletedList" resultMap="BaseResultMap">
+        SELECT <include refid="Base_Column_List"/>
+        FROM water_pipe_info
+        WHERE del_flag = '2'
+        <if test="pipeCode != null and pipeCode != ''">
+            AND pipe_code LIKE CONCAT('%', #{pipeCode}, '%')
+        </if>
+        <if test="pipeName != null and pipeName != ''">
+            AND pipe_name LIKE CONCAT('%', #{pipeName}, '%')
+        </if>
+        <if test="pipeMaterial != null and pipeMaterial != ''">
+            AND pipe_material = #{pipeMaterial}
+        </if>
+        ORDER BY update_time DESC
+    </select>
+
+    <delete id="deleteByIdsPhysically">
+        DELETE FROM water_pipe_info WHERE id IN
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <update id="restoreByIds">
+        UPDATE water_pipe_info
+        SET del_flag = '0',
+        update_by = #{updateBy},
+        update_time = NOW()
+        WHERE id IN
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </update>
+
+</mapper>