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

feat(warning): 添加预警管理系统功能

- 新增EarlyWarning实体类,定义预警信息的数据结构
- 实现EarlyWarningController控制器,提供完整的CRUD和业务操作接口
- 添加EarlyWarningMapper数据访问层,支持预警信息的各种查询操作
- 配置EarlyWarningMapper.xml SQL映射文件,实现复杂的预警信息检索逻辑
- 创建EarlyWarningService服务接口,定义预警管理的核心业务方法
- 实现EarlyWarningServiceImpl服务类,包含预警的保存、修改、删除、发布等功能
- 集成文件上传功能,支持预警相关的附件管理
- 实现预警状态管理,包括草稿、待办、处理中、已发布、已处理、已关闭等状态
- 添加预警关联功能,支持与报警信息的绑定关系
- 实现预警处置流程,包括升级、解除、退回、督办、领导批示等操作
- 提供预警统计和仪表盘功能,支持预警数据的可视化展示
- 实现预警归档功能,自动生成电子档案并存储
- 添加预警流程跟踪,支持处置过程的完整记录和可视化展示
- 实现多维度搜索功能,支持按预警类型、级别、状态等多种条件筛选
- 集成GIS地理位置功能,支持预警位置的地理信息展示
- 提供预警详情和完整信息查看功能,整合所有相关数据
林仔 преди 1 седмица
родител
ревизия
be6720db03

+ 364 - 0
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/warning/EarlyWarningController.java

