徐展城 8 ore fa
parent
commit
8866471f2a
15 ha cambiato i file con 716 aggiunte e 1 eliminazioni
  1. 25 1
      build-uat/update.sql
  2. 49 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/riskalert/RiskAlertController.java
  3. 24 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/riskalert/vo/DeptAlertCountRespVO.java
  4. 25 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/riskalert/vo/TaskOrderReportAlertCountRespVO.java
  5. 81 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/useralertconfig/UserAlertConfigController.java
  6. 28 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/useralertconfig/vo/UserAlertConfigPageReqVO.java
  7. 30 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/useralertconfig/vo/UserAlertConfigRespVO.java
  8. 20 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/useralertconfig/vo/UserAlertConfigSaveReqVO.java
  9. 25 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/useralertconfig/UserAlertConfigDO.java
  10. 72 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/riskalert/RiskAlertMapper.java
  11. 21 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/useralertconfig/UserAlertConfigMapper.java
  12. 17 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/riskalert/RiskAlertService.java
  13. 230 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/riskalert/RiskAlertServiceImpl.java
  14. 21 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/useralertconfig/UserAlertConfigService.java
  15. 48 0
      tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/useralertconfig/UserAlertConfigServiceImpl.java

+ 25 - 1
build-uat/update.sql

@@ -1595,4 +1595,28 @@ COMMENT ON COLUMN "PRESSURE2_INDEX_TODO"."UPDATER" IS '修改人';
 COMMENT ON COLUMN "PRESSURE2_INDEX_TODO"."UPDATE_TIME" IS '修改时间';
 COMMENT ON COLUMN "PRESSURE2_INDEX_TODO"."DELETED" IS '是否删除';
 
---已加
+--已加
+
+CREATE TABLE "PRESSURE2_USER_ALERT_CONFIG"
+(
+    "ID" VARCHAR2(64) NOT NULL,
+    "USER_ID" VARCHAR2(64),
+    "ALERT_NUM" INT DEFAULT NULL,
+    "CREATOR" VARCHAR2(64) DEFAULT '',
+    "CREATE_TIME" TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP NOT NULL,
+    "UPDATER" VARCHAR2(64) DEFAULT '',
+    "UPDATE_TIME" TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP NOT NULL,
+    "DELETED" BIT DEFAULT 0,
+    NOT CLUSTER PRIMARY KEY("ID")) STORAGE(ON "MAIN", CLUSTERBTR) ;
+
+COMMENT ON TABLE "PRESSURE2_USER_ALERT_CONFIG" IS '承压-用户报告预警配置';
+COMMENT ON COLUMN "PRESSURE2_USER_ALERT_CONFIG"."ID" IS '主键';
+COMMENT ON COLUMN "PRESSURE2_USER_ALERT_CONFIG"."USER_ID" IS '系统用户id';
+COMMENT ON COLUMN "PRESSURE2_USER_ALERT_CONFIG"."ALERT_NUM" IS '预警天数';
+COMMENT ON COLUMN "PRESSURE2_USER_ALERT_CONFIG"."CREATOR" IS '创建人';
+COMMENT ON COLUMN "PRESSURE2_USER_ALERT_CONFIG"."CREATE_TIME" IS '创建时间';
+COMMENT ON COLUMN "PRESSURE2_USER_ALERT_CONFIG"."UPDATER" IS '更新者';
+COMMENT ON COLUMN "PRESSURE2_USER_ALERT_CONFIG"."UPDATE_TIME" IS '更新时间';
+COMMENT ON COLUMN "PRESSURE2_USER_ALERT_CONFIG"."DELETED" IS '是否删除';
+
+-- 已加

+ 49 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/riskalert/RiskAlertController.java

