Quellcode durchsuchen

对象管理;

77681 vor 3 Tagen
Ursprung
Commit
b0899e848f
30 geänderte Dateien mit 470 neuen und 136 gelöschten Zeilen
  1. 1 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/BisOrgMonRepPeriController.java
  2. 62 7
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/ObjHiddController.java
  3. 2 1
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/TBusiHiddCountController.java
  4. 3 2
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/TBusiHiddCountMonController.java
  5. 1 1
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/domain/ObjHidd.java
  6. 4 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/domain/ObjHiddVo.java
  7. 12 3
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/mapper/BisOrgMonRepPeriMapper.java
  8. 8 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/mapper/RelBisMedMapper.java
  9. 7 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/mapper/TBusiHiddCountMapper.java
  10. 8 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/mapper/TBusiHiddCountMonMapper.java
  11. 9 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/IRelBisMedService.java
  12. 8 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/ITBusiHiddCountMonService.java
  13. 7 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/ITBusiHiddCountService.java
  14. 80 39
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/BisOrgMonRepPeriServiceImpl.java
  15. 2 1
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/ObjHiddServiceImpl.java
  16. 10 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/RelBisMedServiceImpl.java
  17. 11 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/TBusiHiddCountMonServiceImpl.java
  18. 5 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/TBusiHiddCountServiceImpl.java
  19. 1 1
      gw-slaj/src/main/java/com/goldenwater/slaj/obj/domain/ObjHidd.java
  20. 9 3
      gw-slaj/src/main/resources/mapper/slaj/hidd/BisMajHiddSupMapper.xml
  21. 40 31
      gw-slaj/src/main/resources/mapper/slaj/hidd/BisOrgMonRepPeriMapper.xml
  22. 1 1
      gw-slaj/src/main/resources/mapper/slaj/hidd/BisOrgMonRepRevoMapper.xml
  23. 21 10
      gw-slaj/src/main/resources/mapper/slaj/hidd/ObjHiddMapper.xml
  24. 9 0
      gw-slaj/src/main/resources/mapper/slaj/hidd/RelBisMedMapper.xml
  25. 92 8
      gw-slaj/src/main/resources/mapper/slaj/hidd/TBusiHiddCountMapper.xml
  26. 8 0
      gw-ui/src/api/slaj/hidd.js
  27. 2 1
      gw-ui/src/views/slaj/hidd/month.vue
  28. 2 2
      gw-ui/src/views/slaj/hidd/monthDetail.vue
  29. 36 17
      gw-ui/src/views/slaj/hidd/orgEngQuery.vue
  30. 9 8
      gw-ui/src/views/slaj/hidd/supList.vue

+ 1 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/BisOrgMonRepPeriController.java