@@ -0,0 +1,364 @@
+package com.zksy.web.controller.warning;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zksy.base.warning.domain.EarlyWarning;
+import com.zksy.base.warning.domain.WarningArchive;
+import com.zksy.base.warning.domain.WarningDisposal;
+import com.zksy.base.warning.domain.WarningSaveDTO;
+import com.zksy.base.warning.service.EarlyWarningService;
+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 io.swagger.annotations.ApiParam;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@RestController
+@RequestMapping("/warning")
+@Api(tags = "预警管理")
+public class EarlyWarningController {
+
+    @Autowired
+    private EarlyWarningService earlyWarningService;
+
+    @GetMapping("/list")
+    @ApiOperation("分页查询预警列表")
+    @Anonymous
+    public AjaxResult getWarningList(
+            @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam("每页数量") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam("预警名称") @RequestParam(required = false) String warningName,
+            @ApiParam("预警类型") @RequestParam(required = false) String warningType,
+            @ApiParam("预警级别") @RequestParam(required = false) String warningLevel,
+            @ApiParam("状态") @RequestParam(required = false) String status) {
+        Page<?> page = new Page<>(pageNum, pageSize);
+        IPage<Map<String, Object>> result = earlyWarningService.getWarningList(page, warningName, warningType, warningLevel, status);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/todo/list")
+    @ApiOperation("待办预警列表")
+    @Anonymous
+    public AjaxResult getTodoList(
+            @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam("每页数量") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam("用户ID") @RequestParam String userId,
+            @ApiParam("待办类型") @RequestParam(required = false) String todoType,
+            @ApiParam("预警名称") @RequestParam(required = false) String warningName) {
+        Page<?> page = new Page<>(pageNum, pageSize);
+        IPage<Map<String, Object>> result = earlyWarningService.getTodoList(page, userId, todoType, warningName);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/detail/{warningId}")
+    @ApiOperation("预警详情")
+    @Anonymous
+    public AjaxResult getWarningDetail(@PathVariable String warningId) {
+        Map<String, Object> detail = earlyWarningService.getWarningDetail(warningId);
+        if (detail == null) {
+            return AjaxResult.error("预警信息不存在");
+        }
+        return AjaxResult.success(detail);
+    }
+
+    @PostMapping("/save")
+    @ApiOperation("保存预警信息")
+    @Log(title = "保存预警信息", businessType = BusinessType.INSERT)
+    public AjaxResult saveWarning(WarningSaveDTO entity) {
+        boolean result = earlyWarningService.saveWarning(entity.getWarning(), entity.getAlarmIds(), entity.getFiles());
+        return result ? AjaxResult.success("保存成功", entity.getWarning().getWarningId()) : AjaxResult.error("保存失败");
+    }
+
+    @PutMapping("/update")
+    @ApiOperation("修改预警信息")
+    @Log(title = "修改预警信息", businessType = BusinessType.UPDATE)
+    public AjaxResult updateWarning(EarlyWarning warning, List<MultipartFile> files) {
+        boolean result = earlyWarningService.updateWarning(warning, files);
+        return result ? AjaxResult.success("修改成功") : AjaxResult.error("修改失败");
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("删除预警信息")
+    @Log(title = "删除预警信息", businessType = BusinessType.DELETE)
+    public AjaxResult deleteWarning(@RequestParam String warningId) {
+        boolean result = earlyWarningService.deleteWarning(warningId);
+        return result ? AjaxResult.success("删除成功") : AjaxResult.error("删除失败");
+    }
+
+    @DeleteMapping("/delete/batch")
+    @ApiOperation("批量删除预警信息")
+    @Log(title = "批量删除预警信息", businessType = BusinessType.DELETE)
+    public AjaxResult deleteBatchWarning(@RequestParam List<String> warningIds) {
+        boolean result = earlyWarningService.deleteBatchWarning(warningIds);
+        return result ? AjaxResult.success("批量删除成功") : AjaxResult.error("批量删除失败");
+    }
+
+    @PostMapping("/publish/{warningId}")
+    @ApiOperation("发布预警")
+    @Log(title = "发布预警", businessType = BusinessType.UPDATE)
+    public AjaxResult publishWarning(
+            @PathVariable String warningId,
+            @ApiParam("处置人") @RequestParam(required = false, defaultValue = "system") String disposalUser) {
+        boolean result = earlyWarningService.publishWarning(warningId, disposalUser);
+        return result ? AjaxResult.success("发布成功") : AjaxResult.error("发布失败");
+    }
+
+    @PostMapping("/upgrade")
+    @ApiOperation("预警升级")
+    @Log(title = "预警升级", businessType = BusinessType.UPDATE)
+    public AjaxResult upgradeWarning(
+            @ApiParam("预警ID") @RequestParam String warningId,
+            @ApiParam("新预警级别") @RequestParam String newLevel,
+            @ApiParam("处置人") @RequestParam(required = false, defaultValue = "system") String disposalUser,
+            @ApiParam("处置说明") @RequestParam String disposalContent) {
+        boolean result = earlyWarningService.upgradeWarning(warningId, newLevel, disposalUser, disposalContent);
+        return result ? AjaxResult.success("升级成功") : AjaxResult.error("升级失败");
+    }
+
+    @PostMapping("/resolve")
+    @ApiOperation("解除预警")
+    @Log(title = "解除预警", businessType = BusinessType.UPDATE)
+    public AjaxResult resolveWarning(
+            @ApiParam("预警ID") @RequestParam String warningId,
+            @ApiParam("处置人") @RequestParam(required = false, defaultValue = "system") String disposalUser,
+            @ApiParam("处置说明") @RequestParam String disposalContent) {
+        boolean result = earlyWarningService.resolveWarning(warningId, disposalUser, disposalContent);
+        return result ? AjaxResult.success("解除成功") : AjaxResult.error("解除失败");
+    }
+
+    @PostMapping("/return")
+    @ApiOperation("退回重办")
+    @Log(title = "退回重办", businessType = BusinessType.UPDATE)
+    public AjaxResult returnWarning(
+            @ApiParam("预警ID") @RequestParam String warningId,
+            @ApiParam("处置人") @RequestParam(required = false, defaultValue = "system") String disposalUser,
+            @ApiParam("退回说明") @RequestParam String disposalContent) {
+        boolean result = earlyWarningService.returnWarning(warningId, disposalUser, disposalContent);
+        return result ? AjaxResult.success("退回成功") : AjaxResult.error("退回失败");
+    }
+
+    @PostMapping("/supervision")
+    @ApiOperation("预警督办")
+    @Log(title = "预警督办", businessType = BusinessType.OTHER)
+    public AjaxResult supervisionWarning(
+            @ApiParam("预警ID") @RequestParam String warningId,
+            @ApiParam("督办人员") @RequestParam String supervisionUser,
+            @ApiParam("督办意见") @RequestParam String supervisionContent,
+            @ApiParam("通知方式") @RequestParam String notificationType,
+            @ApiParam("通知内容") @RequestParam(required = false) String notificationContent,
+            @ApiParam("附件地址") @RequestParam(required = false) String attachmentUrl) {
+        boolean result = earlyWarningService.supervisionWarning(warningId, supervisionUser, supervisionContent, notificationType, notificationContent, attachmentUrl);
+        return result ? AjaxResult.success("督办成功") : AjaxResult.error("督办失败");
+    }
+
+    @PostMapping("/instruction")
+    @ApiOperation("领导批示")
+    @Log(title = "领导批示", businessType = BusinessType.OTHER)
+    public AjaxResult addLeaderInstruction(
+            @ApiParam("预警ID") @RequestParam String warningId,
+            @ApiParam("领导姓名") @RequestParam String leaderName,
+            @ApiParam("批示内容") @RequestParam String instructionContent,
+            @ApiParam("短信接收人") @RequestParam(required = false) String smsReceivers) {
+        boolean result = earlyWarningService.addLeaderInstruction(warningId, leaderName, instructionContent, smsReceivers);
+        return result ? AjaxResult.success("批示成功") : AjaxResult.error("批示失败");
+    }
+
+    @PostMapping("/link/alarms")
+    @ApiOperation("关联报警信息")
+    public AjaxResult linkAlarms(
+            @ApiParam("预警ID") @RequestParam String warningId,
+            @ApiParam("报警ID列表") @RequestParam List<String> alarmIds) {
+        boolean result = earlyWarningService.linkAlarms(warningId, alarmIds);
+        return result ? AjaxResult.success("关联成功") : AjaxResult.error("关联失败");
+    }
+
+    @GetMapping("/link/alarms/{warningId}")
+    @ApiOperation("获取关联的报警列表")
+    public AjaxResult getLinkedAlarms(@PathVariable String warningId) {
+        List<Map<String, Object>> result = earlyWarningService.getLinkedAlarms(warningId);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/disposal/{warningId}")
+    @ApiOperation("获取处置记录列表")
+    public AjaxResult getDisposalList(@PathVariable String warningId) {
+        List<Map<String, Object>> result = earlyWarningService.getDisposalList(warningId);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/statistics")
+    @ApiOperation("获取统计数据")
+    @Anonymous
+    public AjaxResult getStatistics() {
+        Map<String, Object> result = earlyWarningService.getStatistics();
+        return AjaxResult.success(result);
+    }
+
+    /*@GetMapping("/config/types")
+    @ApiOperation("获取预警类型配置")
+    public AjaxResult getTypeConfigList() {
+        List<Map<String, Object>> result = earlyWarningService.getTypeConfigList();
+        return AjaxResult.success(result);
+    }*/
+
+    @GetMapping("/search")
+    @ApiOperation("综合搜索预警信息")
+    @Anonymous
+    public AjaxResult searchWarnings(
+            @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam("每页数量") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam("预警名称") @RequestParam(required = false) String warningName,
+            @ApiParam("预警编号") @RequestParam(required = false) String warningNo,
+            @ApiParam("预警类型") @RequestParam(required = false) String warningType,
+            @ApiParam("预警级别") @RequestParam(required = false) String warningLevel,
+            @ApiParam("状态") @RequestParam(required = false) String status,
+            @ApiParam("预警位置") @RequestParam(required = false) String location,
+            @ApiParam("发布人") @RequestParam(required = false) String publisher,
+            @ApiParam("权属单位") @RequestParam(required = false) String ownershipUnit,
+            @ApiParam("开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam("结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
+        Page<?> page = new Page<>(pageNum, pageSize);
+        IPage<Map<String, Object>> result = earlyWarningService.searchWarnings(page, warningName, warningNo, warningType, warningLevel, status, location, publisher, ownershipUnit, startTime, endTime);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/detail/full/{warningId}")
+    @ApiOperation("获取预警完整详情(含GIS定位和电子存档)")
+    @Anonymous
+    public AjaxResult getWarningFullDetail(@PathVariable String warningId) {
+        Map<String, Object> detail = earlyWarningService.getWarningFullDetail(warningId);
+        if (detail == null) {
+            return AjaxResult.error("预警信息不存在");
+        }
+        return AjaxResult.success(detail);
+    }
+
+    @GetMapping("/processing/list")
+    @ApiOperation("获取处置过程跟踪 - 进行中的预警")
+    @Anonymous
+    public AjaxResult getProcessingWarnings(
+            @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam("每页数量") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam("预警类型") @RequestParam(required = false) String warningType,
+            @ApiParam("预警级别") @RequestParam(required = false) String warningLevel) {
+        Page<?> page = new Page<>(pageNum, pageSize);
+        IPage<Map<String, Object>> result = earlyWarningService.getProcessingWarnings(page, warningType, warningLevel);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/completed/list")
+    @ApiOperation("获取处置过程跟踪 - 已完成的预警")
+    @Anonymous
+    public AjaxResult getCompletedWarnings(
+            @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam("每页数量") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam("预警类型") @RequestParam(required = false) String warningType,
+            @ApiParam("预警级别") @RequestParam(required = false) String warningLevel,
+            @ApiParam("开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam("结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
+        Page<?> page = new Page<>(pageNum, pageSize);
+        IPage<Map<String, Object>> result = earlyWarningService.getCompletedWarnings(page, warningType, warningLevel, startTime, endTime);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/disposal/history/{warningId}")
+    @ApiOperation("获取预警处置历史记录")
+    @Anonymous
+    public AjaxResult getDisposalHistory(@PathVariable String warningId) {
+        List<Map<String, Object>> result = earlyWarningService.getDisposalHistory(warningId);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/attachments/{warningId}")
+    @ApiOperation("获取预警附件列表")
+    @Anonymous
+    public AjaxResult getAttachments(@PathVariable String warningId) {
+        List<Map<String, Object>> result = earlyWarningService.getAttachments(warningId);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/dashboard/statistics")
+    @ApiOperation("获取仪表盘统计数据")
+    @Anonymous
+    public AjaxResult getDashboardStatistics() {
+        Map<String, Object> result = earlyWarningService.getDashboardStatistics();
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/archive/{warningId}")
+    @ApiOperation("获取预警归档信息")
+    @Anonymous
+    public AjaxResult getArchive(@PathVariable String warningId) {
+        WarningArchive archive = earlyWarningService.getArchiveByWarningId(warningId);
+        if (archive == null) {
+            return AjaxResult.error("归档信息不存在");
+        }
+        return AjaxResult.success(archive);
+    }
+
+    @GetMapping("/archive/list")
+    @ApiOperation("获取归档列表")
+    @Anonymous
+    public AjaxResult getArchiveList(
+            @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam("每页数量") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam("预警名称") @RequestParam(required = false) String warningName,
+            @ApiParam("预警类型") @RequestParam(required = false) String warningType,
+            @ApiParam("预警级别") @RequestParam(required = false) String warningLevel,
+            @ApiParam("开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam("结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
+        Page<WarningArchive> page = new Page<>(pageNum, pageSize);
+        IPage<WarningArchive> result = earlyWarningService.getArchiveList(page, warningName, warningType, warningLevel, startTime, endTime);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/process/{warningId}")
+    @ApiOperation("获取预警处置过程记录(完整流程)")
+    @Anonymous
+    public AjaxResult getDisposalProcess(@PathVariable String warningId) {
+        List<WarningDisposal> result = earlyWarningService.getDisposalProcess(warningId);
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/diagram/{warningId}")
+    @ApiOperation("获取预警流程可视化数据(路线图)")
+    @Anonymous
+    public AjaxResult getProcessDiagram(@PathVariable String warningId) {
+        Map<String, Object> result = earlyWarningService.getProcessDiagram(warningId);
+        if (result != null && result.containsKey("error")) {
+            return AjaxResult.error(result.get("error").toString());
+        }
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/disposal/detail/{disposalId}")
+    @ApiOperation("获取预警处置详情")
+    @Anonymous
+    public AjaxResult getDisposalDetail(@PathVariable String disposalId) {
+        Map<String, Object> result = earlyWarningService.getDisposalDetail(disposalId);
+        if (result == null) {
+            return AjaxResult.error("处置记录不存在");
+        }
+        return AjaxResult.success(result);
+    }
+
+    @GetMapping("/process/statistics/{warningId}")
+    @ApiOperation("获取预警流程统计信息")
+    @Anonymous
+    public AjaxResult getProcessStatistics(@PathVariable String warningId) {
+        Map<String, Object> result = earlyWarningService.getProcessStatistics(warningId);
+        return AjaxResult.success(result);
+    }
+}

+ 110 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/domain/EarlyWarning.java

@@ -0,0 +1,110 @@
+package com.zksy.base.warning.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@TableName("early_warning")
+@Api(value = "预警信息")
+@Data
+public class EarlyWarning implements Serializable {
+
+    @TableId(value = "warning_id", type = IdType.ASSIGN_UUID)
+    @ApiModelProperty("预警ID")
+    private String warningId;
+
+    @TableField("warning_no")
+    @ApiModelProperty("预警编号")
+    private String warningNo;
+
+    @TableField("warning_name")
+    @ApiModelProperty("预警名称")
+    private String warningName;
+
+    @TableField("warning_type")
+    @ApiModelProperty("预警类型")
+    private String warningType;
+
+    @TableField("warning_level")
+    @ApiModelProperty("预警级别")
+    private String warningLevel;
+
+    @TableField("warning_special")
+    @ApiModelProperty("预警专项")
+    private String warningSpecial;
+
+    @TableField("location")
+    @ApiModelProperty("预警位置")
+    private String location;
+
+    @TableField("longitude")
+    @ApiModelProperty("经度")
+    private BigDecimal longitude;
+
+    @TableField("latitude")
+    @ApiModelProperty("纬度")
+    private BigDecimal latitude;
+
+    @TableField("ownership_unit")
+    @ApiModelProperty("权属单位")
+    private String ownershipUnit;
+
+    @TableField("publisher")
+    @ApiModelProperty("发布人")
+    private String publisher;
+
+    @TableField("publish_time")
+    @ApiModelProperty("发布时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime publishTime;
+
+    @TableField("handler")
+    @ApiModelProperty("处置人")
+    private String handler;
+
+    @TableField("status")
+    @ApiModelProperty("状态")
+    private String status;
+
+    @TableField("warning_content")
+    @ApiModelProperty("预警内容描述")
+    private String warningContent;
+
+    @TableField("process_instance_id")
+    @ApiModelProperty("工作流实例ID")
+    private String processInstanceId;
+
+    @TableField("create_by")
+    @ApiModelProperty("创建人")
+    private String createBy;
+
+    @TableField("create_time")
+    @ApiModelProperty("创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+
+    @TableField("update_by")
+    @ApiModelProperty("更新人")
+    private String updateBy;
+
+    @TableField("update_time")
+    @ApiModelProperty("更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime updateTime;
+
+    @TableField("remark")
+    @ApiModelProperty("备注")
+    private String remark;
+
+    @TableField(exist = false)
+    private static final long serialVersionUID = 1L;
+}

+ 30 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/mapper/EarlyWarningMapper.java

@@ -0,0 +1,30 @@
+package com.zksy.base.warning.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zksy.base.warning.domain.EarlyWarning;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+public interface EarlyWarningMapper extends BaseMapper<EarlyWarning> {
+
+    IPage<Map<String, Object>> selectWarningList(Page<?> page, @Param("warningName") String warningName, @Param("warningType") String warningType, @Param("warningLevel") String warningLevel, @Param("status") String status);
+
+    IPage<Map<String, Object>> searchWarnings(Page<?> page, @Param("warningName") String warningName, @Param("warningNo") String warningNo, @Param("warningType") String warningType, @Param("warningLevel") String warningLevel, @Param("status") String status, @Param("location") String location, @Param("publisher") String publisher, @Param("ownershipUnit") String ownershipUnit, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
+
+    IPage<Map<String, Object>> selectTodoList(Page<?> page, @Param("userId") String userId, @Param("todoType") String todoType, @Param("warningName") String warningName);
+
+    IPage<Map<String, Object>> selectProcessingWarnings(Page<?> page, @Param("warningType") String warningType, @Param("warningLevel") String warningLevel);
+
+    IPage<Map<String, Object>> selectCompletedWarnings(Page<?> page, @Param("warningType") String warningType, @Param("warningLevel") String warningLevel, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime);
+
+    Map<String, Object> selectWarningDetail(@Param("warningId") String warningId);
+
+    List<Map<String, Object>> selectStatistics();
+}

+ 78 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/service/EarlyWarningService.java

@@ -0,0 +1,78 @@
+package com.zksy.base.warning.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.base.warning.domain.EarlyWarning;
+import com.zksy.base.warning.domain.WarningArchive;
+import com.zksy.base.warning.domain.WarningDisposal;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+public interface EarlyWarningService extends IService<EarlyWarning> {
+
+    IPage<Map<String, Object>> getWarningList(Page<?> page, String warningName, String warningType, String warningLevel, String status);
+
+    IPage<Map<String, Object>> searchWarnings(Page<?> page, String warningName, String warningNo, String warningType, String warningLevel, String status, String location, String publisher, String ownershipUnit, LocalDateTime startTime, LocalDateTime endTime);
+
+    IPage<Map<String, Object>> getTodoList(Page<?> page, String userId, String todoType, String warningName);
+
+    Map<String, Object> getWarningDetail(String warningId);
+
+    Map<String, Object> getWarningFullDetail(String warningId);
+
+    boolean saveWarning(EarlyWarning warning, List<String> alarmIds, List<MultipartFile> files);
+
+    boolean updateWarning(EarlyWarning warning, List<MultipartFile> files);
+
+    boolean deleteWarning(String warningId);
+
+    boolean deleteBatchWarning(List<String> warningIds);
+
+    boolean publishWarning(String warningId, String disposalUser);
+
+    boolean upgradeWarning(String warningId, String newLevel, String disposalUser, String disposalContent);
+
+    boolean resolveWarning(String warningId, String disposalUser, String disposalContent);
+
+    boolean returnWarning(String warningId, String disposalUser, String disposalContent);
+
+    boolean supervisionWarning(String warningId, String supervisionUser, String supervisionContent, String notificationType, String notificationContent, String attachmentUrl);
+
+    boolean addLeaderInstruction(String warningId, String leaderName, String instructionContent, String smsReceivers);
+
+    boolean linkAlarms(String warningId, List<String> alarmIds);
+
+    List<Map<String, Object>> getLinkedAlarms(String warningId);
+
+    List<Map<String, Object>> getDisposalList(String warningId);
+
+    List<Map<String, Object>> getDisposalHistory(String warningId);
+
+    IPage<Map<String, Object>> getProcessingWarnings(Page<?> page, String warningType, String warningLevel);
+
+    IPage<Map<String, Object>> getCompletedWarnings(Page<?> page, String warningType, String warningLevel, LocalDateTime startTime, LocalDateTime endTime);
+
+    List<Map<String, Object>> getAttachments(String warningId);
+
+    Map<String, Object> getStatistics();
+
+    Map<String, Object> getDashboardStatistics();
+
+    List<Map<String, Object>> getTypeConfigList();
+
+    WarningArchive getArchiveByWarningId(String warningId);
+
+    IPage<WarningArchive> getArchiveList(Page<WarningArchive> page, String warningName, String warningType, String warningLevel, LocalDateTime startTime, LocalDateTime endTime);
+
+    List<WarningDisposal> getDisposalProcess(String warningId);
+
+    Map<String, Object> getProcessDiagram(String warningId);
+
+    Map<String, Object> getDisposalDetail(String disposalId);
+
+    Map<String, Object> getProcessStatistics(String warningId);
+}

+ 768 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/warning/service/impl/EarlyWarningServiceImpl.java

@@ -0,0 +1,768 @@
+package com.zksy.base.warning.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.base.warning.domain.*;
+import com.zksy.base.warning.mapper.*;
+import com.zksy.base.warning.service.EarlyWarningService;
+import com.zksy.common.config.ZksyConfig;
+import com.zksy.common.core.domain.entity.SysDictData;
+import com.zksy.common.utils.DictUtils;
+import com.zksy.common.utils.file.FileUploadUtils;
+import com.zksy.common.utils.file.FileUtils;
+import com.zksy.service.MinioFileStorageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+@Service
+public class EarlyWarningServiceImpl extends ServiceImpl<EarlyWarningMapper, EarlyWarning>
+        implements EarlyWarningService {
+
+    @Autowired
+    private EarlyWarningMapper earlyWarningMapper;
+    @Autowired
+    private AlarmWarningRelMapper alarmWarningRelMapper;
+    @Autowired
+    private WarningAttachmentMapper warningAttachmentMapper;
+    @Autowired
+    private WarningDisposalMapper warningDisposalMapper;
+    @Autowired
+    private WarningTodoMapper warningTodoMapper;
+
+    @Autowired
+    private WarningArchiveMapper warningArchiveMapper;
+    @Autowired
+    private MinioFileStorageService minioFileStorageService;
+
+    @Override
+    public IPage<Map<String, Object>> getWarningList(Page<?> page, String warningName, String warningType, String warningLevel, String status) {
+        return earlyWarningMapper.selectWarningList(page, warningName, warningType, warningLevel, status);
+    }
+
+    @Override
+    public IPage<Map<String, Object>> searchWarnings(Page<?> page, String warningName, String warningNo, String warningType, String warningLevel, String status, String location, String publisher, String ownershipUnit, LocalDateTime startTime, LocalDateTime endTime) {
+        return earlyWarningMapper.searchWarnings(page, warningName, warningNo, warningType, warningLevel, status, location, publisher, ownershipUnit, startTime, endTime);
+    }
+
+    @Override
+    public IPage<Map<String, Object>> getTodoList(Page<?> page, String userId, String todoType, String warningName) {
+        return earlyWarningMapper.selectTodoList(page, userId, todoType, warningName);
+    }
+
+    @Override
+    public Map<String, Object> getWarningDetail(String warningId) {
+        Map<String, Object> detail = earlyWarningMapper.selectWarningDetail(warningId);
+        if (detail != null) {
+            detail.put("attachmentList", getAttachmentList(warningId));
+            detail.put("disposalList", getDisposalList(warningId));
+            detail.put("alarmList", getLinkedAlarms(warningId));
+        }
+        return detail;
+    }
+
+    @Override
+    public Map<String, Object> getWarningFullDetail(String warningId) {
+        Map<String, Object> result = new HashMap<>();
+        Map<String, Object> basicInfo = earlyWarningMapper.selectWarningDetail(warningId);
+        if (basicInfo == null) {
+            return null;
+        }
+
+        result.put("basicInfo", basicInfo);
+        result.put("gisLocation", getGisLocation(basicInfo));
+        result.put("disposalHistory", getDisposalHistory(warningId));
+        result.put("attachmentList", getAttachmentList(warningId));
+        result.put("alarmList", getLinkedAlarms(warningId));
+        result.put("electronicArchive", generateElectronicArchive(basicInfo));
+
+        return result;
+    }
+
+    private Map<String, Object> getGisLocation(Map<String, Object> warningInfo) {
+        Map<String, Object> gis = new HashMap<>();
+        gis.put("longitude", warningInfo.get("longitude"));
+        gis.put("latitude", warningInfo.get("latitude"));
+        gis.put("location", warningInfo.get("location"));
+        return gis;
+    }
+
+    private Map<String, Object> generateElectronicArchive(Map<String, Object> warningInfo) {
+        String warningId = (String) warningInfo.get("warningId");
+        
+        // 先查询是否已存在归档记录
+        LambdaQueryWrapper<WarningArchive> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(WarningArchive::getWarningId, warningId);
+        WarningArchive existingArchive = warningArchiveMapper.selectOne(wrapper);
+        
+        if (existingArchive != null) {
+            // 如果已存在,直接返回
+            Map<String, Object> archive = new HashMap<>();
+            archive.put("archiveId", existingArchive.getArchiveId());
+            archive.put("archiveNo", existingArchive.getArchiveNo());
+            archive.put("createTime", existingArchive.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+            archive.put("archiveContent", existingArchive.getArchiveContent());
+            archive.put("archiveStatus", existingArchive.getArchiveStatus());
+            return archive;
+        }
+        
+        // 如果不存在,创建新归档
+        WarningArchive archive = new WarningArchive();
+        archive.setWarningId(warningId);
+        archive.setArchiveNo("EA_" + warningInfo.get("warningNo"));
+        archive.setWarningNo((String) warningInfo.get("warningNo"));
+        archive.setWarningName((String) warningInfo.get("warningName"));
+        archive.setWarningType((String) warningInfo.get("warningType"));
+        archive.setWarningLevel((String) warningInfo.get("warningLevel"));
+        archive.setLocation((String) warningInfo.get("location"));
+        archive.setLongitude(warningInfo.get("longitude") != null ? ((Number) warningInfo.get("longitude")).doubleValue() : null);
+        archive.setLatitude(warningInfo.get("latitude") != null ? ((Number) warningInfo.get("latitude")).doubleValue() : null);
+        archive.setOwnershipUnit((String) warningInfo.get("ownershipUnit"));
+        archive.setPublisher((String) warningInfo.get("publisher"));
+        archive.setPublishTime(warningInfo.get("publishTime") instanceof LocalDateTime ? (LocalDateTime) warningInfo.get("publishTime") : null);
+        archive.setHandler((String) warningInfo.get("handler"));
+        archive.setWarningContent((String) warningInfo.get("warningContent"));
+        archive.setArchiveContent((String) warningInfo.get("warningContent"));
+        archive.setArchiveStatus("已归档");
+        archive.setCreateTime(LocalDateTime.now());
+        
+        warningArchiveMapper.insert(archive);
+        
+        Map<String, Object> result = new HashMap<>();
+        result.put("archiveId", archive.getArchiveId());
+        result.put("archiveNo", archive.getArchiveNo());
+        result.put("createTime", archive.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+        result.put("archiveContent", archive.getArchiveContent());
+        result.put("archiveStatus", archive.getArchiveStatus());
+        return result;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean saveWarning(EarlyWarning warning, List<String> alarmIds, List<MultipartFile> files) {
+        String warningNo = "WJ" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
+        warning.setWarningNo(warningNo);
+        warning.setStatus("DRAFT");
+        warning.setCreateTime(LocalDateTime.now());
+        warning.setUpdateTime(LocalDateTime.now());
+
+        boolean result = save(warning);
+        if (result) {
+            if (alarmIds != null && !alarmIds.isEmpty()) {
+                linkAlarms(warning.getWarningId(), alarmIds);
+            }
+            if (files != null && !files.isEmpty()) {
+                saveAttachments(warning.getWarningId(), files);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 保存附件
+     */
+    private void saveAttachments(String warningId, List<MultipartFile> files) {
+        try {
+            for (MultipartFile file : files) {
+                String path = minioFileStorageService.uploadFile(file, "warning");
+                // 上传文件
+                String fileName = path.substring(path.lastIndexOf("/") + 1);
+                // 保存附件信息
+                WarningAttachment attachment = new WarningAttachment();
+                attachment.setWarningId(warningId);
+                attachment.setAttachmentName(fileName);
+                attachment.setAttachmentUrl(path);
+                attachment.setAttachmentType(file.getContentType());
+                attachment.setAttachmentSize(file.getSize());
+                attachment.setCreateTime(LocalDateTime.now());
+                warningAttachmentMapper.insert(attachment);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("附件保存失败", e);
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean updateWarning(EarlyWarning warning, List<MultipartFile> files) {
+        warning.setUpdateTime(LocalDateTime.now());
+        boolean result = updateById(warning);
+        if (result && files != null && !files.isEmpty()) {
+            saveAttachments(warning.getWarningId(), files);
+        }
+        return result;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean deleteWarning(String warningId) {
+        // 先查询附件列表,删除物理文件
+        List<WarningAttachment> attachments = warningAttachmentMapper.selectList(
+                new LambdaQueryWrapper<WarningAttachment>()
+                        .eq(WarningAttachment::getWarningId, warningId)
+        );
+        for (WarningAttachment attachment : attachments) {
+            String attachmentUrl = attachment.getAttachmentUrl();
+            if (attachmentUrl != null && !attachmentUrl.isEmpty()) {
+                // 删除minio文件
+                minioFileStorageService.deleteFile(attachmentUrl);
+            }
+        }
+
+        // 删除关联数据
+        LambdaQueryWrapper<AlarmWarningRel> relWrapper = new LambdaQueryWrapper<>();
+        relWrapper.eq(AlarmWarningRel::getWarningId, warningId);
+        alarmWarningRelMapper.delete(relWrapper);
+
+        LambdaQueryWrapper<WarningAttachment> attachmentWrapper = new LambdaQueryWrapper<>();
+        attachmentWrapper.eq(WarningAttachment::getWarningId, warningId);
+        warningAttachmentMapper.delete(attachmentWrapper);
+
+        LambdaQueryWrapper<WarningDisposal> disposalWrapper = new LambdaQueryWrapper<>();
+        disposalWrapper.eq(WarningDisposal::getWarningId, warningId);
+        warningDisposalMapper.delete(disposalWrapper);
+
+        LambdaQueryWrapper<WarningTodo> todoWrapper = new LambdaQueryWrapper<>();
+        todoWrapper.eq(WarningTodo::getWarningId, warningId);
+        warningTodoMapper.delete(todoWrapper);
+
+        LambdaQueryWrapper<WarningArchive> archiveWrapper = new LambdaQueryWrapper<>();
+        archiveWrapper.eq(WarningArchive::getWarningId, warningId);
+        warningArchiveMapper.delete(archiveWrapper);
+
+        // 删除主表记录
+        return removeById(warningId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean deleteBatchWarning(List<String> warningIds) {
+        for (String warningId : warningIds) {
+            deleteWarning(warningId);
+        }
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean publishWarning(String warningId, String disposalUser) {
+        EarlyWarning warning = getById(warningId);
+        if (warning == null) return false;
+
+        warning.setStatus("PENDING");
+        warning.setPublishTime(LocalDateTime.now());
+        warning.setUpdateTime(LocalDateTime.now());
+
+        boolean result = updateById(warning);
+
+        if (result) {
+            addDisposalRecord(warningId, "RELEASE", null, null, disposalUser, "系统发布预警信息");
+            createTodo(warningId, warning.getHandler(), "待办预警", "TODO");
+        }
+
+        return result;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean upgradeWarning(String warningId, String newLevel, String disposalUser, String disposalContent) {
+        EarlyWarning warning = getById(warningId);
+        if (warning == null) return false;
+
+        String oldLevel = warning.getWarningLevel();
+        warning.setWarningLevel(newLevel);
+        warning.setUpdateTime(LocalDateTime.now());
+
+        boolean result = updateById(warning);
+        if (result) {
+            addDisposalRecord(warningId, "UPGRADE", oldLevel, newLevel, disposalUser, disposalContent);
+        }
+        return result;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean resolveWarning(String warningId, String disposalUser, String disposalContent) {
+        EarlyWarning warning = getById(warningId);
+        if (warning == null) return false;
+
+        warning.setStatus("CLOSED");
+        warning.setUpdateTime(LocalDateTime.now());
+
+        boolean result = updateById(warning);
+        if (result) {
+            addDisposalRecord(warningId, "RESOLVE", null, null, disposalUser, disposalContent);
+            completeTodo(warningId);
+            
+            // 解除预警时自动创建归档
+            Map<String, Object> warningDetail = earlyWarningMapper.selectWarningDetail(warningId);
+            if (warningDetail != null) {
+                generateElectronicArchive(warningDetail);
+            }
+        }
+        return result;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean returnWarning(String warningId, String disposalUser, String disposalContent) {
+        EarlyWarning warning = getById(warningId);
+        if (warning == null) return false;
+
+        warning.setStatus("PENDING");
+        warning.setUpdateTime(LocalDateTime.now());
+
+        boolean result = updateById(warning);
+        if (result) {
+            addDisposalRecord(warningId, "RETURN", null, null, disposalUser, disposalContent);
+        }
+        return result;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean supervisionWarning(String warningId, String supervisionUser, String supervisionContent, String notificationType, String notificationContent, String attachmentUrl) {
+        WarningDisposal disposal = new WarningDisposal();
+        disposal.setWarningId(warningId);
+        disposal.setDisposalType("SUPERVISION");
+        disposal.setDisposalUser(supervisionUser);
+        disposal.setDisposalContent(supervisionContent);
+        disposal.setSupervisionUser(supervisionUser);
+        disposal.setSupervisionContent(supervisionContent);
+        disposal.setNotificationType(notificationType);
+        disposal.setCreateTime(LocalDateTime.now());
+
+        return warningDisposalMapper.insert(disposal) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean addLeaderInstruction(String warningId, String leaderName, String instructionContent, String smsReceivers) {
+        WarningDisposal disposal = new WarningDisposal();
+        disposal.setWarningId(warningId);
+        disposal.setDisposalType("INSTRUCTION");
+        disposal.setDisposalUser(leaderName);
+        disposal.setDisposalContent(instructionContent);
+        disposal.setCreateTime(LocalDateTime.now());
+
+        return warningDisposalMapper.insert(disposal) > 0;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean linkAlarms(String warningId, List<String> alarmIds) {
+        LambdaQueryWrapper<AlarmWarningRel> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(AlarmWarningRel::getWarningId, warningId);
+        alarmWarningRelMapper.delete(wrapper);
+
+        if (alarmIds != null && !alarmIds.isEmpty()) {
+            for (String alarmId : alarmIds) {
+                AlarmWarningRel rel = new AlarmWarningRel();
+                rel.setWarningId(warningId);
+                rel.setAlarmId(alarmId);
+                rel.setCreateTime(LocalDateTime.now());
+                alarmWarningRelMapper.insert(rel);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public List<Map<String, Object>> getLinkedAlarms(String warningId) {
+        return alarmWarningRelMapper.selectAlarmListByWarningId(warningId);
+    }
+
+    @Override
+    public List<Map<String, Object>> getDisposalList(String warningId) {
+        return warningDisposalMapper.selectDisposalList(warningId);
+    }
+
+    @Override
+    public List<Map<String, Object>> getDisposalHistory(String warningId) {
+        return warningDisposalMapper.selectDisposalList(warningId);
+    }
+
+    @Override
+    public IPage<Map<String, Object>> getProcessingWarnings(Page<?> page, String warningType, String warningLevel) {
+        return earlyWarningMapper.selectProcessingWarnings(page, warningType, warningLevel);
+    }
+
+    @Override
+    public IPage<Map<String, Object>> getCompletedWarnings(Page<?> page, String warningType, String warningLevel, LocalDateTime startTime, LocalDateTime endTime) {
+        return earlyWarningMapper.selectCompletedWarnings(page, warningType, warningLevel, startTime, endTime);
+    }
+
+    @Override
+    public List<Map<String, Object>> getAttachments(String warningId) {
+        return getAttachmentList(warningId);
+    }
+
+    @Override
+    public Map<String, Object> getStatistics() {
+        List<Map<String, Object>> statsList = earlyWarningMapper.selectStatistics();
+        if (statsList != null && !statsList.isEmpty()) {
+            return statsList.get(0);
+        }
+        return new HashMap<>();
+    }
+
+    @Override
+    public Map<String, Object> getDashboardStatistics() {
+        Map<String, Object> result = new HashMap<>();
+        
+        Map<String, Object> basicStats = getStatistics();
+        result.put("basicStats", basicStats);
+        
+        List<Map<String, Object>> typeStats = getWarningTypeStatistics();
+        result.put("typeStats", typeStats);
+        
+        List<Map<String, Object>> levelStats = getWarningLevelStatistics();
+        result.put("levelStats", levelStats);
+        
+        List<Map<String, Object>> trendStats = getWarningTrendStatistics();
+        result.put("trendStats", trendStats);
+        
+        return result;
+    }
+
+    private List<Map<String, Object>> getWarningTypeStatistics() {
+        List<SysDictData> types = DictUtils.getDictCache("warning_type");
+        List<Map<String, Object>> result = new ArrayList<>();
+        if (types != null) {
+            for (SysDictData type : types) {
+                LambdaQueryWrapper<EarlyWarning> wrapper = new LambdaQueryWrapper<>();
+                wrapper.eq(EarlyWarning::getWarningType, type.getDictValue());
+                long count = count(wrapper);
+                
+                Map<String, Object> item = new HashMap<>();
+                item.put("typeCode", type.getDictValue());
+                item.put("typeName", type.getDictLabel());
+                item.put("count", count);
+                result.add(item);
+            }
+        }
+        return result;
+    }
+
+    private List<Map<String, Object>> getWarningLevelStatistics() {
+        List<Map<String, Object>> result = new ArrayList<>();
+        // 预警级别:1-4
+        for (int i = 1; i <= 4; i++) {
+            String levelCode = String.valueOf(i);
+            LambdaQueryWrapper<EarlyWarning> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(EarlyWarning::getWarningLevel, levelCode);
+            long count = count(wrapper);
+            
+            Map<String, Object> item = new HashMap<>();
+            item.put("levelCode", levelCode);
+            item.put("count", count);
+            result.add(item);
+        }
+        return result;
+    }
+
+    private List<Map<String, Object>> getWarningTrendStatistics() {
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (int i = 6; i >= 0; i--) {
+            LocalDateTime date = LocalDateTime.now().minusDays(i);
+            LocalDateTime startOfDay = date.toLocalDate().atStartOfDay();
+            LocalDateTime endOfDay = date.toLocalDate().atTime(23, 59, 59);
+            
+            LambdaQueryWrapper<EarlyWarning> wrapper = new LambdaQueryWrapper<>();
+            wrapper.ge(EarlyWarning::getCreateTime, startOfDay);
+            wrapper.le(EarlyWarning::getCreateTime, endOfDay);
+            long count = count(wrapper);
+            
+            Map<String, Object> item = new HashMap<>();
+            item.put("date", date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+            item.put("count", count);
+            result.add(item);
+        }
+        return result;
+    }
+
+    @Override
+    public List<Map<String, Object>> getTypeConfigList() {
+        List<SysDictData> list = DictUtils.getDictCache("warning_type");
+        List<Map<String, Object>> result = new ArrayList<>();
+        if (list != null) {
+            for (SysDictData config : list) {
+                Map<String, Object> map = new HashMap<>();
+                map.put("dictCode", config.getDictCode());
+                map.put("typeCode", config.getDictValue());
+                map.put("typeName", config.getDictLabel());
+                result.add(map);
+            }
+        }
+        return result;
+    }
+
+    private void addDisposalRecord(String warningId, String disposalType, String oldLevel, String newLevel, String disposalUser, String content) {
+        WarningDisposal disposal = new WarningDisposal();
+        disposal.setWarningId(warningId);
+        disposal.setDisposalType(disposalType);
+        disposal.setOldLevel(oldLevel);
+        disposal.setNewLevel(newLevel);
+        disposal.setDisposalUser(disposalUser);
+        disposal.setDisposalContent(content);
+        disposal.setCreateTime(LocalDateTime.now());
+        warningDisposalMapper.insert(disposal);
+    }
+
+    private List<Map<String, Object>> getAttachmentList(String warningId) {
+        List<WarningAttachment> list = warningAttachmentMapper.selectList(
+                new LambdaQueryWrapper<WarningAttachment>()
+                        .eq(WarningAttachment::getWarningId, warningId)
+                        .orderByDesc(WarningAttachment::getCreateTime)
+        );
+
+        List<Map<String, Object>> result = new ArrayList<>();
+        for (WarningAttachment attachment : list) {
+            Map<String, Object> map = new HashMap<>();
+            map.put("attachmentId", attachment.getAttachmentId());
+            map.put("attachmentName", attachment.getAttachmentName());
+            map.put("attachmentUrl", attachment.getAttachmentUrl());
+            map.put("attachmentType", attachment.getAttachmentType());
+            map.put("attachmentSize", attachment.getAttachmentSize());
+            map.put("createTime", attachment.getCreateTime());
+            result.add(map);
+        }
+        return result;
+    }
+
+    private void createTodo(String warningId, String userId, String taskName, String todoType) {
+        WarningTodo todo = new WarningTodo();
+        todo.setWarningId(warningId);
+        todo.setUserId(userId);
+        todo.setUserName(userId);
+        todo.setTodoType(todoType);
+        todo.setReadStatus("UNREAD");
+        todo.setTaskName(taskName);
+        todo.setCreateTime(LocalDateTime.now());
+        warningTodoMapper.insert(todo);
+    }
+
+    private void completeTodo(String warningId) {
+        LambdaQueryWrapper<WarningTodo> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(WarningTodo::getWarningId, warningId)
+                .eq(WarningTodo::getTodoType, "TODO");
+        List<WarningTodo> todos = warningTodoMapper.selectList(wrapper);
+
+        for (WarningTodo todo : todos) {
+            todo.setTodoType("DONE");
+            todo.setReadStatus("READ");
+            todo.setCompleteTime(LocalDateTime.now());
+            warningTodoMapper.updateById(todo);
+        }
+    }
+
+    @Override
+    public WarningArchive getArchiveByWarningId(String warningId) {
+        LambdaQueryWrapper<WarningArchive> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(WarningArchive::getWarningId, warningId);
+        return warningArchiveMapper.selectOne(wrapper);
+    }
+
+    @Override
+    public IPage<WarningArchive> getArchiveList(Page<WarningArchive> page, String warningName, String warningType, String warningLevel, LocalDateTime startTime, LocalDateTime endTime) {
+        LambdaQueryWrapper<WarningArchive> wrapper = new LambdaQueryWrapper<>();
+        
+        if (warningName != null && !warningName.isEmpty()) {
+            wrapper.like(WarningArchive::getWarningName, warningName);
+        }
+        if (warningType != null && !warningType.isEmpty()) {
+            wrapper.eq(WarningArchive::getWarningType, warningType);
+        }
+        if (warningLevel != null && !warningLevel.isEmpty()) {
+            wrapper.eq(WarningArchive::getWarningLevel, warningLevel);
+        }
+        if (startTime != null) {
+            wrapper.ge(WarningArchive::getCreateTime, startTime);
+        }
+        if (endTime != null) {
+            wrapper.le(WarningArchive::getCreateTime, endTime);
+        }
+        
+        wrapper.orderByDesc(WarningArchive::getCreateTime);
+        return warningArchiveMapper.selectPage(page, wrapper);
+    }
+
+    private static final Map<String, String> DISPOSAL_TYPE_MAP = new HashMap<>();
+    static {
+        DISPOSAL_TYPE_MAP.put("RELEASE", "发布预警");
+        DISPOSAL_TYPE_MAP.put("UPGRADE", "升级预警");
+        DISPOSAL_TYPE_MAP.put("RESOLVE", "解除预警");
+        DISPOSAL_TYPE_MAP.put("RETURN", "退回重办");
+        DISPOSAL_TYPE_MAP.put("SUPERVISION", "预警督办");
+        DISPOSAL_TYPE_MAP.put("INSTRUCTION", "领导批示");
+    }
+
+    @Override
+    public List<WarningDisposal> getDisposalProcess(String warningId) {
+        LambdaQueryWrapper<WarningDisposal> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(WarningDisposal::getWarningId, warningId);
+        wrapper.orderByAsc(WarningDisposal::getCreateTime);
+        return warningDisposalMapper.selectList(wrapper);
+    }
+
+    @Override
+    public Map<String, Object> getProcessDiagram(String warningId) {
+        Map<String, Object> result = new HashMap<>();
+        List<Map<String, Object>> nodes = new ArrayList<>();
+        List<Map<String, Object>> edges = new ArrayList<>();
+
+        EarlyWarning warning = earlyWarningMapper.selectById(warningId);
+        if (warning == null) {
+            result.put("error", "预警不存在");
+            return result;
+        }
+
+        List<WarningDisposal> disposals = getDisposalProcess(warningId);
+
+        Map<String, Object> startNode = new HashMap<>();
+        startNode.put("id", "start");
+        startNode.put("name", "预警创建");
+        startNode.put("type", "startEvent");
+        startNode.put("x", 50);
+        startNode.put("y", 150);
+        startNode.put("status", "completed");
+        nodes.add(startNode);
+
+        int x = 180;
+        String lastNodeId = "start";
+
+        for (int i = 0; i < disposals.size(); i++) {
+            WarningDisposal disposal = disposals.get(i);
+            String nodeId = "task_" + i;
+            String typeName = DISPOSAL_TYPE_MAP.getOrDefault(disposal.getDisposalType(), "处置");
+
+            Map<String, Object> taskNode = new HashMap<>();
+            taskNode.put("id", nodeId);
+            taskNode.put("name", typeName);
+            taskNode.put("type", "userTask");
+            taskNode.put("x", x);
+            taskNode.put("y", 150);
+            taskNode.put("status", "completed");
+            taskNode.put("disposalUser", disposal.getDisposalUser());
+            taskNode.put("disposalTime", disposal.getCreateTime() != null ? 
+                    disposal.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null);
+            taskNode.put("disposalId", disposal.getDisposalId());
+            nodes.add(taskNode);
+
+            Map<String, Object> edge = new HashMap<>();
+            edge.put("source", lastNodeId);
+            edge.put("target", nodeId);
+            edge.put("label", "");
+            edge.put("status", "completed");
+            edges.add(edge);
+
+            lastNodeId = nodeId;
+            x += 180;
+        }
+
+        String status = warning.getStatus();
+        String currentStatus = "waiting";
+        if ("CLOSED".equals(status) || "HANDLED".equals(status)) {
+            currentStatus = "completed";
+        } else if ("PROCESSING".equals(status) || "PENDING".equals(status) || "RELEASED".equals(status)) {
+            currentStatus = "active";
+        }
+
+        Map<String, Object> endNode = new HashMap<>();
+        endNode.put("id", "end");
+        endNode.put("name", "处置完成");
+        endNode.put("type", "endEvent");
+        endNode.put("x", x);
+        endNode.put("y", 150);
+        endNode.put("status", currentStatus);
+        nodes.add(endNode);
+
+        if (!disposals.isEmpty()) {
+            Map<String, Object> lastEdge = new HashMap<>();
+            lastEdge.put("source", lastNodeId);
+            lastEdge.put("target", "end");
+            lastEdge.put("label", "");
+            lastEdge.put("status", currentStatus);
+            edges.add(lastEdge);
+        }
+
+        result.put("nodes", nodes);
+        result.put("edges", edges);
+        result.put("warningId", warningId);
+        result.put("warningName", warning.getWarningName());
+        result.put("warningNo", warning.getWarningNo());
+        result.put("status", warning.getStatus());
+        result.put("totalTasks", disposals.size());
+        result.put("processDefinitionName", "预警处置流程");
+
+        return result;
+    }
+
+    @Override
+    public Map<String, Object> getDisposalDetail(String disposalId) {
+        WarningDisposal disposal = warningDisposalMapper.selectById(disposalId);
+        if (disposal == null) {
+            return null;
+        }
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("disposalId", disposal.getDisposalId());
+        result.put("warningId", disposal.getWarningId());
+        result.put("disposalType", disposal.getDisposalType());
+        result.put("disposalTypeName", DISPOSAL_TYPE_MAP.getOrDefault(disposal.getDisposalType(), "未知"));
+        result.put("oldLevel", disposal.getOldLevel());
+        result.put("newLevel", disposal.getNewLevel());
+        result.put("disposalUser", disposal.getDisposalUser());
+        result.put("disposalContent", disposal.getDisposalContent());
+        result.put("supervisionUser", disposal.getSupervisionUser());
+        result.put("supervisionContent", disposal.getSupervisionContent());
+        result.put("notificationType", disposal.getNotificationType());
+        result.put("createTime", disposal.getCreateTime() != null ? 
+                disposal.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null);
+
+        return result;
+    }
+
+    @Override
+    public Map<String, Object> getProcessStatistics(String warningId) {
+        Map<String, Object> result = new HashMap<>();
+
+        List<WarningDisposal> disposals = getDisposalProcess(warningId);
+        EarlyWarning warning = earlyWarningMapper.selectById(warningId);
+
+        result.put("warningId", warningId);
+        result.put("warningName", warning != null ? warning.getWarningName() : null);
+        result.put("totalDisposals", disposals.size());
+
+        Map<String, Integer> typeCount = new HashMap<>();
+        for (WarningDisposal disposal : disposals) {
+            String type = disposal.getDisposalType();
+            typeCount.put(type, typeCount.getOrDefault(type, 0) + 1);
+        }
+        result.put("typeDistribution", typeCount);
+
+        Set<String> handlers = new HashSet<>();
+        for (WarningDisposal disposal : disposals) {
+            if (disposal.getDisposalUser() != null) {
+                handlers.add(disposal.getDisposalUser());
+            }
+        }
+        result.put("handlerCount", handlers.size());
+
+        if (!disposals.isEmpty()) {
+            result.put("firstDisposalTime", disposals.get(0).getCreateTime() != null ? 
+                    disposals.get(0).getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null);
+            result.put("lastDisposalTime", disposals.get(disposals.size() - 1).getCreateTime() != null ? 
+                    disposals.get(disposals.size() - 1).getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : null);
+        }
+
+        return result;
+    }
+}

+ 146 - 0
pipe-network-service/zksy-system/src/main/resources/mapper/warning/EarlyWarningMapper.xml

@@ -0,0 +1,146 @@
+<?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.base.warning.mapper.EarlyWarningMapper">
+
+    <select id="selectWarningList" resultType="java.util.Map">
+        SELECT w.*
+        FROM early_warning w
+        <where>
+            <if test="warningName != null and warningName != ''">
+                AND w.warning_name LIKE CONCAT('%', #{warningName}, '%')
+            </if>
+            <if test="warningType != null and warningType != ''">
+                AND w.warning_type = #{warningType}
+            </if>
+            <if test="warningLevel != null and warningLevel != ''">
+                AND w.warning_level = #{warningLevel}
+            </if>
+            <if test="status != null and status != ''">
+                AND w.status = #{status}
+            </if>
+        </where>
+        ORDER BY w.create_time DESC
+    </select>
+
+    <select id="searchWarnings" resultType="java.util.Map">
+        SELECT w.*
+        FROM early_warning w
+        <where>
+            <if test="warningName != null and warningName != ''">
+                AND w.warning_name LIKE CONCAT('%', #{warningName}, '%')
+            </if>
+            <if test="warningNo != null and warningNo != ''">
+                AND w.warning_no LIKE CONCAT('%', #{warningNo}, '%')
+            </if>
+            <if test="warningType != null and warningType != ''">
+                AND w.warning_type = #{warningType}
+            </if>
+            <if test="warningLevel != null and warningLevel != ''">
+                AND w.warning_level = #{warningLevel}
+            </if>
+            <if test="status != null and status != ''">
+                AND w.status = #{status}
+            </if>
+            <if test="location != null and location != ''">
+                AND w.location LIKE CONCAT('%', #{location}, '%')
+            </if>
+            <if test="publisher != null and publisher != ''">
+                AND w.publisher LIKE CONCAT('%', #{publisher}, '%')
+            </if>
+            <if test="ownershipUnit != null and ownershipUnit != ''">
+                AND w.ownership_unit LIKE CONCAT('%', #{ownershipUnit}, '%')
+            </if>
+            <if test="startTime != null">
+                AND w.create_time >= #{startTime}
+            </if>
+            <if test="endTime != null">
+                AND w.create_time &lt;= #{endTime}
+            </if>
+        </where>
+        ORDER BY w.create_time DESC
+    </select>
+
+    <select id="selectTodoList" resultType="java.util.Map">
+        SELECT
+            t.*,
+            w.warning_name,
+            w.warning_type,
+            w.warning_level,
+            w.handler,
+            w.publisher,
+            w.location,
+            w.ownership_unit,
+            w.publish_time
+        FROM warning_todo t
+        LEFT JOIN early_warning w ON t.warning_id = w.warning_id
+        <where>
+            t.user_id = #{userId}
+            <if test="todoType != null and todoType != ''">
+                AND t.todo_type = #{todoType}
+            </if>
+            <if test="warningName != null and warningName != ''">
+                AND w.warning_name LIKE CONCAT('%', #{warningName}, '%')
+            </if>
+        </where>
+        ORDER BY t.create_time DESC
+    </select>
+
+    <select id="selectProcessingWarnings" resultType="java.util.Map">
+        SELECT w.*
+        FROM early_warning w
+        <where>
+            AND w.status IN ('PENDING', 'PROCESSING', 'RELEASED')
+            <if test="warningType != null and warningType != ''">
+                AND w.warning_type = #{warningType}
+            </if>
+            <if test="warningLevel != null and warningLevel != ''">
+                AND w.warning_level = #{warningLevel}
+            </if>
+        </where>
+        ORDER BY w.publish_time DESC
+    </select>
+
+    <select id="selectCompletedWarnings" resultType="java.util.Map">
+        SELECT w.*
+        FROM early_warning w
+        <where>
+            AND w.status IN ('HANDLED', 'CLOSED')
+            <if test="warningType != null and warningType != ''">
+                AND w.warning_type = #{warningType}
+            </if>
+            <if test="warningLevel != null and warningLevel != ''">
+                AND w.warning_level = #{warningLevel}
+            </if>
+            <if test="startTime != null">
+                AND w.update_time >= #{startTime}
+            </if>
+            <if test="endTime != null">
+                AND w.update_time &lt;= #{endTime}
+            </if>
+        </where>
+        ORDER BY w.update_time DESC
+    </select>
+
+    <select id="selectWarningDetail" resultType="java.util.Map">
+        SELECT w.*
+        FROM early_warning w
+        WHERE w.warning_id = #{warningId}
+    </select>
+
+    <select id="selectStatistics" resultType="java.util.Map">
+        SELECT
+            COUNT(*) AS total,
+            SUM(CASE WHEN status = 'DRAFT' THEN 1 ELSE 0 END) AS draftCount,
+            SUM(CASE WHEN status = 'PENDING' THEN 1 ELSE 0 END) AS pendingCount,
+            SUM(CASE WHEN status = 'PROCESSING' THEN 1 ELSE 0 END) AS processingCount,
+            SUM(CASE WHEN status = 'RELEASED' THEN 1 ELSE 0 END) AS releasedCount,
+            SUM(CASE WHEN status = 'HANDLED' THEN 1 ELSE 0 END) AS handledCount,
+            SUM(CASE WHEN status = 'CLOSED' THEN 1 ELSE 0 END) AS closedCount,
+            SUM(CASE WHEN warning_level = '1' THEN 1 ELSE 0 END) AS level1Count,
+            SUM(CASE WHEN warning_level = '2' THEN 1 ELSE 0 END) AS level2Count,
+            SUM(CASE WHEN warning_level = '3' THEN 1 ELSE 0 END) AS level3Count,
+            SUM(CASE WHEN warning_level = '4' THEN 1 ELSE 0 END) AS level4Count
+        FROM early_warning
+    </select>
+
+</mapper>