@@ -0,0 +1,49 @@
+package cn.start.tz.module.pressure2.controller.admin.riskalert;
+
+import cn.start.tz.framework.common.pojo.CommonResult;
+import cn.start.tz.module.pressure2.controller.admin.riskalert.vo.*;
+import cn.start.tz.module.pressure2.service.riskalert.RiskAlertService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static cn.start.tz.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 首页风险预警")
+@RestController
+@RequestMapping("/pressure2/risk-alert")
+@Validated
+public class RiskAlertController {
+
+    @Resource
+    private RiskAlertService riskAlertService;
+
+    @GetMapping("/boiler/my")
+    @Operation(summary = "当前用户锅炉预警统计")
+    public CommonResult<List<TaskOrderReportAlertCountRespVO>> getMyBoilerAlert() {
+        return success(riskAlertService.getMyBoilerAlert());
+    }
+
+    @PostMapping("/boiler/dept")
+    @Operation(summary = "部门锅炉预警统计")
+    public CommonResult<List<DeptAlertCountRespVO>> getDeptBoilerAlert(@RequestBody List<String> deptIds) {
+        return success(riskAlertService.getDeptBoilerAlert(deptIds));
+    }
+
+    @GetMapping("/pipe/my")
+    @Operation(summary = "当前用户管道预警统计")
+    public CommonResult<List<TaskOrderReportAlertCountRespVO>> getMyPipeAlert() {
+        return success(riskAlertService.getMyPipeAlert());
+    }
+
+    @PostMapping("/pipe/dept")
+    @Operation(summary = "部门管道预警统计")
+    public CommonResult<List<DeptAlertCountRespVO>> getDeptPipeAlert(@RequestBody List<String> deptIds) {
+        return success(riskAlertService.getDeptPipeAlert(deptIds));
+    }
+
+}

+ 24 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/riskalert/vo/DeptAlertCountRespVO.java

@@ -0,0 +1,24 @@
+package cn.start.tz.module.pressure2.controller.admin.riskalert.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "部门预警统计")
+@Data
+public class DeptAlertCountRespVO {
+
+    @Schema(description = "部门ID")
+    private String deptId;
+
+    @Schema(description = "部门名称")
+    private String deptName;
+
+    @Schema(description = "预警总数")
+    private int totalCount;
+
+    @Schema(description = "按检验性质分组的统计")
+    private List<TaskOrderReportAlertCountRespVO> checkTypeStats;
+
+}

+ 25 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/riskalert/vo/TaskOrderReportAlertCountRespVO.java

@@ -0,0 +1,25 @@
+package cn.start.tz.module.pressure2.controller.admin.riskalert.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Schema(description = "任务单报告预警统计项")
+@Data
+public class TaskOrderReportAlertCountRespVO {
+
+    @Schema(description = "检验性质")
+    private Integer checkType;
+
+    @Schema(description = "检验性质名称")
+    private String checkTypeName;
+
+    @Schema(description = "预警数量")
+    private int count;
+
+    @Schema(description = "设备代码列表")
+    private List<String> equipCodes = new ArrayList<>();
+
+}

+ 81 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/useralertconfig/UserAlertConfigController.java