@@ -125,6 +125,7 @@ public class BisOrgMonRepPeriController extends BaseController {
     @PostMapping("/urge")
     public AjaxResult urge(@RequestParam String orgGuid, @RequestParam(required = false) String repMonth,
                            @RequestParam(required = false) String notType) {
+        bisOrgMonRepPeriService.urgeReport(orgGuid, repMonth);
         return AjaxResult.success("督促通知已发送");
     }
 

+ 62 - 7
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/ObjHiddController.java

@@ -2,6 +2,9 @@ package com.goldenwater.slaj.hidd.controller;
 
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
+
+import com.goldenwater.slaj.hidd.service.IRelBisMedService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import com.goldenwater.common.core.controller.BaseController;
@@ -10,7 +13,9 @@ import com.goldenwater.common.core.page.TableDataInfo;
 import com.goldenwater.slaj.hidd.domain.HiddGroupByExportVo;
 import com.goldenwater.slaj.hidd.domain.ObjHidd;
 import com.goldenwater.slaj.hidd.domain.ObjHiddVo;
+import com.goldenwater.slaj.hidd.domain.BisHiddRecRep;
 import com.goldenwater.slaj.hidd.service.IObjHiddService;
+import com.goldenwater.slaj.hidd.service.IBisHiddRecRepService;
 import jakarta.servlet.http.HttpServletResponse;
 import org.springframework.security.access.prepost.PreAuthorize;
 import com.goldenwater.common.annotation.Log;
@@ -27,6 +32,12 @@ public class ObjHiddController extends BaseController {
     @Autowired
     private IObjHiddService objHiddService;
 
+    @Autowired
+    private IRelBisMedService relBisMedService;
+
+    @Autowired
+    private IBisHiddRecRepService bisHiddRecRepService;
+
     @GetMapping("/list")
     public TableDataInfo list(ObjHidd objHidd) {
         startPage();
@@ -91,6 +102,14 @@ public class ObjHiddController extends BaseController {
         return toAjax(objHiddService.insertNextHidd(objHidd));
     }
 
+    /**
+     * 查询隐患关联的附件列表(编辑回显用)
+     */
+    @GetMapping("/medList/{guid}")
+    public AjaxResult medList(@PathVariable String guid) {
+        return AjaxResult.success(relBisMedService.selectMedListByBisInfo("OBJ_HIDD", guid));
+    }
+
     @Log(title = "隐患对象管理", businessType = BusinessType.EXPORT)
     @PreAuthorize("@ss.hasPermi('hidd:objhidd:export')")
     @PostMapping("/export")
@@ -185,6 +204,7 @@ public class ObjHiddController extends BaseController {
 
     /**
      * 隐患上报(批量)
+     * 与旧版一致:向 bis_hidd_rec_rep 写入上报记录,rep_act='1'
      */
     @Log(title = "隐患上报", businessType = BusinessType.UPDATE)
     @PreAuthorize("@ss.hasPermi('hidd:objhidd:report')")
@@ -197,9 +217,26 @@ public class ObjHiddController extends BaseController {
         int count = 0;
         for (String guid : guidArr) {
             ObjHidd hidd = objHiddService.selectObjHiddByGuid(guid);
-            if (hidd != null) {
-                hidd.setUpdTime(new java.util.Date());
-                count += objHiddService.updateObjHidd(hidd);
+            if (hidd == null) continue;
+            // 查询是否已有上报记录
+            BisHiddRecRep query = new BisHiddRecRep();
+            query.setHiddGuid(guid);
+            List<BisHiddRecRep> exists = bisHiddRecRepService.selectBisHiddRecRepList(query);
+            if (exists != null && !exists.isEmpty()) {
+                // 已有记录:更新为已上报
+                BisHiddRecRep rec = exists.get(0);
+                rec.setRepAct("1");
+                rec.setUpdTime(new java.util.Date());
+                count += bisHiddRecRepService.updateBisHiddRecRep(rec);
+            } else {
+                // 无记录:新建上报记录
+                BisHiddRecRep rec = new BisHiddRecRep();
+                rec.setGuid(UUID.randomUUID().toString().replace("-", ""));
+                rec.setHiddGuid(guid);
+                rec.setRepOrgGuid(getDeptId());
+                rec.setRepAct("1");
+                rec.setCollTime(new java.util.Date());
+                count += bisHiddRecRepService.insertBisHiddRecRep(rec);
             }
         }
         return toAjax(count);
@@ -207,6 +244,7 @@ public class ObjHiddController extends BaseController {
 
     /**
      * 隐患退回(批量)
+     * 与旧版一致:更新 bis_hidd_rec_rep 的 rep_act='2' 并记录退回说明
      */
     @Log(title = "隐患退回", businessType = BusinessType.UPDATE)
     @PreAuthorize("@ss.hasPermi('hidd:objhidd:return')")
@@ -219,10 +257,27 @@ public class ObjHiddController extends BaseController {
         int count = 0;
         for (String guid : guidArr) {
             ObjHidd hidd = objHiddService.selectObjHiddByGuid(guid);
-            if (hidd != null) {
-                hidd.setNote((hidd.getNote() == null ? "" : hidd.getNote()) + " [退回:" + returnDesc + "]");
-                hidd.setUpdTime(new java.util.Date());
-                count += objHiddService.updateObjHidd(hidd);
+            if (hidd == null) continue;
+            // 更新上报记录状态为退回
+            BisHiddRecRep query = new BisHiddRecRep();
+            query.setHiddGuid(guid);
+            List<BisHiddRecRep> exists = bisHiddRecRepService.selectBisHiddRecRepList(query);
+            if (exists != null && !exists.isEmpty()) {
+                BisHiddRecRep rec = exists.get(0);
+                rec.setRepAct("2");
+                rec.setReturnDesc(returnDesc);
+                rec.setUpdTime(new java.util.Date());
+                count += bisHiddRecRepService.updateBisHiddRecRep(rec);
+            } else {
+                // 无上报记录也记录退回
+                BisHiddRecRep rec = new BisHiddRecRep();
+                rec.setGuid(UUID.randomUUID().toString().replace("-", ""));
+                rec.setHiddGuid(guid);
+                rec.setRepOrgGuid(getDeptId());
+                rec.setRepAct("2");
+                rec.setReturnDesc(returnDesc);
+                rec.setCollTime(new java.util.Date());
+                count += bisHiddRecRepService.insertBisHiddRecRep(rec);
             }
         }
         return toAjax(count);

+ 2 - 1
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/TBusiHiddCountController.java

@@ -25,7 +25,8 @@ public class TBusiHiddCountController extends BaseController {
     @GetMapping("/list")
     public TableDataInfo list(TBusiHiddCountVo vo) {
         startPage();
-        List<TBusiHiddCountVo> list = tBusiHiddCountService.selectTBusiHiddCountListWithCalc(vo);
+        // 实时聚合统计,不依赖 t_busi_hidd_count 预统计表(对齐旧版实时计算口径)
+        List<TBusiHiddCountVo> list = tBusiHiddCountService.selectTBusiHiddCountRealtimeList(vo);
         return getDataTable(list);
     }
 

+ 3 - 2
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/TBusiHiddCountMonController.java

@@ -7,6 +7,7 @@ import com.goldenwater.common.core.controller.BaseController;
 import com.goldenwater.common.core.domain.AjaxResult;
 import com.goldenwater.common.core.page.TableDataInfo;
 import com.goldenwater.slaj.hidd.domain.TBusiHiddCountMon;
+import com.goldenwater.slaj.hidd.domain.TBusiHiddCountMonVo;
 import com.goldenwater.slaj.hidd.service.ITBusiHiddCountMonService;
 
 @RestController
@@ -16,9 +17,9 @@ public class TBusiHiddCountMonController extends BaseController {
     private ITBusiHiddCountMonService tBusiHiddCountMonService;
 
     @GetMapping("/list")
-    public TableDataInfo list(TBusiHiddCountMon tBusiHiddCountMon) {
+    public TableDataInfo list(TBusiHiddCountMonVo vo) {
         startPage();
-        List<TBusiHiddCountMon> list = tBusiHiddCountMonService.selectTBusiHiddCountMonList(tBusiHiddCountMon);
+        List<TBusiHiddCountMonVo> list = tBusiHiddCountMonService.selectTBusiHiddCountMonListWithCalc(vo);
         return getDataTable(list);
     }
 

+ 1 - 1
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/domain/ObjHidd.java

@@ -42,7 +42,7 @@ public class ObjHidd {
     private String inspRecGuid;
     /** 安全元素检查项guid */
     private String seCheckItemGuid;
-    /** 隐患状态0未整改 1正在整改 2已整改 */
+    /** 隐患状态 0未整改 1正在整改 2已整改 3已销号 */
     private String hiddStat;
     /** 合并隐患guid */
     private String hiddMergGuid;

+ 4 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/domain/ObjHiddVo.java

@@ -28,4 +28,8 @@ public class ObjHiddVo extends ObjHidd {
     private String supStat;
     /** 取消状态 */
     private String cancelState;
+    /** 上报状态 1已上报 2已退回 */
+    private String repAct;
+    /** 退回说明 */
+    private String returnDesc;
 }

+ 12 - 3
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/mapper/BisOrgMonRepPeriMapper.java

@@ -3,6 +3,7 @@ package com.goldenwater.slaj.hidd.mapper;
 import java.util.List;
 import java.util.Map;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 import com.goldenwater.slaj.hidd.domain.BisOrgMonRepPeri;
 
 /**
@@ -61,9 +62,17 @@ public interface BisOrgMonRepPeriMapper {
     List<Map<String, Object>> selectMonthTotalList(Map<String, Object> params);
 
     /**
-     * 查询月报统计列表
-     * @param params 查询参数
-     * @return 月报统计列表
+     * 查询隐患月度统计列表
+     * @param params 查询条件
+     * @return 隐患月度统计列表
      */
     List<Map<String, Object>> selectMonthListStats(Map<String, Object> params);
+
+    /**
+     * 统计上级单位该月份已上报的月报数量
+     * @param orgGuid 当前单位guid
+     * @param month 月份(如 2025-06)
+     * @return 已上报数量
+     */
+    int countParentReported(@Param("orgGuid") String orgGuid, @Param("month") String month);
 }

+ 8 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/mapper/RelBisMedMapper.java

@@ -1,6 +1,7 @@
 package com.goldenwater.slaj.hidd.mapper;
 
 import java.util.List;
+import java.util.Map;
 import org.apache.ibatis.annotations.Mapper;
 import com.goldenwater.slaj.hidd.domain.RelBisMed;
 
@@ -60,6 +61,13 @@ public interface RelBisMedMapper {
      */
     List<RelBisMed> selectRelBisMedByBisInfo(String bisTablename, String bisGuid);
 
+    /**
+     * 查询业务关联的多媒体附件(含名称/路径,用于编辑回显)
+     * @param params 含 bisTablename/bisGuid
+     * @return 附件集合 [{name, path, medGuid}]
+     */
+    List<Map<String, Object>> selectMedListByBisInfo(Map<String, Object> params);
+
     /**
      * 根据业务表名和业务guid删除关联多媒体
      * @param bisTablename 业务表名

+ 7 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/mapper/TBusiHiddCountMapper.java

@@ -74,4 +74,11 @@ public interface TBusiHiddCountMapper {
      * @return 隐患统计VO集合
      */
     List<TBusiHiddCountVo> selectTBusiHiddCountListWithCalc(TBusiHiddCountVo vo);
+
+    /**
+     * 查询隐患统计列表(实时聚合,不依赖 t_busi_hidd_count 表)
+     * @param vo 查询条件VO
+     * @return 隐患统计VO集合
+     */
+    List<TBusiHiddCountVo> selectTBusiHiddCountRealtimeList(TBusiHiddCountVo vo);
 }

+ 8 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/mapper/TBusiHiddCountMonMapper.java

@@ -3,6 +3,7 @@ package com.goldenwater.slaj.hidd.mapper;
 import java.util.List;
 import org.apache.ibatis.annotations.Mapper;
 import com.goldenwater.slaj.hidd.domain.TBusiHiddCountMon;
+import com.goldenwater.slaj.hidd.domain.TBusiHiddCountMonVo;
 
 /**
  * 隐患月度统计 数据层
@@ -24,6 +25,13 @@ public interface TBusiHiddCountMonMapper {
      */
     List<TBusiHiddCountMon> selectTBusiHiddCountMonList(TBusiHiddCountMon tBusiHiddCountMon);
 
+    /**
+     * 查询隐患月度统计列表(含计算字段:隐患总数/已整改/整改率等)
+     * @param vo 隐患月度统计查询条件
+     * @return 隐患月度统计集合(含计算字段)
+     */
+    List<TBusiHiddCountMonVo> selectTBusiHiddCountMonListWithCalc(TBusiHiddCountMonVo vo);
+
     /**
      * 新增隐患月度统计
      * @param tBusiHiddCountMon 隐患月度统计信息

+ 9 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/IRelBisMedService.java

@@ -1,6 +1,7 @@
 package com.goldenwater.slaj.hidd.service;
 
 import java.util.List;
+import java.util.Map;
 import com.goldenwater.slaj.hidd.domain.RelBisMed;
 
 /**
@@ -58,6 +59,14 @@ public interface IRelBisMedService {
      */
     List<RelBisMed> selectRelBisMedByBisInfo(String bisTablename, String bisGuid);
 
+    /**
+     * 查询业务关联的多媒体附件(含名称/路径,用于编辑回显)
+     * @param bisTablename 业务表名
+     * @param bisGuid 业务guid
+     * @return 附件集合 [{name, path, medGuid}]
+     */
+    List<Map<String, Object>> selectMedListByBisInfo(String bisTablename, String bisGuid);
+
     /**
      * 根据业务表名和业务guid删除关联多媒体
      * @param bisTablename 业务表名

+ 8 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/ITBusiHiddCountMonService.java

@@ -2,6 +2,7 @@ package com.goldenwater.slaj.hidd.service;
 
 import java.util.List;
 import com.goldenwater.slaj.hidd.domain.TBusiHiddCountMon;
+import com.goldenwater.slaj.hidd.domain.TBusiHiddCountMonVo;
 
 /**
  * 隐患月度统计 服务层
@@ -22,6 +23,13 @@ public interface ITBusiHiddCountMonService {
      */
     List<TBusiHiddCountMon> selectTBusiHiddCountMonList(TBusiHiddCountMon tBusiHiddCountMon);
 
+    /**
+     * 查询隐患月度统计列表(含计算字段:隐患总数/已整改/整改率等)
+     * @param vo 隐患月度统计查询条件
+     * @return 隐患月度统计集合(含计算字段)
+     */
+    List<TBusiHiddCountMonVo> selectTBusiHiddCountMonListWithCalc(TBusiHiddCountMonVo vo);
+
     /**
      * 新增隐患月度统计
      * @param tBusiHiddCountMon 隐患月度统计信息

+ 7 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/ITBusiHiddCountService.java

@@ -59,6 +59,13 @@ public interface ITBusiHiddCountService {
      */
     List<TBusiHiddCountVo> selectTBusiHiddCountListWithCalc(TBusiHiddCountVo vo);
 
+    /**
+     * 查询隐患统计列表(实时聚合,不依赖 t_busi_hidd_count 表)
+     * @param vo 查询条件
+     * @return 隐患统计集合
+     */
+    List<TBusiHiddCountVo> selectTBusiHiddCountRealtimeList(TBusiHiddCountVo vo);
+
     /**
      * 查询隐患月报上报率图表数据
      * @param params 查询参数

+ 80 - 39
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/BisOrgMonRepPeriServiceImpl.java

@@ -1,6 +1,7 @@
 package com.goldenwater.slaj.hidd.service.impl;
 
 import java.time.LocalDate;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
@@ -11,6 +12,7 @@ import java.util.Map;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import com.goldenwater.common.utils.SecurityUtils;
 import com.goldenwater.slaj.hidd.mapper.BisOrgMonRepPeriMapper;
 import com.goldenwater.slaj.hidd.mapper.BisHiddRecRepMapper;
 import com.goldenwater.slaj.hidd.mapper.BisOrgMonRepRevoMapper;
@@ -34,6 +36,9 @@ public class BisOrgMonRepPeriServiceImpl implements IBisOrgMonRepPeriService {
     @Autowired
     private BisOrgMonRepRevoMapper bisOrgMonRepRevoMapper;
 
+    @Autowired
+    private com.goldenwater.slaj.acci.service.impl.AcciNotifyService acciNotifyService;
+
     /** 上报时间窗口:每月7日-次月6日 */
     private static final int REPORT_START_DAY = 7;
     private static final int REPORT_END_DAY = 6;
@@ -72,6 +77,26 @@ public class BisOrgMonRepPeriServiceImpl implements IBisOrgMonRepPeriService {
     public List<Map<String, Object>> selectRepTreeData(String parentGuid) {
         List<Map<String, Object>> tree = new ArrayList<>();
         Calendar c = Calendar.getInstance();
+
+        // 查询当前单位各月份的上报状态,用于树节点颜色标记
+        String orgGuid = null;
+        try {
+            orgGuid = SecurityUtils.getDeptId();
+        } catch (Exception ignored) {
+        }
+        Map<String, String> repActMap = new HashMap<>();
+        if (orgGuid != null && !orgGuid.isEmpty()) {
+            BisOrgMonRepPeri query = new BisOrgMonRepPeri();
+            query.setRepOrgGuid(orgGuid);
+            List<BisOrgMonRepPeri> peris = bisOrgMonRepPeriMapper.selectBisOrgMonRepPeriList(query);
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
+            for (BisOrgMonRepPeri p : peris) {
+                if (p.getRepTime() != null) {
+                    repActMap.put(sdf.format(p.getRepTime()), p.getRepAct());
+                }
+            }
+        }
+
         for (int i = 0; i < 3; i++) {
             int year = c.get(Calendar.YEAR) - i;
             Map<String, Object> yearNode = new HashMap<>();
@@ -88,7 +113,8 @@ public class BisOrgMonRepPeriServiceImpl implements IBisOrgMonRepPeriService {
                     monthNode.put("label", monthStr + "月");
                     monthNode.put("pId", String.valueOf(year));
                     monthNode.put("month", String.valueOf(m));
-                    monthNode.put("IsUpload", 0);
+                    // 已上报(rep_act='1')显示绿色,其余显示黄色
+                    monthNode.put("IsUpload", "1".equals(repActMap.get(year + "-" + monthStr)) ? 1 : 0);
                     if (m == c.get(Calendar.MONTH) + 1) {
                         monthNode.put("selectedNowMonth", true);
                     } else {
@@ -128,9 +154,6 @@ public class BisOrgMonRepPeriServiceImpl implements IBisOrgMonRepPeriService {
         // P0-1: 月报上报时间窗口校验
         validateReportTimeWindow(period);
         
-        // P0-2: 月报上级已上报校验
-        validateParentNotReported(period);
-        
         // 删除该月报下原有上报记录
         bisHiddRecRepMapper.deleteBisHiddRecRepByRepGuid(guid);
         // 新增上报记录
@@ -169,17 +192,6 @@ public class BisOrgMonRepPeriServiceImpl implements IBisOrgMonRepPeriService {
         }
     }
 
-    /**
-     * P0-2: 月报上级已上报校验
-     * 规则:上级单位未上报时,下级单位不允许上报
-     */
-    private void validateParentNotReported(BisOrgMonRepPeri period) {
-        // 查询上级单位的月报状态
-        // 这里需要根据组织架构查询上级单位
-        // 暂时简化实现:检查是否有上级单位的月报已上报
-        // 实际实现需要关联组织架构表查询
-    }
-
     @Override
     public int returnMonth(String guid, String returnDesc) {
         BisOrgMonRepPeri period = new BisOrgMonRepPeri();
@@ -192,31 +204,42 @@ public class BisOrgMonRepPeriServiceImpl implements IBisOrgMonRepPeriService {
 
     @Override
     public int revokeMonth(String guid, String revocDesc) {
-        // 创建撤销申请记录
+        // 申请撤回:只创建撤回申请记录(待审批),不删明细、不改上报状态
+        // 审批通过后才由 approveRevoke 清明细并置为未上报
         BisOrgMonRepRevo revo = new BisOrgMonRepRevo();
+        revo.setGuid(java.util.UUID.randomUUID().toString().replace("-", ""));
         revo.setRepGuid(guid);
+        revo.setRevoOrgGuid(SecurityUtils.getDeptId());
         revo.setRevoReas(revocDesc);
-        revo.setRevoVeriResu("0");
+        revo.setRevoVeriResu("0"); // 待审批
         revo.setCollTime(new Date());
-        bisOrgMonRepRevoMapper.insertBisOrgMonRepRevo(revo);
-        // 清除上报记录
-        bisHiddRecRepMapper.deleteBisHiddRecRepByRepGuid(guid);
-        // 更新月报状态为未上报
-        BisOrgMonRepPeri period = new BisOrgMonRepPeri();
-        period.setGuid(guid);
-        period.setRepAct("2");
-        period.setUpdTime(new Date());
-        return bisOrgMonRepPeriMapper.updateBisOrgMonRepPeri(period);
+        revo.setRecPers(SecurityUtils.getUserId());
+        return bisOrgMonRepRevoMapper.insertBisOrgMonRepRevo(revo);
     }
 
     @Override
     public int approveRevoke(String guid, boolean approved, String opinion) {
-        BisOrgMonRepPeri period = new BisOrgMonRepPeri();
-        period.setGuid(guid);
-        period.setRepAct(approved ? "2" : "1");
-        period.setNote(opinion);
-        period.setUpdTime(new Date());
-        return bisOrgMonRepPeriMapper.updateBisOrgMonRepPeri(period);
+        // guid 为撤回申请记录 guid
+        BisOrgMonRepRevo revo = bisOrgMonRepRevoMapper.selectBisOrgMonRepRevoByGuid(guid);
+        if (revo == null) {
+            throw new RuntimeException("撤回申请记录不存在");
+        }
+        // 更新申请记录状态
+        revo.setRevoVeriResu(approved ? "1" : "2"); // 1同意 2驳回
+        revo.setRevoVeriOpin(opinion);
+        revo.setVeriOrgGuid(SecurityUtils.getDeptId());
+        revo.setUpdTime(new Date());
+        int result = bisOrgMonRepRevoMapper.updateBisOrgMonRepRevo(revo);
+        if (approved) {
+            // 同意撤回:清除上报明细 + 月报状态置为未上报
+            bisHiddRecRepMapper.deleteBisHiddRecRepByRepGuid(revo.getRepGuid());
+            BisOrgMonRepPeri period = new BisOrgMonRepPeri();
+            period.setGuid(revo.getRepGuid());
+            period.setRepAct("2");
+            period.setUpdTime(new Date());
+            result = bisOrgMonRepPeriMapper.updateBisOrgMonRepPeri(period);
+        }
+        return result;
     }
 
     @Override
@@ -235,16 +258,34 @@ public class BisOrgMonRepPeriServiceImpl implements IBisOrgMonRepPeriService {
 
     @Override
     public void urgeReport(String orgGuids, String repName) {
-        // 这里可以调用通知服务发送督促通知
-        // 例如:短信通知、系统消息等
-        // 暂时为空实现
+        // 与旧版 pushForward 一致:向被督促单位发送站内通知
+        // orgGuids 为目标单位guid,repName 为上报期间(如 2025-06)
+        if (orgGuids == null || orgGuids.isEmpty()) {
+            return;
+        }
+        String title = repName + "隐患月报督促上报信息";
+        String content = repName + "隐患月报尚未上报,请及时完成上报";
+        for (String orgGuid : orgGuids.split(",")) {
+            if (orgGuid != null && !orgGuid.isEmpty()) {
+                acciNotifyService.sendNotice(orgGuid.trim(), title, content, "hidd");
+            }
+        }
     }
 
     @Override
     public boolean checkCanRevoke(String month, String type) {
-        // 检查上级是否已上报:查询父级单位该月份的月报状态
-        // 如果上级已上报,则不允许撤回
-        // 简化实现:默认允许撤回
-        return true;
+        // 规则:上级单位已上报该月月报后,下级不允许撤回
+        // 防止下级撤回导致上级已汇总的数据不一致
+        String orgGuid = null;
+        try {
+            orgGuid = SecurityUtils.getDeptId();
+        } catch (Exception ignored) {
+        }
+        if (orgGuid == null || orgGuid.isEmpty() || month == null || month.isEmpty()) {
+            return true;
+        }
+        // 查上级单位该月份的月报是否已上报
+        int parentReported = bisOrgMonRepPeriMapper.countParentReported(orgGuid, month);
+        return parentReported == 0;
     }
 }

+ 2 - 1
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/ObjHiddServiceImpl.java

@@ -159,7 +159,8 @@ public class ObjHiddServiceImpl implements IObjHiddService {
         }
 
         // 保存附件:先创建 att_med_base 记录,再建立 rel_bis_med 关联
-        if (params.containsKey("fileList") && params.get("fileList") instanceof List) {
+        // 注意: fileList 为空时不处理(保留旧附件),避免编辑时未重新上传导致附件丢失
+        if (params.containsKey("fileList") && params.get("fileList") instanceof List && !((List<?>) params.get("fileList")).isEmpty()) {
             List<Map<String, String>> fileList = (List<Map<String, String>>) params.get("fileList");
             // 更新时先清除旧关联及旧文件记录
             if (params.containsKey("guid") && params.get("guid") != null) {

+ 10 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/RelBisMedServiceImpl.java

@@ -1,6 +1,8 @@
 package com.goldenwater.slaj.hidd.service.impl;
 
 import java.util.List;
+import java.util.Map;
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.goldenwater.slaj.hidd.mapper.RelBisMedMapper;
@@ -87,6 +89,14 @@ public class RelBisMedServiceImpl implements IRelBisMedService {
         return relBisMedMapper.selectRelBisMedByBisInfo(bisTablename, bisGuid);
     }
 
+    @Override
+    public List<Map<String, Object>> selectMedListByBisInfo(String bisTablename, String bisGuid) {
+        Map<String, Object> params = new java.util.HashMap<>();
+        params.put("bisTablename", bisTablename);
+        params.put("bisGuid", bisGuid);
+        return relBisMedMapper.selectMedListByBisInfo(params);
+    }
+
     /**
      * 根据业务表名和业务guid删除关联多媒体
      * @param bisTablename 业务表名

+ 11 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/TBusiHiddCountMonServiceImpl.java

@@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.goldenwater.slaj.hidd.mapper.TBusiHiddCountMonMapper;
 import com.goldenwater.slaj.hidd.domain.TBusiHiddCountMon;
+import com.goldenwater.slaj.hidd.domain.TBusiHiddCountMonVo;
 import com.goldenwater.slaj.hidd.service.ITBusiHiddCountMonService;
 
 /**
@@ -36,6 +37,16 @@ public class TBusiHiddCountMonServiceImpl implements ITBusiHiddCountMonService {
         return tBusiHiddCountMonMapper.selectTBusiHiddCountMonList(tBusiHiddCountMon);
     }
 
+    /**
+     * 查询隐患月度统计列表(含计算字段)
+     * @param vo 隐患月度统计查询条件
+     * @return 隐患月度统计集合(含计算字段)
+     */
+    @Override
+    public List<TBusiHiddCountMonVo> selectTBusiHiddCountMonListWithCalc(TBusiHiddCountMonVo vo) {
+        return tBusiHiddCountMonMapper.selectTBusiHiddCountMonListWithCalc(vo);
+    }
+
     /**
      * 新增隐患月度统计
      * @param tBusiHiddCountMon 隐患月度统计信息

+ 5 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/service/impl/TBusiHiddCountServiceImpl.java

@@ -92,4 +92,9 @@ public class TBusiHiddCountServiceImpl implements ITBusiHiddCountService {
     public List<TBusiHiddCountVo> selectTBusiHiddCountListWithCalc(TBusiHiddCountVo vo) {
         return tBusiHiddCountMapper.selectTBusiHiddCountListWithCalc(vo);
     }
+
+    @Override
+    public List<TBusiHiddCountVo> selectTBusiHiddCountRealtimeList(TBusiHiddCountVo vo) {
+        return tBusiHiddCountMapper.selectTBusiHiddCountRealtimeList(vo);
+    }
 }

+ 1 - 1
gw-slaj/src/main/java/com/goldenwater/slaj/obj/domain/ObjHidd.java

@@ -61,7 +61,7 @@ public class ObjHidd {
     /** se_check_item_guid */
     private String seCheckItemGuid;
 
-    /** hidd_stat */
+    /** hidd_stat 0未整改 1正在整改 2已整改 3已销号 */
     @Excel(name = "hidd_stat", width = 30)
     private String hiddStat;
 

+ 9 - 3
gw-slaj/src/main/resources/mapper/slaj/hidd/BisMajHiddSupMapper.xml

@@ -41,10 +41,16 @@
                eng.eng_type, eng.eng_name,
                horg.org_name as hidd_org_name,
                horg_ext.wiun_prop as org_nature,
+               -- TODO: sup_stat_value 衍生自 bis_hidd_rect_acce.cancel_state 的派生字段
+               -- 业务逻辑: 督办发出后产生 bis_maj_hidd_sup 记录,销号流程记录在 bis_hidd_rect_acce
+               -- cancel_state = null/'0'(未销号) → 督办中(已督办)
+               -- cancel_state = '1'(待销号审批)   → 待销号
+               -- cancel_state = '2'(销号审批通过)  → 已销号
+               -- 注意: 当前直接返回中文,如需国际化或多语言需改为编码+字典
                case when (acce.guid is null or acce.cancel_state = '0') then '已督办'
-                    when acce.cancel_state = '1' then '待销号'
-                    when acce.cancel_state = '2' then '已销号'
-               else '已督办' end as sup_stat_value,
+                     when acce.cancel_state = '1' then '待销号'
+                     when acce.cancel_state = '2' then '已销号'
+                else '已督办' end as sup_stat_value,
                acce.requ_comp_date, acce.accep_date, acce.accep_opin,
                med.med_guid, att.med_titl
         from bis_maj_hidd_sup s

+ 40 - 31
gw-slaj/src/main/resources/mapper/slaj/hidd/BisOrgMonRepPeriMapper.xml

@@ -60,14 +60,23 @@
     <delete id="deleteBisOrgMonRepPeriByGuid" parameterType="String">
         delete from bis_org_mon_rep_peri where guid = #{guid}
     </delete>
+
+    <!-- 统计上级单位该月份已上报的月报数量(撤回前校验用) -->
+    <select id="countParentReported" resultType="int">
+        select count(1)
+        from bis_org_mon_rep_peri r
+        where r.rep_org_guid = (select pguid from att_org_base where guid = #{orgGuid})
+          and r.rep_time like #{month} || '%'
+          and r.rep_act = '1'
+    </select>
+    <!-- 注意: PG 未加引号的别名会转小写,Map 返回必须用双引号保留驼峰,否则前端取不到字段 -->
     <select id="selectMonthTotalList" parameterType="java.util.Map" resultType="java.util.Map">
-        select c.hidd_clas as repType,
-               coalesce(sum(case when (d.guid is not null and (d.requ_comp_date is null or (d.requ_comp_date is not null and now() > d.requ_comp_date and e.accep_leg_pers is null))) then 1 else 0 end), 0) as overUnImplRect,
-               coalesce(sum(case when c.hidd_grad = '1' then 1 else 0 end), 0) as impHiddCount,
-               coalesce(sum(case when c.hidd_stat = '1' then 1 else 0 end), 0) as unImplRect,
-               coalesce(sum(case when c.hidd_stat = '2' then 1 else 0 end), 0) as implRect,
-               coalesce(sum(case when c.hidd_stat = '3' then 1 else 0 end), 0) as inRect,
-               coalesce(sum(case when c.hidd_stat = '4' then 1 else 0 end), 0) as compRect
+        select c.hidd_clas as "repType",
+               coalesce(sum(case when (d.guid is not null and (d.requ_comp_date is null or (d.requ_comp_date is not null and now() > d.requ_comp_date and e.accep_leg_pers is null))) then 1 else 0 end), 0) as "overUnImplRect",
+               coalesce(sum(case when c.hidd_grad = '1' then 1 else 0 end), 0) as "impHiddCount",
+               coalesce(sum(case when c.hidd_stat = '1' then 1 else 0 end), 0) as "unImplRect",
+               coalesce(sum(case when c.hidd_stat in ('2','3') then 1 else 0 end), 0) as "implRect",
+               coalesce(sum(case when c.hidd_stat = '3' then 1 else 0 end), 0) as "inRect"
         from bis_org_mon_rep_peri a
         left join bis_hidd_rec_rep b on b.rep_guid = a.guid
         left join obj_hidd c on c.guid = b.hidd_guid
@@ -93,23 +102,23 @@
     <select id="selectMonthReportStats" parameterType="String" resultType="java.util.Map">
         select 
             -- 重大隐患数
-            coalesce(sum(case when c.hidd_grad = '2' then 1 else 0 end), 0) as impHiddCount,
+            coalesce(sum(case when c.hidd_grad = '2' then 1 else 0 end), 0) as "impHiddCount",
             -- 一般隐患数
-            coalesce(sum(case when c.hidd_grad = '1' then 1 else 0 end), 0) as normalHiddCount,
+            coalesce(sum(case when c.hidd_grad = '1' then 1 else 0 end), 0) as "normalHiddCount",
             -- 未落实整改
-            coalesce(sum(case when c.hidd_stat = '0' then 1 else 0 end), 0) as unSolvedCount,
+            coalesce(sum(case when c.hidd_stat = '0' then 1 else 0 end), 0) as "unSolvedCount",
             -- 整改中
-            coalesce(sum(case when c.hidd_stat = '1' then 1 else 0 end), 0) as solvingCount,
-            -- 完成整改
-            coalesce(sum(case when c.hidd_stat = '2' then 1 else 0 end), 0) as hasSolvedCount,
+            coalesce(sum(case when c.hidd_stat = '1' then 1 else 0 end), 0) as "solvingCount",
+            -- 完成整改(含已销号)
+            coalesce(sum(case when c.hidd_stat in ('2','3') then 1 else 0 end), 0) as "hasSolvedCount",
             -- 逾期未整改(要求完成日期小于当前日期且未完成整改)
             coalesce(sum(case when d.requ_comp_date is not null 
                 and d.requ_comp_date &lt; CURRENT_DATE 
-                and c.hidd_stat != '2' then 1 else 0 end), 0) as overUnImplRect,
+                and c.hidd_stat not in ('2','3') then 1 else 0 end), 0) as "overUnImplRect",
             -- 整改率
             case when count(c.guid) > 0 
-                then round(sum(case when c.hidd_stat = '2' then 1 else 0 end) * 100.0 / count(c.guid), 2)
-                else 0 end as solveRate
+                then round(sum(case when c.hidd_stat in ('2','3') then 1 else 0 end) * 100.0 / count(c.guid), 2)
+                else 0 end as "solveRate"
         from bis_org_mon_rep_peri a
         left join bis_hidd_rec_rep b on b.rep_guid = a.guid
         left join obj_hidd c on c.guid = b.hidd_guid
@@ -120,34 +129,34 @@
     <!-- 月报列表统计(根据月份) -->
     <select id="selectMonthListStats" parameterType="java.util.Map" resultType="java.util.Map">
         select 
-            a.guid as guid,
-            a.rep_org_guid as repOrgGuid,
-            a.rep_name as repName,
-            a.rep_act as repAct,
-            a.rep_time as repTime,
-            a.rep_type as repType,
+            a.guid as "guid",
+            a.rep_org_guid as "repOrgGuid",
+            a.rep_name as "repName",
+            a.rep_act as "repAct",
+            a.rep_time as "repTime",
+            a.rep_type as "repType",
             -- 重大隐患数
-            coalesce(stats.imp_hidd_count, 0) as impHiddCount,
+            coalesce(stats.imp_hidd_count, 0) as "impHiddCount",
             -- 逾期未整改
-            coalesce(stats.over_un_impl_rect, 0) as overUnImplRect,
+            coalesce(stats.over_un_impl_rect, 0) as "overUnImplRect",
             -- 未落实整改
-            coalesce(stats.un_solved_count, 0) as unSolvedCount,
+            coalesce(stats.un_solved_count, 0) as "unSolvedCount",
             -- 整改中
-            coalesce(stats.solving_count, 0) as solvingCount,
+            coalesce(stats.solving_count, 0) as "solvingCount",
             -- 完成整改
-            coalesce(stats.has_solved_count, 0) as hasSolvedCount,
+            coalesce(stats.has_solved_count, 0) as "hasSolvedCount",
             -- 整改率
-            coalesce(stats.solve_rate, 0) as solveRate
+            coalesce(stats.solve_rate, 0) as "solveRate"
         from bis_org_mon_rep_peri a
         left join (
             select 
                 b.rep_guid,
                 sum(case when c.hidd_grad = '2' then 1 else 0 end) as imp_hidd_count,
-                sum(case when d.requ_comp_date is not null and d.requ_comp_date &lt; CURRENT_DATE and c.hidd_stat != '2' then 1 else 0 end) as over_un_impl_rect,
+                sum(case when d.requ_comp_date is not null and d.requ_comp_date &lt; CURRENT_DATE and c.hidd_stat not in ('2','3') then 1 else 0 end) as over_un_impl_rect,
                 sum(case when c.hidd_stat = '0' then 1 else 0 end) as un_solved_count,
                 sum(case when c.hidd_stat = '1' then 1 else 0 end) as solving_count,
-                sum(case when c.hidd_stat = '2' then 1 else 0 end) as has_solved_count,
-                case when count(c.guid) > 0 then round(sum(case when c.hidd_stat = '2' then 1 else 0 end) * 100.0 / count(c.guid), 2) else 0 end as solve_rate
+                sum(case when c.hidd_stat in ('2','3') then 1 else 0 end) as has_solved_count,
+                case when count(c.guid) > 0 then round(sum(case when c.hidd_stat in ('2','3') then 1 else 0 end) * 100.0 / count(c.guid), 2) else 0 end as solve_rate
             from bis_hidd_rec_rep b
             left join obj_hidd c on c.guid = b.hidd_guid
             left join bis_hidd_rect_impl d on d.hidd_guid = b.hidd_guid

+ 1 - 1
gw-slaj/src/main/resources/mapper/slaj/hidd/BisOrgMonRepRevoMapper.xml

@@ -57,7 +57,7 @@
     </select>
     <insert id="insertBisOrgMonRepRevo" parameterType="com.goldenwater.slaj.hidd.domain.BisOrgMonRepRevo">
         insert into bis_org_mon_rep_revo (guid, rep_guid, revo_org_guid, veri_org_guid, revo_reas, rep_resc, return_desc, revo_veri_opin, revo_veri_resu, note, coll_time, upd_time, rec_pers)
-        values (#{guid}, #{repGuid}, #{revoOrgGuid}, #{veriOrgGuid}, #{revoReas}, #{repResc}, #{returnDesc}, #{revoVeriOpin}, #{revoVeriResu}, #{note}, #{collTime}, #{updTime}, #{recPers}, )
+        values (#{guid}, #{repGuid}, #{revoOrgGuid}, #{veriOrgGuid}, #{revoReas}, #{repResc}, #{returnDesc}, #{revoVeriOpin}, #{revoVeriResu}, #{note}, #{collTime}, #{updTime}, #{recPers})
     </insert>
     <update id="updateBisOrgMonRepRevo" parameterType="com.goldenwater.slaj.hidd.domain.BisOrgMonRepRevo">
         update bis_org_mon_rep_revo

+ 21 - 10
gw-slaj/src/main/resources/mapper/slaj/hidd/ObjHiddMapper.xml

@@ -39,6 +39,8 @@
         <result property="requCompDate" column="requ_comp_date"/>
         <result property="supStat" column="sup_stat"/>
         <result property="cancelState" column="cancel_state"/>
+        <result property="repAct" column="rep_act"/>
+        <result property="returnDesc" column="return_desc"/>
     </resultMap>
     <sql id="selectObjHiddVo">
         select h.guid, h.hidd_name, h.eng_guid, h.tend_guid, h.se_guid, h.org_guid, h.hidd_sour, h.hidd_grad, h.hidd_clas, h.if_found, h.pro_part, h.part_long, h.part_lat, h.otlcol_qiff_fnvu, h.insp_rec_guid, h.se_check_item_guid, h.hidd_stat, h.hidd_merg_guid, h.rec_org_guid, h.note, h.coll_time, h.upd_time, h.rec_pers, h.hidds_guid, h.occu_num, h.sins_sche_guid, h.group_guid, h.temp, h.to_date, h.dict_guid,
@@ -48,15 +50,23 @@
                ri.requ_comp_date,
                t.tend_name,
                COALESCE(CASE WHEN ms.hidd_guid IS NOT NULL THEN '1' ELSE '0' END, '0') as sup_stat,
-               COALESCE(ra.cancel_state, '0') as cancel_state
+               COALESCE(ra.cancel_state, '0') as cancel_state,
+               rr.rep_act,
+               rr.return_desc
         from obj_hidd h
-        left join att_eng_base e on h.eng_guid = e.guid
+        left join obj_eng e on h.eng_guid = e.guid
         left join att_org_base o on h.org_guid = o.guid
         left join bis_hidd_inve bi on h.insp_rec_guid = bi.guid
         left join bis_hidd_rect_impl ri on h.guid = ri.hidd_guid
         left join bis_hidd_rect_acce ra on h.guid = ra.hidd_guid
         left join bis_maj_hidd_sup ms on h.guid = ms.hidd_guid
         left join obj_tend t on h.tend_guid = t.guid
+        -- 最新一条上报记录(上报/退回状态与原因)
+        left join (
+            select distinct on (rrx.hidd_guid) rrx.hidd_guid, rrx.rep_act, rrx.return_desc
+            from bis_hidd_rec_rep rrx
+            order by rrx.hidd_guid, rrx.coll_time desc
+        ) rr on rr.hidd_guid = h.guid
     </sql>
     <select id="selectObjHiddByGuid" parameterType="String" resultMap="ObjHiddResult">
         <include refid="selectObjHiddVo"/>
@@ -156,23 +166,24 @@
     </insert>
 
     <!-- 工程/非工程隐患聚合查询 -->
+    <!-- 注意: PG 未加引号的别名会转小写,必须用双引号保留驼峰,否则前端取不到字段 -->
     <select id="selectHiddGroupBy" parameterType="java.util.Map" resultType="java.util.LinkedHashMap">
         SELECT
-            e.eng_name AS engName,
-            org.org_name AS orgName,
-            count(h.guid) AS totalCount,
-            coalesce(sum(case when h.hidd_grad = '1' then 1 else 0 end), 0) AS normalCount,
-            coalesce(sum(case when h.hidd_grad = '2' then 1 else 0 end), 0) AS majorCount,
-            coalesce(sum(case when h.hidd_stat = '2' then 1 else 0 end), 0) AS solvedCount
+            e.eng_name AS "engName",
+            org.org_name AS "orgName",
+            count(h.guid) AS "totalCount",
+            coalesce(sum(case when h.hidd_grad = '1' then 1 else 0 end), 0) AS "normalCount",
+            coalesce(sum(case when h.hidd_grad = '2' then 1 else 0 end), 0) AS "majorCount",
+            coalesce(sum(case when h.hidd_stat = '2' then 1 else 0 end), 0) AS "solvedCount"
         FROM obj_hidd h
         LEFT JOIN obj_eng e ON h.eng_guid = e.guid
         LEFT JOIN att_org_base org ON h.org_guid = org.guid
         <where>
             <if test="engName != null and engName != ''">AND e.eng_name LIKE '%' || #{engName} || '%'</if>
             <if test="orgName != null and orgName != ''">AND org.org_name LIKE '%' || #{orgName} || '%'</if>
-            <if test="collTime != null and collTime != ''">AND h.coll_time LIKE #{collTime} || '%'</if>
+            <if test="collTime != null and collTime != ''">AND h.coll_time >= CAST(#{collTime} AS timestamp) AND h.coll_time &lt; CAST(#{collTime} AS timestamp) + INTERVAL '1 day'</if>
         </where>
         GROUP BY e.eng_name, org.org_name
-        ORDER BY totalCount DESC
+        ORDER BY "totalCount" DESC
     </select>
 </mapper>

+ 9 - 0
gw-slaj/src/main/resources/mapper/slaj/hidd/RelBisMedMapper.xml

@@ -30,6 +30,15 @@
         <include refid="selectRelBisMedVo"/>
         where bis_tablename = #{bisTablename} and bis_guid = #{bisGuid}
     </select>
+    <!-- 查询业务关联的多媒体附件(含名称/路径,用于前端编辑回显) -->
+    <select id="selectMedListByBisInfo" parameterType="java.util.Map" resultType="java.util.LinkedHashMap">
+        select m.med_name as "name",
+               m.med_path as "path",
+               m.guid as "medGuid"
+        from rel_bis_med r
+        left join att_med_base m on m.guid = r.med_guid
+        where r.bis_tablename = #{bisTablename} and r.bis_guid = #{bisGuid}
+    </select>
     <insert id="insertRelBisMed" parameterType="com.goldenwater.slaj.hidd.domain.RelBisMed">
         insert into rel_bis_med (guid, bis_guid, bis_tablename, med_guid, bis_rel_columns, from_date, to_date)
         values (#{guid}, #{bisGuid}, #{bisTablename}, #{medGuid}, #{bisRelColumns}, #{fromDate}, #{toDate})

+ 92 - 8
gw-slaj/src/main/resources/mapper/slaj/hidd/TBusiHiddCountMapper.xml

@@ -102,11 +102,12 @@
         </foreach>
     </delete>
 
+    <!-- 注意: PG 未加引号的别名会转小写,Map 返回必须用双引号保留驼峰,否则前端取不到字段 -->
     <select id="selectReportRateChart" parameterType="java.util.Map" resultType="java.util.LinkedHashMap">
-        select c.org_guid as orgGuid,
-               org.wiun_name as orgName,
-               c.pcl as rateData,
-               c.create_time as repTime
+        select c.org_guid as "orgGuid",
+               org.wiun_name as "orgName",
+               c.pcl as "rateData",
+               c.create_time as "repTime"
         from t_busi_hidd_count c
         left join att_org_ext org on org.org_guid = c.org_guid
         <where>
@@ -116,10 +117,10 @@
     </select>
 
     <select id="selectRectifyRateChart" parameterType="java.util.Map" resultType="java.util.LinkedHashMap">
-        select c.org_guid as orgGuid,
-               org.wiun_name as orgName,
-               c.hidd_zgl as rateData,
-               c.create_time as repTime
+        select c.org_guid as "orgGuid",
+               org.wiun_name as "orgName",
+               c.hidd_zgl as "rateData",
+               c.create_time as "repTime"
         from t_busi_hidd_count c
         left join att_org_ext org on org.org_guid = c.org_guid
         <where>
@@ -198,6 +199,89 @@
         order by c.create_time desc
     </select>
 
+    <!-- 隐患统计列表查询(实时聚合,不依赖 t_busi_hidd_count 表)
+         口径:按单位实时统计名下隐患,与旧版 selectHiddCount 一致 -->
+    <select id="selectTBusiHiddCountRealtimeList" parameterType="com.goldenwater.slaj.hidd.domain.TBusiHiddCountVo" resultMap="TBusiHiddCountVoResult">
+        select
+            o.guid as org_guid,
+            o.org_name as org_name,
+            -- 排查情况:非工程单位(下级单位中无工程关联的)
+            coalesce(stat.oeng_org, 0) as oeng_org,
+            -- 已排查非工程单位(有隐患记录的下级单位)
+            coalesce(stat.hidd_org, 0) as hidd_org,
+            -- 工程总数(该单位名下的工程)
+            coalesce(stat.eng_num, 0) as eng_num,
+            -- 有隐患的工程数
+            coalesce(stat.hidd_eng, 0) as hidd_eng,
+            -- 排查率 = 已排查单位/单位总数
+            case when coalesce(stat.total_org, 0) > 0
+                 then round(coalesce(stat.hidd_org, 0) * 100.0 / stat.total_org, 2)
+                 else 0 end as pcl,
+            -- 综合整改率
+            case when coalesce(stat.total_hidd, 0) > 0
+                 then round(coalesce(stat.solved_hidd, 0) * 100.0 / stat.total_hidd, 2)
+                 else 0 end as hidd_zgl,
+            -- 一般隐患数
+            coalesce(stat.yb_hidd, 0) as yb_hidd,
+            -- 已整改一般隐患数
+            coalesce(stat.zg_yb_hidd, 0) as zg_yb_hidd,
+            -- 一般整改率
+            case when coalesce(stat.yb_hidd, 0) > 0
+                 then round(coalesce(stat.zg_yb_hidd, 0) * 100.0 / stat.yb_hidd, 2)
+                 else 0 end as yb_zgl,
+            -- 重大隐患数
+            coalesce(stat.zd_hidd, 0) as zd_hidd,
+            -- 已整改重大隐患数
+            coalesce(stat.zg_zd_hidd, 0) as zg_zd_hidd,
+            -- 重大整改率
+            case when coalesce(stat.zd_hidd, 0) > 0
+                 then round(coalesce(stat.zg_zd_hidd, 0) * 100.0 / stat.zd_hidd, 2)
+                 else 0 end as zd_zgl
+        from att_org_base o
+        left join (
+            select
+                u.guid as org_guid,
+                -- 下级单位总数(非工程单位 = 无工程关联的下级单位)
+                count(distinct case when e.guid is null then sub.guid end) as total_org,
+                -- 非工程单位总数
+                count(distinct case when e.guid is null then sub.guid end) as oeng_org,
+                -- 有隐患记录的下级单位(已排查)
+                count(distinct case when e.guid is null and h.guid is not null then sub.guid end) as hidd_org,
+                -- 该单位名下工程总数
+                count(distinct e.guid) as eng_num,
+                -- 有隐患的工程数
+                count(distinct case when eh.guid is not null then e.guid end) as hidd_eng,
+                -- 隐患统计(该单位名下)
+                count(distinct h.guid) as total_hidd,
+                count(distinct case when h.hidd_grad = '1' then h.guid end) as yb_hidd,
+                count(distinct case when h.hidd_grad = '1' and h.hidd_stat in ('2','3') then h.guid end) as zg_yb_hidd,
+                count(distinct case when h.hidd_grad = '2' then h.guid end) as zd_hidd,
+                count(distinct case when h.hidd_grad = '2' and h.hidd_stat in ('2','3') then h.guid end) as zg_zd_hidd,
+                count(distinct case when h.hidd_stat in ('2','3') then h.guid end) as solved_hidd
+            from att_org_base u
+            left join att_org_base sub on sub.pguid = u.guid
+            left join att_eng_base e on e.org_guid = sub.guid
+            left join obj_hidd h on h.org_guid = sub.guid
+            left join obj_hidd eh on eh.eng_guid = e.guid
+            group by u.guid
+        ) stat on stat.org_guid = o.guid
+        <where>
+            <if test="orgName != null and orgName != ''">AND o.org_name like concat('%', #{orgName}, '%')</if>
+            <if test="unitType != null and unitType != ''">
+                AND o.guid in (
+                    select org_guid from att_org_ext where wiun_code like concat(
+                        case #{unitType}
+                            when '1' then '%000000'
+                            when '2' then '%000'
+                            when '3' then '%0000'
+                        end
+                    )
+                )
+            </if>
+        </where>
+        order by o.org_name
+    </select>
+
     <!-- 月度统计列表查询 -->
     <select id="selectTBusiHiddCountMonListWithCalc" parameterType="com.goldenwater.slaj.hidd.domain.TBusiHiddCountMonVo" resultType="com.goldenwater.slaj.hidd.domain.TBusiHiddCountMon">
         select 

+ 8 - 0
gw-ui/src/api/slaj/hidd.js

@@ -17,6 +17,14 @@ export function getObjHidd(guid) {
   })
 }
 
+// 查询隐患关联附件(编辑回显)
+export function getObjHiddMedList(guid) {
+  return request({
+    url: '/hidd/objhidd/medList/' + guid,
+    method: 'get'
+  })
+}
+
 // 工程/非工程隐患聚合查询
 export function getHiddGroupBy(query) {
   return request({

+ 2 - 1
gw-ui/src/views/slaj/hidd/month.vue

@@ -425,7 +425,8 @@ function submitReturn() {
 
 function handlePendingApproval() {
   revokeApproveList().then(res => {
-    pendingList.value = res.rows || res.data || []
+    // 只展示待审批记录(revo_veri_resu='0')
+    pendingList.value = (res.rows || res.data || []).filter(r => r.revoVeriResu === '0' || r.revoVeriResu === undefined || r.revoVeriResu === null)
     pendingOpen.value = true
   }).catch(() => {
     pendingList.value = []

+ 2 - 2
gw-ui/src/views/slaj/hidd/monthDetail.vue

@@ -86,7 +86,7 @@
           <el-table-column label="整改状态" align="center" width="100">
             <template #default="scope">
               <el-link type="primary" @click="handleRectClick(scope.row)">
-                {{ scope.row.hiddStat === '0' ? '未落实整改' : scope.row.hiddStat === '1' ? '正在整改' : scope.row.hiddStat === '2' ? '完成整改' : '--' }}
+                {{ scope.row.hiddStat === '0' ? '未落实整改' : scope.row.hiddStat === '1' ? '正在整改' : scope.row.hiddStat === '2' ? '完成整改' : scope.row.hiddStat === '3' ? '已销号' : '--' }}
               </el-link>
             </template>
           </el-table-column>
@@ -172,7 +172,7 @@
       <el-descriptions :column="2" border v-if="rectImplRow">
         <el-descriptions-item label="隐患名称" :span="2">{{ rectImplRow.hiddName }}</el-descriptions-item>
         <el-descriptions-item label="整改状态">
-          {{ rectImplRow.hiddStat === '0' ? '未落实整改' : rectImplRow.hiddStat === '1' ? '正在整改' : rectImplRow.hiddStat === '2' ? '完成整改' : '--' }}
+          {{ rectImplRow.hiddStat === '0' ? '未落实整改' : rectImplRow.hiddStat === '1' ? '正在整改' : rectImplRow.hiddStat === '2' ? '完成整改' : rectImplRow.hiddStat === '3' ? '已销号' : '--' }}
         </el-descriptions-item>
         <el-descriptions-item label="整改负责人">{{ rectImplRow.rectPers }}</el-descriptions-item>
         <el-descriptions-item label="要求整改完成日期">{{ rectImplRow.requCompDate }}</el-descriptions-item>

+ 36 - 17
gw-ui/src/views/slaj/hidd/orgEngQuery.vue

@@ -148,6 +148,15 @@
                 <dict-tag :options="hidd_stat" :value="scope.row.hiddStat" />
               </template>
             </el-table-column>
+            <el-table-column label="上报状态" align="center" width="100">
+              <template #default="scope">
+                <el-tooltip v-if="scope.row.repAct === '2'" :content="scope.row.returnDesc || ''" placement="top">
+                  <el-tag type="danger" size="small">已退回</el-tag>
+                </el-tooltip>
+                <el-tag v-else-if="scope.row.repAct === '1'" type="success" size="small">已上报</el-tag>
+                <el-tag v-else type="info" size="small">未上报</el-tag>
+              </template>
+            </el-table-column>
           </el-table>
            <div class="pagination">
             <el-pagination v-model:current-page="queryParams2.pageNum" v-model:page-size="queryParams2.pageSize" :total="total2" :page-sizes="[10, 20, 50, 100]" layout="total, sizes, prev, pager, next, jumper" @size-change="getList2" @current-change="getList2" />
@@ -734,7 +743,8 @@
 </template>
 
 <script setup name="OrgEngQuery">
-import { listObjHidd, delObjHidd, addObjHidd, updateObjHidd, compoundSaveHidd, getHiddGroupBy, listBisHiddRectImpl, addBisHiddRectImpl, updateBisHiddRectImpl, listBisHiddRectAcce, addBisHiddRectAcce, updateBisHiddRectAcce, listBisHiddRectProg, addBisHiddRectProg, listAttEngBase, listNextDepHidd, writeOffBisMajHiddSup, getHiddListByName, listAttOrgBase, applyWriteOffBisMajHiddSup, approveWriteOffBisMajHiddSup, reportHidd, returnHidd, addBisMajHiddSup } from "@/api/slaj/hidd"
+import { listObjHidd, delObjHidd, addObjHidd, updateObjHidd, compoundSaveHidd, getHiddGroupBy, getObjHiddMedList, listBisHiddRectImpl, addBisHiddRectImpl, updateBisHiddRectImpl, listBisHiddRectAcce, addBisHiddRectAcce, updateBisHiddRectAcce, listBisHiddRectProg, addBisHiddRectProg, listNextDepHidd, writeOffBisMajHiddSup, getHiddListByName, listAttOrgBase, applyWriteOffBisMajHiddSup, approveWriteOffBisMajHiddSup, reportHidd, returnHidd, addBisMajHiddSup } from "@/api/slaj/hidd"
+import { listObjEng } from "@/api/slaj/eng"
 import { getToken } from "@/utils/auth"
 import useUserStore from '@/store/modules/user'
 import { Search, Plus, Download, Delete, Upload, Edit, Position, Back } from '@element-plus/icons-vue'
@@ -832,7 +842,7 @@ function queryHiddName(queryString, cb) {
 function handleAdd() {
   formTitle.value = '本级单位工程隐患新增'
   form.value = { hiddGrad: '1', hiddStat: '0', inspDate: '', inspLeader: '', inspLeaderPost: '', proPart: '', hiddDesc: '', engGuid: '', tendGuid: '', engName: '', tendName: '', orgGuid: userStore.orgGuid || '' }
-  listAttEngBase({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
+  listObjEng({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
   fileAttachList.value = []
   uploadFileList.value = []
   formDrawer.value = true
@@ -844,10 +854,9 @@ function handleUpdate(row) {
   const data = list.value.find(d => d.guid === guid)
   if (data) {
     form.value = { ...data, engGuid: data.engGuid || '', tendGuid: data.tendGuid || '' }
-    listAttEngBase({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
+    listObjEng({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
     formTitle.value = '本级单位工程隐患修改'
-    fileAttachList.value = []
-    uploadFileList.value = []
+    loadHiddMedList(data.guid)
     formDrawer.value = true
   }
 }
@@ -864,6 +873,19 @@ function handleUploadRemove(file, fileList) {
   uploadFileList.value = fileList
 }
 
+// 编辑时回填已有附件,避免保存时旧附件被清空
+function loadHiddMedList(guid) {
+  if (!guid) { fileAttachList.value = []; uploadFileList.value = []; return }
+  getObjHiddMedList(guid).then(res => {
+    const list = res.data || []
+    fileAttachList.value = list.map(m => ({ name: m.name, path: m.path, medGuid: m.medGuid }))
+    uploadFileList.value = list.map(m => ({ name: m.name, url: m.path }))
+  }).catch(() => {
+    fileAttachList.value = []
+    uploadFileList.value = []
+  })
+}
+
 function submitFormDrawer() {
   if (!form.value.hiddName) { proxy.$modal.msgWarning('请输入隐患名称'); return }
   formLoading.value = true
@@ -1028,7 +1050,7 @@ function getList4() {
 function handleAdd4() {
   formTitle.value = '施工单位隐患新增'
   form.value = { hiddGrad: '1', hiddStat: '0', hiddSour: '1', inspDate: '', inspLeader: '', inspLeaderPost: '', proPart: '', hiddDesc: '', engGuid: '', tendGuid: '', engName: '', tendName: '', orgName: '', orgGuid: userStore.orgGuid || '' }
-  listAttEngBase({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
+  listObjEng({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
   listAttOrgBase({ orgNature: '7' }).then(res => {
     consOrgList.value = (res.rows || []).map(o => ({ value: o.guid, label: o.orgName }))
   })
@@ -1040,10 +1062,9 @@ function handleUpdate4(row) {
   const data = row || (ids4.value.length ? list4.value.find(d => d.guid === ids4.value[0]) : null)
   if (!data) { proxy.$modal.msgWarning('请先选择一条数据'); return }
   form.value = { ...data, engGuid: data.engGuid || '', tendGuid: data.tendGuid || '' }
-  listAttEngBase({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
+  listObjEng({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
   formTitle.value = '施工单位隐患修改'
-  fileAttachList.value = []
-  uploadFileList.value = []
+  loadHiddMedList(data.guid)
   formDrawer.value = true
 }
 function handleDelete4(row) {
@@ -1086,7 +1107,7 @@ function getList5() {
 function handleAdd5() {
   formTitle.value = '参建单位隐患新增'
   form.value = { hiddGrad: '1', hiddStat: '0', inspDate: '', inspLeader: '', inspLeaderPost: '', proPart: '', hiddDesc: '', engGuid: '', tendGuid: '', engName: '', tendName: '', orgGuid: userStore.orgGuid || '' }
-  listAttEngBase({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
+  listObjEng({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
   fileAttachList.value = []
   uploadFileList.value = []
   formDrawer.value = true
@@ -1095,10 +1116,9 @@ function handleUpdate5(row) {
   const data = row || (ids5.value.length ? list5.value.find(d => d.guid === ids5.value[0]) : null)
   if (!data) { proxy.$modal.msgWarning('请先选择一条数据'); return }
   form.value = { ...data, engGuid: data.engGuid || '', tendGuid: data.tendGuid || '' }
-  listAttEngBase({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
+  listObjEng({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
   formTitle.value = '参建单位隐患修改'
-  fileAttachList.value = []
-  uploadFileList.value = []
+  loadHiddMedList(data.guid)
   formDrawer.value = true
 }
 function handleDelete5(row) {
@@ -1120,7 +1140,7 @@ function handleSelectionChange3(selection) { ids3.value = selection.map(item =>
 function handleAdd3() {
   formTitle.value = '本级单位标段隐患新增'
   form.value = { hiddGrad: '1', hiddStat: '0', inspDate: '', inspLeader: '', inspLeaderPost: '', proPart: '', hiddDesc: '', engGuid: '', tendGuid: '', engName: '', tendName: '', orgGuid: userStore.orgGuid || '' }
-  listAttEngBase({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
+  listObjEng({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
   fileAttachList.value = []
   uploadFileList.value = []
   formDrawer.value = true
@@ -1131,10 +1151,9 @@ function handleUpdate3(row) {
   const data = list3.value.find(d => d.guid === guid)
   if (data) {
     form.value = { ...data, engGuid: data.engGuid || '', tendGuid: data.tendGuid || '' }
-    listAttEngBase({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
+    listObjEng({}).then(res => { engList.value = (res.rows || []).map(e => ({ value: e.guid, label: e.engName })) })
     formTitle.value = '本级单位标段隐患修改'
-    fileAttachList.value = []
-    uploadFileList.value = []
+    loadHiddMedList(data.guid)
     formDrawer.value = true
   }
 }

+ 9 - 8
gw-ui/src/views/slaj/hidd/supList.vue

@@ -71,9 +71,12 @@
             {{ formatDate(scope.row.collTime) }}
           </template>
         </el-table-column>
+        <!-- TODO: supStatValue 由后端 SQL 根据 bis_hidd_rect_acce.cancel_state 派生,直接返回中文 -->
+        <!-- 业务逻辑: null/'0'=未销号→已督办  '1'=待销号审批→待销号  '2'=销号审批通过→已销号 -->
+        <!-- 注意: 如需国际化需改为编码+字典,前后端同步修改 -->
         <el-table-column label="督办情况" align="center" prop="supStatValue" v-if="columns.supStat.visible" min-width="80">
           <template #default="scope">
-            <dict-tag :options="sup_stat" :value="supStatMap[scope.row.supStatValue] || scope.row.supStatValue" />
+            {{ scope.row.supStatValue }}
           </template>
         </el-table-column>
         <el-table-column label="整改情况" align="center" prop="hiddStat" v-if="columns.hiddStat.visible" min-width="80">
@@ -83,8 +86,8 @@
         </el-table-column>
         <el-table-column label="操作" align="center" class-name="small-padding fixed-width" min-width="150">
           <template #default="scope">
-            <el-button link type="primary" v-if="supStatMap[scope.row.supStatValue] === '0' && scope.row.hiddStat !== '2'" @click="handleSup(scope.row)" v-hasPermi="['hidd:majhiddsup:add']">督办</el-button>
-            <el-button link type="primary" v-if="supStatMap[scope.row.supStatValue] === '2'" @click="handleWriteOff(scope.row)" v-hasPermi="['hidd:majhiddsup:edit']">销号</el-button>
+            <el-button link type="primary" v-if="scope.row.supStatValue === '已督办' && scope.row.hiddStat !== '2'" @click="handleSup(scope.row)" v-hasPermi="['hidd:majhiddsup:add']">督办</el-button>
+            <el-button link type="primary" v-if="scope.row.supStatValue === '待销号'" @click="handleWriteOff(scope.row)" v-hasPermi="['hidd:majhiddsup:edit']">销号</el-button>
             <el-button link type="primary" @click="handleDetail(scope.row)">详情</el-button>
           </template>
         </el-table-column>
@@ -305,11 +308,9 @@ const supRules = {
   rectPeri: [{ required: true, message: "请选择督办期限", trigger: "change" }]
 }
 
-const supStatMap = {
-  '已督办': '0',
-  '待销号': '2',
-  '已销号': '3'
-}
+// TODO: supStatValue 由后端 SQL 根据 bis_hidd_rect_acce.cancel_state 派生并直接返回中文
+// 业务逻辑: null/'0'=未销号→已督办  '1'=待销号审批→待销号  '2'=销号审批通过→已销号
+// 注意: 如需国际化需改为编码+字典,前后端同步修改
 
 const writeOffOpen = ref(false)
 const writeOffRow = ref({})