@@ -0,0 +1,81 @@
+package cn.start.tz.module.pressure2.controller.admin.useralertconfig;
+
+import cn.start.tz.framework.common.pojo.*;
+import cn.start.tz.framework.common.util.object.BeanUtils;
+import cn.start.tz.framework.excel.core.util.ExcelUtils;
+import cn.start.tz.framework.apilog.core.annotation.ApiAccessLog;
+import cn.start.tz.module.pressure2.controller.admin.useralertconfig.vo.*;
+import cn.start.tz.module.pressure2.dal.dataobject.useralertconfig.UserAlertConfigDO;
+import cn.start.tz.module.pressure2.service.useralertconfig.UserAlertConfigService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static cn.start.tz.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.start.tz.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 用户报告预警配置")
+@RestController
+@RequestMapping("/pressure2/user-alert-config")
+@Validated
+public class UserAlertConfigController {
+
+    @Resource
+    private UserAlertConfigService userAlertConfigService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建用户报告预警配置")
+    public CommonResult<String> createUserAlertConfig(@Valid @RequestBody UserAlertConfigSaveReqVO createReqVO) {
+        return success(userAlertConfigService.createUserAlertConfig(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新用户报告预警配置")
+    public CommonResult<Boolean> updateUserAlertConfig(@Valid @RequestBody UserAlertConfigSaveReqVO updateReqVO) {
+        userAlertConfigService.updateUserAlertConfig(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除用户报告预警配置")
+    @Parameter(name = "id", description = "编号", required = true)
+    public CommonResult<Boolean> deleteUserAlertConfig(@RequestParam("id") String id) {
+        userAlertConfigService.deleteUserAlertConfig(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得用户报告预警配置")
+    @Parameter(name = "id", description = "编号", required = true)
+    public CommonResult<UserAlertConfigRespVO> getUserAlertConfig(@RequestParam("id") String id) {
+        UserAlertConfigDO userAlertConfig = userAlertConfigService.getUserAlertConfig(id);
+        return success(BeanUtils.toBean(userAlertConfig, UserAlertConfigRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得用户报告预警配置分页")
+    public CommonResult<PageResult<UserAlertConfigRespVO>> getUserAlertConfigPage(@Valid UserAlertConfigPageReqVO pageReqVO) {
+        PageResult<UserAlertConfigDO> pageResult = userAlertConfigService.getUserAlertConfigPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, UserAlertConfigRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出用户报告预警配置 Excel")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportUserAlertConfigExcel(@Valid UserAlertConfigPageReqVO pageReqVO,
+                                           HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<UserAlertConfigDO> list = userAlertConfigService.getUserAlertConfigPage(pageReqVO).getList();
+        ExcelUtils.write(response, "用户报告预警配置.xls", "数据", UserAlertConfigRespVO.class,
+                BeanUtils.toBean(list, UserAlertConfigRespVO.class));
+    }
+
+}

+ 28 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/useralertconfig/vo/UserAlertConfigPageReqVO.java

@@ -0,0 +1,28 @@
+package cn.start.tz.module.pressure2.controller.admin.useralertconfig.vo;
+
+import lombok.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.start.tz.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.start.tz.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 用户报告预警配置分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class UserAlertConfigPageReqVO extends PageParam {
+
+    @Schema(description = "系统用户id")
+    private String userId;
+
+    @Schema(description = "预警天数")
+    private Integer alertNum;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 30 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/useralertconfig/vo/UserAlertConfigRespVO.java

@@ -0,0 +1,30 @@
+package cn.start.tz.module.pressure2.controller.admin.useralertconfig.vo;
+
+import com.alibaba.excel.annotation.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 用户报告预警配置 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class UserAlertConfigRespVO {
+
+    @Schema(description = "主键")
+    @ExcelProperty("主键")
+    private String id;
+
+    @Schema(description = "系统用户id")
+    @ExcelProperty("系统用户id")
+    private String userId;
+
+    @Schema(description = "预警天数")
+    @ExcelProperty("预警天数")
+    private Integer alertNum;
+
+    @Schema(description = "创建时间")
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 20 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/controller/admin/useralertconfig/vo/UserAlertConfigSaveReqVO.java

@@ -0,0 +1,20 @@
+package cn.start.tz.module.pressure2.controller.admin.useralertconfig.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import jakarta.validation.constraints.*;
+
+@Schema(description = "管理后台 - 用户报告预警配置新增/修改 Request VO")
+@Data
+public class UserAlertConfigSaveReqVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
+    private String id;
+
+    @Schema(description = "系统用户id")
+    private String userId;
+
+    @Schema(description = "预警天数")
+    private Integer alertNum;
+
+}

+ 25 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/dataobject/useralertconfig/UserAlertConfigDO.java

@@ -0,0 +1,25 @@
+package cn.start.tz.module.pressure2.dal.dataobject.useralertconfig;
+
+import lombok.*;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.start.tz.framework.mybatis.core.dataobject.BaseDO;
+
+@TableName("pressure2_user_alert_config")
+@KeySequence("pressure2_user_alert_config_seq")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UserAlertConfigDO extends BaseDO {
+
+    @TableId(value = "id", type = IdType.ASSIGN_UUID)
+    private String id;
+
+    private String userId;
+
+    private Integer alertNum;
+
+}

+ 72 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/riskalert/RiskAlertMapper.java

@@ -0,0 +1,72 @@
+package cn.start.tz.module.pressure2.dal.mysql.riskalert;
+
+import cn.start.tz.framework.mybatis.core.mapper.BaseMapperX;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+public interface RiskAlertMapper extends BaseMapperX<Object> {
+
+    // ========== 锅炉 ==========
+
+    @Select("""
+            SELECT o.check_type, o.check_date, i.equip_code
+            FROM pressure_task_order o
+            JOIN pressure2_boiler_task_order_item i ON o.id = i.order_id AND i.task_status >= 400 AND i.task_status != 800
+            JOIN pressure2_boiler_task_order_item_report r ON i.id = r.order_item_id AND r.report_type = 100 AND r.task_status NOT IN (200, 800)
+            JOIN pressure2_boiler_task_order_item_report_user u ON r.id = u.report_id AND u.user_id = #{userId}
+            WHERE o.equip_main_type = 200
+              AND o.task_status NOT IN (200, 800)
+            """)
+    List<Map<String, Object>> selectMyBoilerAlert(@Param("userId") String userId);
+
+    @Select("""
+            <script>
+            SELECT o.dept_id, o.check_type, o.check_date, i.equip_code
+            FROM pressure_task_order o
+            JOIN pressure2_boiler_task_order_item i ON o.id = i.order_id AND i.task_status >= 400 AND i.task_status != 800
+            JOIN pressure2_boiler_task_order_item_report r ON i.id = r.order_item_id AND r.report_type = 100 AND r.task_status NOT IN (200, 800)
+            WHERE o.equip_main_type = 200
+              AND o.dept_id IN
+              <foreach collection="deptIds" item="deptId" open="(" separator="," close=")">
+                #{deptId}
+              </foreach>
+              AND o.task_status NOT IN (200, 800)
+            </script>
+            """)
+    List<Map<String, Object>> selectDeptBoilerAlert(@Param("deptIds") List<String> deptIds);
+
+    // ========== 管道 ==========
+
+    @Select("""
+            SELECT o.check_type, o.check_date, i.equip_code
+            FROM pressure_task_order o
+            JOIN pressure2_pipe_task_order_item i ON o.id = i.order_id AND i.task_status != 800
+            JOIN pressure2_pipe_task_order_item_report r ON o.id = r.order_id AND r.report_type = 100 AND r.task_status NOT IN (200, 800)
+            JOIN pressure2_pipe_task_order_item_report_user u ON r.id = u.report_id AND u.user_id = #{userId}
+            WHERE o.equip_main_type = 300
+              AND o.task_status NOT IN (200, 800)
+            """)
+    List<Map<String, Object>> selectMyPipeAlert(@Param("userId") String userId);
+
+    @Select("""
+            <script>
+            SELECT o.dept_id, o.check_type, o.check_date, i.equip_code
+            FROM pressure_task_order o
+            JOIN pressure2_pipe_task_order_item i ON o.id = i.order_id AND i.task_status != 800
+            JOIN pressure2_pipe_task_order_item_report r ON o.id = r.order_id AND r.report_type = 100 AND r.task_status NOT IN (200, 800)
+            WHERE o.equip_main_type = 300
+              AND o.dept_id IN
+              <foreach collection="deptIds" item="deptId" open="(" separator="," close=")">
+                #{deptId}
+              </foreach>
+              AND o.task_status NOT IN (200, 800)
+            </script>
+            """)
+    List<Map<String, Object>> selectDeptPipeAlert(@Param("deptIds") List<String> deptIds);
+
+}

+ 21 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/dal/mysql/useralertconfig/UserAlertConfigMapper.java

@@ -0,0 +1,21 @@
+package cn.start.tz.module.pressure2.dal.mysql.useralertconfig;
+
+import cn.start.tz.framework.common.pojo.PageResult;
+import cn.start.tz.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.start.tz.framework.mybatis.core.mapper.BaseMapperX;
+import cn.start.tz.module.pressure2.controller.admin.useralertconfig.vo.*;
+import cn.start.tz.module.pressure2.dal.dataobject.useralertconfig.UserAlertConfigDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface UserAlertConfigMapper extends BaseMapperX<UserAlertConfigDO> {
+
+    default PageResult<UserAlertConfigDO> selectPage(UserAlertConfigPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<UserAlertConfigDO>()
+                .eqIfPresent(UserAlertConfigDO::getUserId, reqVO.getUserId())
+                .eqIfPresent(UserAlertConfigDO::getAlertNum, reqVO.getAlertNum())
+                .betweenIfPresent(UserAlertConfigDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(UserAlertConfigDO::getId));
+    }
+
+}

+ 17 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/riskalert/RiskAlertService.java

@@ -0,0 +1,17 @@
+package cn.start.tz.module.pressure2.service.riskalert;
+
+import cn.start.tz.module.pressure2.controller.admin.riskalert.vo.*;
+
+import java.util.List;
+
+public interface RiskAlertService {
+
+    List<TaskOrderReportAlertCountRespVO> getMyBoilerAlert();
+
+    List<DeptAlertCountRespVO> getDeptBoilerAlert(List<String> deptIds);
+
+    List<TaskOrderReportAlertCountRespVO> getMyPipeAlert();
+
+    List<DeptAlertCountRespVO> getDeptPipeAlert(List<String> deptIds);
+
+}

+ 230 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/riskalert/RiskAlertServiceImpl.java

@@ -0,0 +1,230 @@
+package cn.start.tz.module.pressure2.service.riskalert;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.start.tz.module.pressure2.controller.admin.riskalert.vo.*;
+import cn.start.tz.module.pressure2.dal.dataobject.useralertconfig.UserAlertConfigDO;
+import cn.start.tz.module.pressure2.dal.mysql.riskalert.RiskAlertMapper;
+import cn.start.tz.module.pressure2.dal.mysql.useralertconfig.UserAlertConfigMapper;
+import cn.start.tz.module.system.api.dept.DeptApi;
+import cn.start.tz.module.system.api.dept.dto.DeptRespDTO;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static cn.start.tz.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+
+@Slf4j
+@Service
+public class RiskAlertServiceImpl implements RiskAlertService {
+
+    private static final int DEFAULT_ALERT_DAYS = 5;
+
+    // 锅炉检验性质:100内部检验 200外部检验 300耐压检验
+    private static final Map<Integer, String> BOILER_CHECK_TYPE_MAP = Map.of(
+            100, "内部检验", 200, "外部检验", 300, "耐压检验"
+    );
+    // 管道检验性质:100法定检验 200年度检查
+    private static final Map<Integer, String> PIPE_CHECK_TYPE_MAP = Map.of(
+            100, "定期检验", 200, "年度检查"
+    );
+
+    @Resource
+    private RiskAlertMapper riskAlertMapper;
+
+    @Resource
+    private UserAlertConfigMapper userAlertConfigMapper;
+
+    @Resource
+    private DeptApi deptApi;
+
+    // ============ 锅炉预警 ============
+
+    @Override
+    public List<TaskOrderReportAlertCountRespVO> getMyBoilerAlert() {
+        String userId = getLoginUserId();
+        if (StrUtil.isBlank(userId)) return Collections.emptyList();
+        return getMyAlertStats(userId, "boiler");
+    }
+
+    @Override
+    public List<DeptAlertCountRespVO> getDeptBoilerAlert(List<String> deptIds) {
+        if (CollUtil.isEmpty(deptIds)) return Collections.emptyList();
+        return getDeptAlertStats(deptIds, "boiler");
+    }
+
+    // ============ 管道预警 ============
+
+    @Override
+    public List<TaskOrderReportAlertCountRespVO> getMyPipeAlert() {
+        String userId = getLoginUserId();
+        if (StrUtil.isBlank(userId)) return Collections.emptyList();
+        return getMyAlertStats(userId, "pipe");
+    }
+
+    @Override
+    public List<DeptAlertCountRespVO> getDeptPipeAlert(List<String> deptIds) {
+        if (CollUtil.isEmpty(deptIds)) return Collections.emptyList();
+        return getDeptAlertStats(deptIds, "pipe");
+    }
+
+    // ============ 核心逻辑 ============
+
+    private List<TaskOrderReportAlertCountRespVO> getMyAlertStats(String userId, String equipType) {
+        int alertDays = getUserAlertDays(userId);
+
+        List<Map<String, Object>> rows;
+        try {
+            rows = "boiler".equals(equipType)
+                    ? riskAlertMapper.selectMyBoilerAlert(userId)
+                    : riskAlertMapper.selectMyPipeAlert(userId);
+        } catch (Exception e) {
+            log.error("[getMyAlertStats] 查询失败, equipType={}", equipType, e);
+            return Collections.emptyList();
+        }
+
+        return aggregateByCheckType(rows, alertDays, equipType);
+    }
+
+    private List<DeptAlertCountRespVO> getDeptAlertStats(List<String> deptIds, String equipType) {
+        int alertDays = DEFAULT_ALERT_DAYS;
+
+        List<Map<String, Object>> rows;
+        try {
+            rows = "boiler".equals(equipType)
+                    ? riskAlertMapper.selectDeptBoilerAlert(deptIds)
+                    : riskAlertMapper.selectDeptPipeAlert(deptIds);
+        } catch (Exception e) {
+            log.error("[getDeptAlertStats] 查询失败, equipType={}", equipType, e);
+            return Collections.emptyList();
+        }
+
+        // 批量获取部门名称
+        Map<String, String> deptNameMap = getDeptNameMap(deptIds);
+
+        // 按部门分组
+        Map<String, List<Map<String, Object>>> deptGrouped = rows.stream()
+                .collect(Collectors.groupingBy(row -> String.valueOf(row.get("dept_id"))));
+
+        List<DeptAlertCountRespVO> result = new ArrayList<>();
+        for (Map.Entry<String, List<Map<String, Object>>> entry : deptGrouped.entrySet()) {
+            String deptId = entry.getKey();
+            List<TaskOrderReportAlertCountRespVO> stats = aggregateByCheckType(entry.getValue(), alertDays, equipType);
+            if (!stats.isEmpty()) {
+                DeptAlertCountRespVO deptVO = new DeptAlertCountRespVO();
+                deptVO.setDeptId(deptId);
+                deptVO.setDeptName(deptNameMap.getOrDefault(deptId, deptId));
+                deptVO.setCheckTypeStats(stats);
+                deptVO.setTotalCount(stats.stream().mapToInt(TaskOrderReportAlertCountRespVO::getCount).sum());
+                result.add(deptVO);
+            }
+        }
+        return result;
+    }
+
+    // ---------- 工具方法 ----------
+
+    /**
+     * 按检验性质分组统计,只保留剩余工作日 <= alertDays 的记录
+     */
+    private List<TaskOrderReportAlertCountRespVO> aggregateByCheckType(List<Map<String, Object>> rows, int alertDays, String equipType) {
+        Map<Integer, String> checkTypeNameMap = "boiler".equals(equipType) ? BOILER_CHECK_TYPE_MAP : PIPE_CHECK_TYPE_MAP;
+        // 收集唯一 checkDate → 批量计算剩余工作日
+        Set<LocalDate> dateSet = new HashSet<>();
+        for (Map<String, Object> row : rows) {
+            Object checkDateObj = row.get("check_date");
+            if (checkDateObj instanceof java.sql.Date) {
+                dateSet.add(((java.sql.Date) checkDateObj).toLocalDate());
+            } else if (checkDateObj instanceof LocalDate) {
+                dateSet.add((LocalDate) checkDateObj);
+            }
+        }
+        Map<LocalDate, Integer> remainingMap = new HashMap<>();
+        for (LocalDate date : dateSet) {
+            remainingMap.put(date, calcRemainingWorkDays(date));
+        }
+
+        // 分类统计
+        Map<Integer, Set<String>> checkTypeMap = new LinkedHashMap<>();
+        for (Map<String, Object> row : rows) {
+            Integer checkType = toInt(row.get("check_type"));
+            Object checkDateObj = row.get("check_date");
+            String equipCode = (String) row.get("equip_code");
+            if (checkType == null || checkDateObj == null || StrUtil.isBlank(equipCode)) continue;
+
+            LocalDate checkDate = toLocalDate(checkDateObj);
+            if (checkDate == null) continue;
+
+            Integer remain = remainingMap.get(checkDate);
+            if (remain != null && remain <= alertDays) {
+                checkTypeMap.computeIfAbsent(checkType, k -> new LinkedHashSet<>()).add(equipCode);
+            }
+        }
+
+        List<TaskOrderReportAlertCountRespVO> result = new ArrayList<>();
+        for (Map.Entry<Integer, Set<String>> entry : checkTypeMap.entrySet()) {
+            TaskOrderReportAlertCountRespVO vo = new TaskOrderReportAlertCountRespVO();
+            vo.setCheckType(entry.getKey());
+            vo.setCheckTypeName(checkTypeNameMap.getOrDefault(entry.getKey(), "未知"));
+            vo.setEquipCodes(new ArrayList<>(entry.getValue()));
+            vo.setCount(entry.getValue().size());
+            result.add(vo);
+        }
+        result.sort(Comparator.comparing(TaskOrderReportAlertCountRespVO::getCheckType));
+        return result;
+    }
+
+    private int getUserAlertDays(String userId) {
+        UserAlertConfigDO config = userAlertConfigMapper.selectOne(
+                Wrappers.<UserAlertConfigDO>lambdaQuery().eq(UserAlertConfigDO::getUserId, userId));
+        return config != null && config.getAlertNum() != null ? config.getAlertNum() : DEFAULT_ALERT_DAYS;
+    }
+
+    private Map<String, String> getDeptNameMap(List<String> deptIds) {
+        try {
+            Map<String, DeptRespDTO> deptMap = deptApi.getDeptMap(deptIds);
+            return deptMap.entrySet().stream()
+                    .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getName()));
+        } catch (Exception e) {
+            log.warn("[getDeptNameMap] 查询部门名称失败", e);
+            return new HashMap<>();
+        }
+    }
+
+    /**
+     * 计算剩余工作日(不含周末)
+     */
+    private static int calcRemainingWorkDays(LocalDate checkDate) {
+        LocalDate today = LocalDate.now();
+        if (!checkDate.isAfter(today)) return 0;
+        int workDays = 0;
+        LocalDate d = today;
+        while (d.isBefore(checkDate)) {
+            d = d.plusDays(1);
+            if (d.getDayOfWeek() != DayOfWeek.SATURDAY && d.getDayOfWeek() != DayOfWeek.SUNDAY) {
+                workDays++;
+            }
+        }
+        return workDays;
+    }
+
+    private static Integer toInt(Object obj) {
+        if (obj == null) return null;
+        if (obj instanceof Number) return ((Number) obj).intValue();
+        try { return Integer.parseInt(obj.toString()); } catch (Exception e) { return null; }
+    }
+
+    private static LocalDate toLocalDate(Object obj) {
+        if (obj == null) return null;
+        if (obj instanceof java.sql.Date) return ((java.sql.Date) obj).toLocalDate();
+        if (obj instanceof LocalDate) return (LocalDate) obj;
+        return null;
+    }
+
+}

+ 21 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/useralertconfig/UserAlertConfigService.java

@@ -0,0 +1,21 @@
+package cn.start.tz.module.pressure2.service.useralertconfig;
+
+import cn.start.tz.module.pressure2.controller.admin.useralertconfig.vo.*;
+import cn.start.tz.module.pressure2.dal.dataobject.useralertconfig.UserAlertConfigDO;
+import cn.start.tz.framework.common.pojo.PageResult;
+import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.validation.Valid;
+
+public interface UserAlertConfigService extends IService<UserAlertConfigDO> {
+
+    String createUserAlertConfig(@Valid UserAlertConfigSaveReqVO createReqVO);
+
+    void updateUserAlertConfig(@Valid UserAlertConfigSaveReqVO updateReqVO);
+
+    void deleteUserAlertConfig(String id);
+
+    UserAlertConfigDO getUserAlertConfig(String id);
+
+    PageResult<UserAlertConfigDO> getUserAlertConfigPage(UserAlertConfigPageReqVO pageReqVO);
+
+}

+ 48 - 0
tz-module-pressure2/tz-module-pressure2-biz/src/main/java/cn/start/tz/module/pressure2/service/useralertconfig/UserAlertConfigServiceImpl.java

@@ -0,0 +1,48 @@
+package cn.start.tz.module.pressure2.service.useralertconfig;
+
+import cn.start.tz.module.pressure2.controller.admin.useralertconfig.vo.*;
+import cn.start.tz.module.pressure2.dal.dataobject.useralertconfig.UserAlertConfigDO;
+import cn.start.tz.module.pressure2.dal.mysql.useralertconfig.UserAlertConfigMapper;
+import cn.start.tz.framework.common.pojo.PageResult;
+import cn.start.tz.framework.common.util.object.BeanUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+@Service
+@Validated
+public class UserAlertConfigServiceImpl extends ServiceImpl<UserAlertConfigMapper, UserAlertConfigDO> implements UserAlertConfigService {
+
+    @Resource
+    private UserAlertConfigMapper userAlertConfigMapper;
+
+    @Override
+    public String createUserAlertConfig(UserAlertConfigSaveReqVO createReqVO) {
+        UserAlertConfigDO userAlertConfig = BeanUtils.toBean(createReqVO, UserAlertConfigDO.class);
+        userAlertConfigMapper.insert(userAlertConfig);
+        return userAlertConfig.getId();
+    }
+
+    @Override
+    public void updateUserAlertConfig(UserAlertConfigSaveReqVO updateReqVO) {
+        UserAlertConfigDO updateObj = BeanUtils.toBean(updateReqVO, UserAlertConfigDO.class);
+        userAlertConfigMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteUserAlertConfig(String id) {
+        userAlertConfigMapper.deleteById(id);
+    }
+
+    @Override
+    public UserAlertConfigDO getUserAlertConfig(String id) {
+        return userAlertConfigMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<UserAlertConfigDO> getUserAlertConfigPage(UserAlertConfigPageReqVO pageReqVO) {
+        return userAlertConfigMapper.selectPage(pageReqVO);
+    }
+
+}