Browse Source

隐患相关修改

77681 2 tuần trước cách đây
mục cha
commit
ebe401f405
34 tập tin đã thay đổi với 1068 bổ sung615 xóa
  1. 6 3
      gw-common/src/main/java/com/goldenwater/common/utils/PageUtils.java
  2. 17 0
      gw-slaj/src/main/java/com/goldenwater/slaj/acci/controller/ObjAcciController.java
  3. 2 0
      gw-slaj/src/main/java/com/goldenwater/slaj/acci/domain/ObjAcciVo.java
  4. 7 0
      gw-slaj/src/main/java/com/goldenwater/slaj/acci/mapper/ObjAcciMapper.java
  5. 7 0
      gw-slaj/src/main/java/com/goldenwater/slaj/acci/service/IObjAcciService.java
  6. 5 0
      gw-slaj/src/main/java/com/goldenwater/slaj/acci/service/impl/ObjAcciServiceImpl.java
  7. 97 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/BisMajHiddSupController.java
  8. 73 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/ObjHiddController.java
  9. 2 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/domain/AttOrgBase.java
  10. 28 0
      gw-slaj/src/main/java/com/goldenwater/slaj/hidd/domain/HiddGroupByExportVo.java
  11. 30 1
      gw-slaj/src/main/resources/mapper/slaj/acci/ObjAcciMapper.xml
  12. 7 4
      gw-slaj/src/main/resources/mapper/slaj/hidd/AttOrgBaseMapper.xml
  13. 2 2
      gw-slaj/src/main/resources/mapper/slaj/hidd/ObjHiddMapper.xml
  14. 2 2
      gw-slaj/src/main/resources/mapper/slaj/hidd/TBusiHiddCountMapper.xml
  15. 8 8
      gw-system/src/main/resources/mapper/system/SysMenuMapper.xml
  16. 5 5
      gw-system/src/main/resources/mapper/system/SysRoleMapper.xml
  17. 12 12
      gw-system/src/main/resources/mapper/system/SysUserMapper.xml
  18. 3 0
      gw-ui/src/api/slaj/acci.js
  19. 36 0
      gw-ui/src/api/slaj/hidd.js
  20. 196 0
      gw-ui/src/views/slaj/acci/fastQuery.vue
  21. 53 270
      gw-ui/src/views/slaj/acci/index.vue
  22. 67 29
      gw-ui/src/views/slaj/acci/manage.vue
  23. 8 8
      gw-ui/src/views/slaj/acci/month.vue
  24. 65 154
      gw-ui/src/views/slaj/acci/stat.vue
  25. 4 4
      gw-ui/src/views/slaj/hazard/engQuery.vue
  26. 33 22
      gw-ui/src/views/slaj/hazard/manage.vue
  27. 1 1
      gw-ui/src/views/slaj/hazard/patrol.vue
  28. 7 2
      gw-ui/src/views/slaj/hazard/supervise.vue
  29. 3 3
      gw-ui/src/views/slaj/hidd/engQuery.vue
  30. 12 12
      gw-ui/src/views/slaj/hidd/month.vue
  31. 1 1
      gw-ui/src/views/slaj/hidd/monthDetail.vue
  32. 254 63
      gw-ui/src/views/slaj/hidd/orgEngQuery.vue
  33. 2 2
      gw-ui/src/views/slaj/hidd/stat.vue
  34. 13 7
      gw-ui/src/views/slaj/hidd/supList.vue

+ 6 - 3
gw-common/src/main/java/com/goldenwater/common/utils/PageUtils.java

@@ -20,9 +20,12 @@ public class PageUtils extends PageHelper
         PageDomain pageDomain = TableSupport.buildPageRequest();
         Integer pageNum = pageDomain.getPageNum();
         Integer pageSize = pageDomain.getPageSize();
-        String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
-        Boolean reasonable = pageDomain.getReasonable();
-        PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+        if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize))
+        {
+            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+            Boolean reasonable = pageDomain.getReasonable();
+            PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+        }
     }
 
     /**

+ 17 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/acci/controller/ObjAcciController.java

@@ -249,4 +249,21 @@ public class ObjAcciController extends BaseController {
         List<Map<String, Object>> list = objAcciService.selectGisData(params);
         return AjaxResult.success(list);
     }
+
+    /**
+     * 事故统计报表 — 按单位维度统计事故数量、伤亡人数、经济损失等指标。
+     * 支持按单位性质和时间范围筛选。
+     */
+    @GetMapping("/statList")
+    public TableDataInfo statList(@RequestParam(required = false) String orgNature,
+                                  @RequestParam(required = false) String beginTime,
+                                  @RequestParam(required = false) String endTime) {
+        startPage();
+        Map<String, Object> params = new java.util.HashMap<>();
+        params.put("orgNature", orgNature);
+        params.put("beginTime", beginTime);
+        params.put("endTime", endTime);
+        List<Map<String, Object>> list = objAcciService.selectAcciStatList(params);
+        return getDataTable(list);
+    }
 }

+ 2 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/acci/domain/ObjAcciVo.java

@@ -7,6 +7,8 @@ import lombok.EqualsAndHashCode;
 @Data
 @EqualsAndHashCode(callSuper = true)
 public class ObjAcciVo extends ObjAcci {
+    @Excel(name = "事故名称", width = 20)
+    private String acciName;
     @Excel(name = "工程名称", width = 20)
     private String engName;
     @Excel(name = "标段名称", width = 20)

+ 7 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/acci/mapper/ObjAcciMapper.java

@@ -81,4 +81,11 @@ public interface ObjAcciMapper {
      * @return 含经纬度的事故列表
      */
     List<Map<String, Object>> selectGisData(Map<String, Object> params);
+
+    /**
+     * 事故统计报表 — 按单位维度统计
+     * @param params 查询参数(orgNature, beginTime, endTime)
+     * @return 统计结果列表
+     */
+    List<Map<String, Object>> selectAcciStatList(Map<String, Object> params);
 }

+ 7 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/acci/service/IObjAcciService.java

@@ -81,4 +81,11 @@ public interface IObjAcciService {
      * @return 含经纬度的事故列表
      */
     List<Map<String, Object>> selectGisData(Map<String, Object> params);
+
+    /**
+     * 事故统计报表 — 按单位维度统计
+     * @param params 查询参数(orgNature, beginTime, endTime)
+     * @return 统计结果列表
+     */
+    List<Map<String, Object>> selectAcciStatList(Map<String, Object> params);
 }

+ 5 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/acci/service/impl/ObjAcciServiceImpl.java

@@ -108,6 +108,11 @@ public class ObjAcciServiceImpl implements IObjAcciService {
         return objAcciMapper.selectGisData(params);
     }
 
+    @Override
+    public List<Map<String, Object>> selectAcciStatList(Map<String, Object> params) {
+        return objAcciMapper.selectAcciStatList(params);
+    }
+
     @Override
     public int compoundSave(Map<String, Object> params) {
         ObjAcci acci = new ObjAcci();

+ 97 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/BisMajHiddSupController.java

@@ -37,6 +37,9 @@ public class BisMajHiddSupController extends BaseController {
     @Autowired
     private IRelBisMedService relBisMedService;
 
+    @Autowired
+    private com.goldenwater.slaj.hidd.service.IBisHiddRectAcceService bisHiddRectAcceService;
+
     @Autowired
     private AcciNotifyService acciNotifyService;
 
@@ -124,9 +127,103 @@ public class BisMajHiddSupController extends BaseController {
     @PreAuthorize("@ss.hasPermi('hidd:majhiddsup:edit')")
     @PutMapping("/writeOff")
     public AjaxResult writeOff(@RequestBody BisMajHiddSup bisMajHiddSup) {
+        if (bisMajHiddSup.getGuid() == null) {
+            return AjaxResult.error("参数错误:缺少督办记录ID");
+        }
+        BisMajHiddSup sup = bisMajHiddSupService.selectBisMajHiddSupByGuid(bisMajHiddSup.getGuid());
+        if (sup == null) {
+            return AjaxResult.error("督办记录不存在");
+        }
+        if (sup.getHiddGuid() != null) {
+            ObjHidd hidd = objHiddService.selectObjHiddByGuid(sup.getHiddGuid());
+            if (hidd != null && !"2".equals(hidd.getHiddStat())) {
+                return AjaxResult.error("隐患尚未完成整改,不能销号");
+            }
+        }
         return toAjax(bisMajHiddSupService.updateBisMajHiddSup(bisMajHiddSup));
     }
 
+    /**
+     * 隐患销号申请 - 本单位提交销号申请
+     * 设置 bis_hidd_rect_acce.cancel_state = '1'(待审批)
+     */
+    @Log(title = "隐患销号申请", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('hidd:objhidd:writeoff')")
+    @PutMapping("/applyWriteOff")
+    public AjaxResult applyWriteOff(@RequestBody BisMajHiddSup bisMajHiddSup) {
+        if (bisMajHiddSup.getGuid() == null) {
+            return AjaxResult.error("参数错误:缺少督办记录ID");
+        }
+        BisMajHiddSup sup = bisMajHiddSupService.selectBisMajHiddSupByGuid(bisMajHiddSup.getGuid());
+        if (sup == null) {
+            return AjaxResult.error("督办记录不存在");
+        }
+        if (sup.getHiddGuid() == null) {
+            return AjaxResult.error("隐患记录不存在");
+        }
+        ObjHidd hidd = objHiddService.selectObjHiddByGuid(sup.getHiddGuid());
+        if (hidd == null) {
+            return AjaxResult.error("隐患记录不存在");
+        }
+        if (!"2".equals(hidd.getHiddStat())) {
+            return AjaxResult.error("隐患尚未完成整改,不能申请销号");
+        }
+        com.goldenwater.slaj.hidd.domain.BisHiddRectAcce acce = new com.goldenwater.slaj.hidd.domain.BisHiddRectAcce();
+        acce.setHiddGuid(sup.getHiddGuid());
+        java.util.List<com.goldenwater.slaj.hidd.domain.BisHiddRectAcce> list = bisHiddRectAcceService.selectBisHiddRectAcceList(acce);
+        if (list != null && !list.isEmpty()) {
+            com.goldenwater.slaj.hidd.domain.BisHiddRectAcce existing = list.get(0);
+            existing.setCancelState("1");
+            existing.setUpdTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+            return toAjax(bisHiddRectAcceService.updateBisHiddRectAcce(existing));
+        } else {
+            acce.setGuid(UUID.randomUUID().toString().replace("-", ""));
+            acce.setCancelState("1");
+            acce.setCollTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+            acce.setUpdTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+            return toAjax(bisHiddRectAcceService.insertBisHiddRectAcce(acce));
+        }
+    }
+
+    /**
+     * 隐患销号审批 - 上级同意/驳回
+     * 同意:hidd_stat = '3'(已销号),cancel_state = '2'
+     * 驳回:cancel_state = '0'
+     */
+    @Log(title = "隐患销号审批", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('hidd:majhiddsup:edit')")
+    @PutMapping("/approveWriteOff")
+    public AjaxResult approveWriteOff(@RequestBody java.util.Map<String, Object> params) {
+        String hiddGuid = (String) params.get("hiddGuid");
+        Boolean approved = (Boolean) params.get("approved");
+        if (hiddGuid == null || approved == null) {
+            return AjaxResult.error("参数错误");
+        }
+        ObjHidd hidd = objHiddService.selectObjHiddByGuid(hiddGuid);
+        if (hidd == null) {
+            return AjaxResult.error("隐患记录不存在");
+        }
+        com.goldenwater.slaj.hidd.domain.BisHiddRectAcce acceQuery = new com.goldenwater.slaj.hidd.domain.BisHiddRectAcce();
+        acceQuery.setHiddGuid(hiddGuid);
+        java.util.List<com.goldenwater.slaj.hidd.domain.BisHiddRectAcce> list = bisHiddRectAcceService.selectBisHiddRectAcceList(acceQuery);
+        if (list == null || list.isEmpty()) {
+            return AjaxResult.error("未找到销号申请记录");
+        }
+        com.goldenwater.slaj.hidd.domain.BisHiddRectAcce acce = list.get(0);
+        if (approved) {
+            acce.setCancelState("2");
+            hidd.setHiddStat("3");
+        } else {
+            acce.setCancelState("0");
+        }
+        acce.setUpdTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+        int acceResult = bisHiddRectAcceService.updateBisHiddRectAcce(acce);
+        if (approved) {
+            objHiddService.updateObjHidd(hidd);
+        }
+        return toAjax(acceResult);
+    }
+
     @Log(title = "撤销隐患督办", businessType = BusinessType.DELETE)
     @PreAuthorize("@ss.hasPermi('hidd:majhiddsup:remove')")
     @DeleteMapping("/cancel/{guid}")

+ 73 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/controller/ObjHiddController.java

@@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.*;
 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.HiddGroupByExportVo;
 import com.goldenwater.slaj.hidd.domain.ObjHidd;
 import com.goldenwater.slaj.hidd.domain.ObjHiddVo;
 import com.goldenwater.slaj.hidd.service.IObjHiddService;
@@ -146,6 +147,33 @@ public class ObjHiddController extends BaseController {
         return getDataTable(list);
     }
 
+    @Log(title = "隐患查询导出", businessType = BusinessType.EXPORT)
+    @PostMapping("/groupBy/export")
+    public void groupByExport(HttpServletResponse response,
+                               @RequestParam(required = false) String hiddSort,
+                               @RequestParam(required = false) String engName,
+                               @RequestParam(required = false) String orgName,
+                               @RequestParam(required = false) String collTime) {
+        Map<String, Object> params = new java.util.HashMap<>();
+        params.put("hiddSort", hiddSort);
+        params.put("engName", engName);
+        params.put("orgName", orgName);
+        params.put("collTime", collTime);
+        List<Map<String, Object>> list = objHiddService.selectHiddGroupBy(params);
+        List<HiddGroupByExportVo> exportList = list.stream().map(m -> {
+            HiddGroupByExportVo vo = new HiddGroupByExportVo();
+            vo.setEngName((String) m.get("engName"));
+            vo.setOrgName((String) m.get("orgName"));
+            vo.setTotalCount(String.valueOf(m.getOrDefault("totalCount", "0")));
+            vo.setNormalCount(String.valueOf(m.getOrDefault("normalCount", "0")));
+            vo.setMajorCount(String.valueOf(m.getOrDefault("majorCount", "0")));
+            vo.setSolvedCount(String.valueOf(m.getOrDefault("solvedCount", "0")));
+            return vo;
+        }).collect(java.util.stream.Collectors.toList());
+        ExcelUtil<HiddGroupByExportVo> util = new ExcelUtil<>(HiddGroupByExportVo.class);
+        util.exportExcel(response, exportList, "隐患查询数据");
+    }
+
     /**
      * 复合保存隐患(obj_hidd + bis_hidd_inve)
      */
@@ -158,4 +186,49 @@ public class ObjHiddController extends BaseController {
             return AjaxResult.error("保存失败:" + e.getMessage());
         }
     }
+
+    /**
+     * 隐患上报(批量)
+     */
+    @Log(title = "隐患上报", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('hidd:objhidd:report')")
+    @PutMapping("/report")
+    public AjaxResult report(@RequestParam String guids) {
+        if (guids == null || guids.isEmpty()) {
+            return AjaxResult.error("请选择要上报的隐患");
+        }
+        String[] guidArr = guids.split(",");
+        int count = 0;
+        for (String guid : guidArr) {
+            ObjHidd hidd = objHiddService.selectObjHiddByGuid(guid);
+            if (hidd != null) {
+                hidd.setUpdTime(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));
+                count += objHiddService.updateObjHidd(hidd);
+            }
+        }
+        return toAjax(count);
+    }
+
+    /**
+     * 隐患退回(批量)
+     */
+    @Log(title = "隐患退回", businessType = BusinessType.UPDATE)
+    @PreAuthorize("@ss.hasPermi('hidd:objhidd:return')")
+    @PutMapping("/return")
+    public AjaxResult returnHidd(@RequestParam String guids, @RequestParam String returnDesc) {
+        if (guids == null || guids.isEmpty()) {
+            return AjaxResult.error("请选择要退回的隐患");
+        }
+        String[] guidArr = guids.split(",");
+        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.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date()));
+                count += objHiddService.updateObjHidd(hidd);
+            }
+        }
+        return toAjax(count);
+    }
 }

+ 2 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/domain/AttOrgBase.java

@@ -41,4 +41,6 @@ public class AttOrgBase {
     private String areaType;
     /** 节点代码 */
     private String nodeCode;
+    /** 单位性质(用于JOIN att_org_ext.wiun_prop查询,非持久化字段) */
+    private String wiunProp;
 }

+ 28 - 0
gw-slaj/src/main/java/com/goldenwater/slaj/hidd/domain/HiddGroupByExportVo.java

@@ -0,0 +1,28 @@
+package com.goldenwater.slaj.hidd.domain;
+
+import com.goldenwater.common.annotation.Excel;
+import lombok.Data;
+
+/**
+ * 工程/非工程隐患聚合导出VO
+ */
+@Data
+public class HiddGroupByExportVo {
+    @Excel(name = "工程名称", width = 25)
+    private String engName;
+
+    @Excel(name = "管理单位", width = 20)
+    private String orgName;
+
+    @Excel(name = "总数", width = 10)
+    private String totalCount;
+
+    @Excel(name = "一般隐患", width = 12)
+    private String normalCount;
+
+    @Excel(name = "重大隐患", width = 12)
+    private String majorCount;
+
+    @Excel(name = "已整改隐患", width = 14)
+    private String solvedCount;
+}

+ 30 - 1
gw-slaj/src/main/resources/mapper/slaj/acci/ObjAcciMapper.xml

@@ -27,6 +27,7 @@
         <result property="engGuid" column="eng_guid"/>
         <result property="toDate" column="to_date"/>
         <result property="tendGuid" column="tend_guid"/>
+        <result property="acciName" column="acci_name"/>
         <result property="engName" column="eng_name"/>
         <result property="tendName" column="tend_name"/>
         <result property="ifDuty" column="if_duty"/>
@@ -48,7 +49,16 @@
         where a.guid = #{guid}
     </select>
     <select id="selectObjAcciList" parameterType="com.goldenwater.slaj.acci.domain.ObjAcciVo" resultMap="ObjAcciResult">
-        <include refid="selectObjAcciVo"/>
+        select a.guid, a.p_guid, a.acci_wiun_guid, a.acci_wiun_type, a.acci_cate, a.occu_time,
+               a.occu_loc, a.miss_num, a.ser_inj_num, a.cas_num, a.econ_loss, a.otlcol_guui_vicm,
+               a.resc_trea_meas, a.conta_pers, a.offi_tel, a.rep_stat, a.note, a.coll_time,
+               a.upd_time, a.rec_pers, a.sgdw_name, a.acci_grad, a.eng_guid, a.to_date, a.tend_guid,
+               a.sgdw_name || '事故' as acci_name,
+               e.eng_name, t.tend_name, bi.if_resp_acci as if_duty, bi.if_pho_rep as if_phone
+        from obj_acci a
+        left join att_eng_base e on a.eng_guid = e.guid
+        left join obj_tend t on a.tend_guid = t.guid
+        left join bis_acci_inve bi on a.guid = bi.acci_guid
         <where>
             <if test="guid != null and guid != ''">AND a.guid = #{guid}</if>
             <if test="acciGrad != null and acciGrad != ''">AND a.acci_grad = #{acciGrad}</if>
@@ -165,4 +175,23 @@
         </where>
         order by a.occu_time desc
     </select>
+
+    <select id="selectAcciStatList" parameterType="java.util.Map" resultType="java.util.LinkedHashMap">
+        select sgdw_name as orgName,
+               count(1) as acciCount,
+               sum(cast(coalesce(cas_num, '0') as numeric)) as deathCount,
+               sum(cast(coalesce(ser_inj_num, '0') as numeric)) as injuryCount,
+               sum(cast(coalesce(econ_loss, '0') as numeric)) as econLoss,
+               round(cast(sum(cast(coalesce(cas_num, '0') as numeric)) / count(1) as numeric), 2) as avgDeath,
+               round(cast(sum(cast(coalesce(ser_inj_num, '0') as numeric)) / count(1) as numeric), 2) as avgInjury,
+               round(cast(sum(cast(coalesce(econ_loss, '0') as numeric)) / count(1) as numeric), 2) as avgEconLoss
+        from obj_acci
+        <where>
+            <if test="orgNature != null and orgNature != ''">AND acci_wiun_type = #{orgNature}</if>
+            <if test="beginTime != null and beginTime != ''">AND occu_time &gt;= #{beginTime}</if>
+            <if test="endTime != null and endTime != ''">AND occu_time &lt;= #{endTime}</if>
+        </where>
+        group by sgdw_name
+        order by acciCount desc
+    </select>
 </mapper>

+ 7 - 4
gw-slaj/src/main/resources/mapper/slaj/hidd/AttOrgBaseMapper.xml

@@ -30,11 +30,14 @@
         where guid = #{guid}
     </select>
     <select id="selectAttOrgBaseList" parameterType="com.goldenwater.slaj.hidd.domain.AttOrgBase" resultMap="AttOrgBaseResult">
-        <include refid="selectAttOrgBaseVo"/>
+        select b.guid, b.pguid, b.org_code, b.org_name, b.org_level, b.org_grad, b.org_type, b.ordernum,
+               b.ad_code, b.status, b.modifier, b.from_date, b.to_date, b.note, b.jurd, b.area_type, b.node_code
+        from att_org_base b
         <where>
-            <if test="orgName != null and orgName != ''">AND org_name like '%' || #{orgName} || '%'</if>
-            <if test="orgCode != null and orgCode != ''">AND org_code = #{orgCode}</if>
-            <if test="pguid != null and pguid != ''">AND pguid = #{pguid}</if>
+            <if test="orgName != null and orgName != ''">AND b.org_name like '%' || #{orgName} || '%'</if>
+            <if test="orgCode != null and orgCode != ''">AND b.org_code = #{orgCode}</if>
+            <if test="pguid != null and pguid != ''">AND b.pguid = #{pguid}</if>
+            <if test="wiunProp != null and wiunProp != ''">AND EXISTS (SELECT 1 FROM att_org_ext ext WHERE ext.org_guid = b.guid AND ext.wiun_prop = #{wiunProp})</if>
         </where>
     </select>
     <insert id="insertAttOrgBase" parameterType="com.goldenwater.slaj.hidd.domain.AttOrgBase">

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

@@ -148,12 +148,12 @@
     <select id="selectNextDepHiddList" parameterType="com.goldenwater.slaj.hidd.domain.ObjHidd" resultMap="ObjHiddResult">
         <include refid="selectObjHiddVo"/>
         <where>
-            <if test="orgGuid != null and orgGuid != ''">AND org_guid in (select guid from att_org_base where parent_org_guid = #{orgGuid})</if>
+            <if test="orgGuid != null and orgGuid != ''">AND h.org_guid in (select guid from att_org_base where pguid = #{orgGuid})</if>
             <if test="hiddName != null and hiddName != ''">AND hidd_name like concat('%', #{hiddName}, '%')</if>
             <if test="hiddGrad != null and hiddGrad != ''">AND hidd_grad = #{hiddGrad}</if>
             <if test="hiddStat != null and hiddStat != ''">AND hidd_stat = #{hiddStat}</if>
             <if test="hiddSort != null and hiddSort != ''">AND hidd_sort = #{hiddSort}</if>
-            <if test="wiunProp != null and wiunProp != ''">AND EXISTS (SELECT 1 FROM att_org_ext ext WHERE ext.org_guid = org_guid AND ext.wiun_prop = #{wiunProp})</if>
+            <if test="wiunProp != null and wiunProp != ''">AND EXISTS (SELECT 1 FROM att_org_ext ext WHERE ext.org_guid = h.org_guid AND ext.wiun_prop = #{wiunProp})</if>
         </where>
         order by coll_time desc
     </select>

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

@@ -188,8 +188,8 @@
                     select org_guid from att_org_ext where wiun_code like concat(
                         case #{unitType}
                             when '1' then '%000000'
-                            when '2' then '%0000'
-                            when '3' then '%000'
+                            when '2' then '%000'
+                            when '3' then '%0000'
                         end
                     )
                 )

+ 8 - 8
gw-system/src/main/resources/mapper/system/SysMenuMapper.xml

@@ -59,8 +59,8 @@
 		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.route_name, m.visible, m.status, coalesce(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
 		from sys_menu m
 		left join sys_role_menu rm on m.menu_id = rm.menu_id
-		left join sys_user_role ur on rm.role_id = ur.role_id
-		left join sys_role ro on ur.role_id = ro.role_id
+		left join sys_user_role ur on rm.role_id::text = ur.role_id::text
+		left join sys_role ro on ur.role_id::text = ro.role_id::text
 		where ur.user_id = #{params.userId}
 		<if test="menuName != null and menuName != ''">
             AND m.menu_name like '%' || #{menuName} || '%'
@@ -78,9 +78,9 @@
 		select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.route_name, m.visible, m.status, coalesce(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
 		from sys_menu m
 			 left join sys_role_menu rm on m.menu_id = rm.menu_id
-			 left join sys_user_role ur on rm.role_id = ur.role_id
-			 left join sys_role ro on ur.role_id = ro.role_id
-			 left join sys_user u on ur.user_id = u.user_id
+			 left join sys_user_role ur on rm.role_id::text = ur.role_id::text
+			 left join sys_role ro on ur.role_id::text = ro.role_id::text
+			 left join sys_user u on ur.user_id::text = u.user_id
 		where u.user_id = #{userId} and m.menu_type in ('M', 'C') and m.status = 0  AND ro.status = 0
 		order by m.parent_id, m.order_num
 	</select>
@@ -100,15 +100,15 @@
 		select distinct m.perms
 		from sys_menu m
 			 left join sys_role_menu rm on m.menu_id = rm.menu_id
-			 left join sys_user_role ur on rm.role_id = ur.role_id
+			 left join sys_user_role ur on rm.role_id::text = ur.role_id::text
 	</select>
 
 	<select id="selectMenuPermsByUserId" parameterType="String" resultType="String">
 		select distinct m.perms
 		from sys_menu m
 			 left join sys_role_menu rm on m.menu_id = rm.menu_id
-			 left join sys_user_role ur on rm.role_id = ur.role_id
-			 left join sys_role r on r.role_id = ur.role_id
+			 left join sys_user_role ur on rm.role_id::text = ur.role_id::text
+			 left join sys_role r on r.role_id::text = ur.role_id::text
 		where m.status = '0' and r.status = '0' and ur.user_id = #{userId}
 	</select>
 

+ 5 - 5
gw-system/src/main/resources/mapper/system/SysRoleMapper.xml

@@ -25,9 +25,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	    select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly,
             r.status, r.del_flag, r.create_time, r.remark 
         from sys_role r
-	        left join sys_user_role ur on ur.role_id = r.role_id
-	        left join sys_user u on u.user_id = ur.user_id
-	        left join sys_dept d on u.dept_id = d.dept_id
+	        left join sys_user_role ur on ur.role_id::text = r.role_id::text
+	        left join sys_user u on u.user_id::text = ur.user_id::text
+	        left join sys_dept d on u.dept_id::text = d.dept_id::text
     </sql>
     
     <select id="selectRoleList" parameterType="SysRole" resultMap="SysRoleResult">
@@ -68,8 +68,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	<select id="selectRoleListByUserId" parameterType="String" resultType="String">
 		select r.role_id
         from sys_role r
-	        left join sys_user_role ur on ur.role_id = r.role_id
-	        left join sys_user u on u.user_id = ur.user_id
+	        left join sys_user_role ur on ur.role_id::text = r.role_id::text
+	        left join sys_user u on u.user_id::text = ur.user_id::text
 	    where u.user_id = #{userId}
 	</select>
 	

+ 12 - 12
gw-system/src/main/resources/mapper/system/SysUserMapper.xml

@@ -52,9 +52,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
         r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
         from sys_user u
-		    left join sys_dept d on u.dept_id = d.dept_id
-		    left join sys_user_role ur on u.user_id = ur.user_id
-		    left join sys_role r on r.role_id = ur.role_id
+		    left join sys_dept d on u.dept_id::text = d.dept_id::text
+		    left join sys_user_role ur on u.user_id::text = ur.user_id::text
+		    left join sys_role r on r.role_id::text = ur.role_id::text
     </sql>
 
     <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
@@ -89,10 +89,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	<select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
 	    select distinct u.user_id, u.dept_id, u.user_name, u.real_name, u.email, u.phonenumber, u.status, u.create_time
 	    from sys_user u
-			 left join sys_dept d on u.dept_id = d.dept_id
-			 left join sys_user_role ur on u.user_id = ur.user_id
-			 left join sys_role r on r.role_id = ur.role_id
-	    where u.del_flag = '0' and r.role_id = #{roleId}
+			 left join sys_dept d on u.dept_id::text = d.dept_id::text
+			 left join sys_user_role ur on u.user_id::text = ur.user_id::text
+			 left join sys_role r on r.role_id::text = ur.role_id::text
+	    where u.del_flag = '0' and r.role_id::text = #{roleId}
 	    <if test="userName != null and userName != ''">
 			AND u.user_name like '%' || #{userName} || '%'
 		</if>
@@ -106,11 +106,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 	<select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult">
 	    select distinct u.user_id, u.dept_id, u.user_name, u.real_name, u.email, u.phonenumber, u.status, u.create_time
 	    from sys_user u
-			 left join sys_dept d on u.dept_id = d.dept_id
-			 left join sys_user_role ur on u.user_id = ur.user_id
-			 left join sys_role r on r.role_id = ur.role_id
-	    where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL)
-	    and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and ur.role_id = #{roleId})
+			 left join sys_dept d on u.dept_id::text = d.dept_id::text
+			 left join sys_user_role ur on u.user_id::text = ur.user_id::text
+			 left join sys_role r on r.role_id::text = ur.role_id::text
+	    where u.del_flag = '0' and (r.role_id::text != #{roleId} or r.role_id IS NULL)
+	    and u.user_id::text not in (select u.user_id::text from sys_user u inner join sys_user_role ur on u.user_id::text = ur.user_id::text and ur.role_id::text = #{roleId})
 	    <if test="userName != null and userName != ''">
 			AND u.user_name like '%' || #{userName} || '%'
 		</if>

+ 3 - 0
gw-ui/src/api/slaj/acci.js

@@ -146,3 +146,6 @@ export function mobileCancelBisAcciMont(data) { return request({ url: '/acci/bis
 
 // 查询撤销原因
 export function getAcciRevokReason(guid) { return request({ url: '/acci/bisaccimont/revokReason/' + guid, method: 'get' }) }
+
+// 事故统计报表
+export function listAcciStat(query) { return request({ url: '/acci/objacci/statList', method: 'get', params: query }) }

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

@@ -345,6 +345,24 @@ export function writeOffBisMajHiddSup(data) {
   })
 }
 
+// 隐患销号申请
+export function applyWriteOffBisMajHiddSup(data) {
+  return request({
+    url: '/hidd/majhiddsup/applyWriteOff',
+    method: 'put',
+    data: data
+  })
+}
+
+// 隐患销号审批
+export function approveWriteOffBisMajHiddSup(data) {
+  return request({
+    url: '/hidd/majhiddsup/approveWriteOff',
+    method: 'put',
+    data: data
+  })
+}
+
 // 撤销隐患督办
 export function cancelBisMajHiddSup(guid) {
   return request({
@@ -854,6 +872,24 @@ export function saveNextHidd(data) {
   })
 }
 
+// 隐患上报
+export function reportHidd(guids) {
+  return request({
+    url: '/hidd/objhidd/report',
+    method: 'put',
+    params: { guids: guids.join(',') }
+  })
+}
+
+// 隐患退回
+export function returnHidd(guids, returnDesc) {
+  return request({
+    url: '/hidd/objhidd/return',
+    method: 'put',
+    params: { guids: guids.join(','), returnDesc: returnDesc }
+  })
+}
+
 // 下级单位隐患列表
 export function listNextDepHidd(query) {
   return request({

+ 196 - 0
gw-ui/src/views/slaj/acci/fastQuery.vue

@@ -0,0 +1,196 @@
+<template>
+  <div ref="containerRef" class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="auto">
+      <el-form-item label="单位性质" prop="wiunProp">
+        <el-select v-model="queryParams.wiunProp" placeholder="请选择" clearable style="width: 130px">
+          <el-option label="直属单位" value="1" />
+          <el-option label="下级水行政" value="2" />
+          <el-option label="流域机构" value="3" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="事故类型" prop="acciCate">
+        <el-select v-model="queryParams.acciCate" placeholder="请选择" clearable style="width: 130px">
+          <el-option v-for="dict in acci_cate" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="事故等级" prop="acciGrad">
+        <el-select v-model="queryParams.acciGrad" placeholder="请选择" clearable style="width: 130px">
+          <el-option v-for="dict in acci_grad" :key="dict.value" :label="dict.label" :value="dict.value" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="单位名称" prop="sgdwName">
+        <el-input v-model="queryParams.sgdwName" placeholder="请输入" clearable style="width: 180px" @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="行政区域" prop="areaName">
+        <el-input v-model="queryParams.areaName" placeholder="请输入" clearable style="width: 150px" @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="事故时间">
+        <el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" style="width: 240px" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+        <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['acci:fastquery:export']">导出</el-button>
+      </el-form-item>
+    </el-form>
+
+    <div class="table-wrapper">
+    <el-table :height="tableHeight" v-loading="loading" :data="list" border style="width:100%" :header-cell-style="{ 'text-align': 'center' }">
+      <el-table-column label="序号" align="center" type="index" width="60" />
+      <el-table-column label="上报单位" align="center" prop="sgdwName" min-width="160" :show-overflow-tooltip="true" v-if="columns.sgdwName.visible">
+        <template #default="scope">
+          <el-link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['acci:fastquery:detail']">{{ scope.row.sgdwName }}</el-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="事故类型" align="center" prop="acciCate" width="100" v-if="columns.acciCate.visible">
+        <template #default="scope">
+          <dict-tag :options="acci_cate" :value="scope.row.acciCate" />
+        </template>
+      </el-table-column>
+      <el-table-column label="事故等级" align="center" prop="acciGrad" width="100" v-if="columns.acciGrad.visible">
+        <template #default="scope">
+          <dict-tag :options="acci_grad" :value="scope.row.acciGrad" />
+        </template>
+      </el-table-column>
+      <el-table-column label="重伤人数(人)" align="center" prop="serInjNum" width="120" v-if="columns.serInjNum.visible" />
+      <el-table-column label="死亡人数(人)" align="center" prop="casNum" width="120" v-if="columns.casNum.visible" />
+      <el-table-column label="直接经济损失(万元)" align="center" prop="econLoss" width="150" v-if="columns.econLoss.visible" />
+    </el-table>
+    </div>
+
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+
+    <!-- 事故详情弹窗 -->
+    <el-dialog title="事故详情" v-model="detailOpen" width="80%" top="5vh" append-to-body>
+      <div v-loading="detailLoading">
+        <div class="section-title">基本档案</div>
+        <el-table :data="[detailForm]" border style="width: 100%" :header-cell-style="{ 'text-align': 'center' }">
+          <el-table-column label="单位名称" align="center" prop="sgdwName" min-width="140" />
+          <el-table-column label="事故单位类型" align="center" width="100">
+            <template #default="scope">{{ scope.row.acciWiunType === '1' ? '直属' : scope.row.acciWiunType === '2' ? '下级' : scope.row.acciWiunType === '3' ? '流域' : scope.row.acciWiunType }}</template>
+          </el-table-column>
+          <el-table-column label="事故类型" align="center" prop="acciCate" width="100" />
+          <el-table-column label="发生时间" align="center" prop="occuTime" width="100" />
+          <el-table-column label="重伤人数(人)" align="center" prop="serInjNum" width="100" />
+          <el-table-column label="死亡人数(人)" align="center" prop="casNum" width="100" />
+          <el-table-column label="直接经济损失(万元)" align="center" prop="econLoss" width="120" />
+          <el-table-column label="事故简要情况" align="center" prop="otlcolGuuiVicm" min-width="120" :show-overflow-tooltip="true" />
+          <el-table-column label="是否责任事故" align="center" width="100">
+            <template #default="scope">{{ scope.row.ifDuty === '1' ? '是' : '否' }}</template>
+          </el-table-column>
+          <el-table-column label="是否已电话上报" align="center" width="110">
+            <template #default="scope">{{ scope.row.ifPhone === '1' ? '是' : '否' }}</template>
+          </el-table-column>
+        </el-table>
+
+        <div class="section-title" style="margin-top: 16px;">补报信息</div>
+        <el-table :data="suppList" border style="width: 100%" :header-cell-style="{ 'text-align': 'center' }">
+          <el-table-column label="补报时间" align="center" prop="repTime" width="120" />
+          <el-table-column label="死亡人数(人)" align="center" prop="casNum" width="100" />
+          <el-table-column label="重伤人数(人)" align="center" prop="serInjNum" width="100" />
+          <el-table-column label="经济损失(万元)" align="center" prop="econLoss" width="120" />
+          <el-table-column label="事故描述" align="center" prop="acciDesc" min-width="150" :show-overflow-tooltip="true" />
+        </el-table>
+        <pagination :total="suppTotal" v-model:page="suppQuery.pageNum" v-model:limit="suppQuery.pageSize" @pagination="loadSuppList" layout="total, prev, pager, next" />
+      </div>
+      <template #footer>
+        <el-button @click="detailOpen = false">关 闭</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="AcciFastQuery">
+import { listObjAcci, listBisAcciExpRep } from "@/api/slaj/acci"
+import { useTableHeight } from '@/hooks/useTableHeight'
+
+const { tableHeight, containerRef } = useTableHeight()
+
+const { proxy } = getCurrentInstance()
+const { acci_grad, acci_cate } = proxy.useDict("acci_grad", "acci_cate")
+
+const list = ref([])
+const loading = ref(false)
+const total = ref(0)
+const showSearch = ref(true)
+const dateRange = ref([])
+
+const columns = ref({
+  sgdwName: { label: '上报单位', visible: true },
+  acciCate: { label: '事故类型', visible: true },
+  acciGrad: { label: '事故等级', visible: true },
+  serInjNum: { label: '重伤人数', visible: true },
+  casNum: { label: '死亡人数', visible: true },
+  econLoss: { label: '直接经济损失', visible: true }
+})
+
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  wiunProp: undefined,
+  acciCate: undefined,
+  acciGrad: undefined,
+  sgdwName: undefined,
+  areaName: undefined
+})
+
+// 详情弹窗
+const detailOpen = ref(false)
+const detailLoading = ref(false)
+const detailForm = ref({})
+const suppList = ref([])
+const suppTotal = ref(0)
+const suppQuery = reactive({ pageNum: 1, pageSize: 10 })
+
+function getList() {
+  loading.value = true
+  const params = { ...queryParams }
+  if (dateRange.value && dateRange.value.length === 2) {
+    params.beginTime = dateRange.value[0]
+    params.endTime = dateRange.value[1]
+  }
+  listObjAcci(params).then(res => {
+    list.value = res.rows || []
+    total.value = res.total || 0
+  }).finally(() => { loading.value = false })
+}
+
+function handleQuery() {
+  queryParams.pageNum = 1
+  getList()
+}
+
+function handleExport() {
+  const params = { ...queryParams }
+  if (dateRange.value && dateRange.value.length === 2) {
+    params.beginTime = dateRange.value[0]
+    params.endTime = dateRange.value[1]
+  }
+  proxy.download("acci/objacci/export", params, `事故快报_${new Date().getTime()}.xlsx`)
+}
+
+function handleDetail(row) {
+  detailForm.value = { ...row }
+  suppList.value = []
+  suppTotal.value = 0
+  suppQuery.pageNum = 1
+  detailOpen.value = true
+  loadSuppList()
+}
+
+function loadSuppList() {
+  detailLoading.value = true
+  listBisAcciExpRep({ acciGuid: detailForm.value.guid, pageNum: suppQuery.pageNum, pageSize: suppQuery.pageSize }).then(res => {
+    suppList.value = res.rows || []
+    suppTotal.value = res.total || 0
+  }).finally(() => { detailLoading.value = false })
+}
+
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped>
+.table-wrapper { margin-top: 8px; }
+.section-title { font-weight: bold; font-size: 14px; margin-bottom: 8px; }
+</style>

+ 53 - 270
gw-ui/src/views/slaj/acci/index.vue

@@ -1,331 +1,114 @@
 <template>
   <div ref="containerRef" class="app-container">
-    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="auto">
-      <el-form-item label="事故名称" prop="acciName">
-        <el-input v-model="queryParams.acciName" placeholder="请输入事故名称" clearable style="width: 160px" @keyup.enter="handleQuery" />
+    <el-form :model="queryParams" ref="queryRef" :inline="true" label-width="80px">
+      <el-form-item label="组织机构" prop="sgdwName">
+        <el-input v-model="queryParams.sgdwName" placeholder="请输入" clearable style="width: 150px" @keyup.enter="handleQuery" />
       </el-form-item>
-      <el-form-item label="事故级" prop="acciGrad">
-        <el-select v-model="queryParams.acciGrad" placeholder="请选择事故等级" clearable style="width: 130px">
+      <el-form-item label="事故级" prop="acciGrad">
+        <el-select v-model="queryParams.acciGrad" placeholder="请选择" clearable style="width: 130px">
           <el-option v-for="dict in acci_grad" :key="dict.value" :label="dict.label" :value="dict.value" />
         </el-select>
       </el-form-item>
-      <el-form-item label="事故类" prop="acciCate">
-        <el-select v-model="queryParams.acciCate" placeholder="请选择事故类别" clearable style="width: 130px">
+      <el-form-item label="事故类" prop="acciCate">
+        <el-select v-model="queryParams.acciCate" placeholder="请选择" clearable style="width: 130px">
           <el-option v-for="dict in acci_cate" :key="dict.value" :label="dict.label" :value="dict.value" />
         </el-select>
       </el-form-item>
-      <el-form-item label="报状态" prop="repStat">
-        <el-select v-model="queryParams.repStat" placeholder="请选择报告状态" clearable style="width: 130px">
+      <el-form-item label="报状态" prop="repStat">
+        <el-select v-model="queryParams.repStat" placeholder="请选择" clearable style="width: 130px">
           <el-option v-for="dict in rep_stat" :key="dict.value" :label="dict.label" :value="dict.value" />
         </el-select>
       </el-form-item>
-      <!-- 业务说明: 查询范围 dataFrom 控制事故数据的所属维度。1=直属单位(本级直接管辖),2=下级水行政(下级水利部门),3=流域机构(流域管理范围) -->
-      <el-form-item label="查询范围" prop="dataFrom">
-        <el-select v-model="queryParams.dataFrom" placeholder="查询范围" clearable style="width: 130px">
-          <el-option label="直属单位" value="1" />
-          <el-option label="下级水行政" value="2" />
-          <el-option label="流域机构" value="3" />
-        </el-select>
-      </el-form-item>
       <el-form-item label="发生时间">
-        <el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
+        <el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" style="width: 240px"></el-date-picker>
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+        <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
       </el-form-item>
     </el-form>
 
-    <el-row :gutter="10" class="mb8">
-      <el-col :span="1.5">
-        <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['acci:objacci:add']">新增</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate" v-hasPermi="['acci:objacci:edit']">修改</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['acci:objacci:remove']">删除</el-button>
-      </el-col>
-      <el-col :span="1.5">
-        <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['acci:objacci:export']">导出</el-button>
-      </el-col>
-      <!-- 业务说明: 批量上报 — 将表格中勾选的多条事故记录一次性提交至上级单位,后端批量更新事故状态为"已上报"(状态值2) -->
-      <el-col :span="1.5">
-        <el-button type="primary" plain icon="Top" :disabled="multiple" @click="handleBatchReport" v-hasPermi="['acci:objacci:edit']">批量上报</el-button>
-      </el-col>
-      <!-- 业务说明: 催报 — 督促下级单位上报事故月报,触发后端向目标单位发送通知/提醒,仅当选中单条记录时可操作 -->
-      <el-col :span="1.5">
-        <el-button type="info" plain icon="Bell" :disabled="single" @click="handlePushForward" v-hasPermi="['acci:objacci:edit']">催报</el-button>
-      </el-col>
-      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns" storageKey="acci-objacci-index"></right-toolbar>
-    </el-row>
-
     <div class="table-wrapper">
-    <el-table :height="tableHeight" v-loading="loading" :data="objAcciList" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="事故名称" align="center" prop="acciName" v-if="columns.acciName.visible" :show-overflow-tooltip="true" />
-      <el-table-column label="事故等级" align="center" prop="acciGrad" v-if="columns.acciGrad.visible">
+    <el-table :height="tableHeight" v-loading="loading" :data="objAcciList" border :header-cell-style="{ 'text-align': 'center' }">
+      <el-table-column label="序号" align="center" type="index" width="60" />
+      <el-table-column label="事故名称" align="center" prop="acciName" min-width="150" :show-overflow-tooltip="true" />
+      <el-table-column label="事故级别" align="center" prop="acciGrad" width="100">
         <template #default="scope">
           <dict-tag :options="acci_grad" :value="scope.row.acciGrad" />
         </template>
       </el-table-column>
-      <el-table-column label="事故类别" align="center" prop="acciCate" v-if="columns.acciCate.visible">
+      <el-table-column label="事故类型" align="center" prop="acciCate" width="100">
         <template #default="scope">
           <dict-tag :options="acci_cate" :value="scope.row.acciCate" />
         </template>
       </el-table-column>
-      <el-table-column label="报告状态" align="center" prop="repStat" v-if="columns.repStat.visible">
+      <el-table-column label="死亡人数" align="center" prop="casNum" width="90" />
+      <el-table-column label="重伤人数" align="center" prop="serInjNum" width="90" />
+      <el-table-column label="直接经济损失(万元)" align="center" prop="econLoss" width="160" />
+      <el-table-column label="上报状态" align="center" prop="repStat" width="100">
         <template #default="scope">
           <dict-tag :options="rep_stat" :value="scope.row.repStat" />
         </template>
       </el-table-column>
-      <el-table-column label="发生时间" align="center" prop="occuTime" v-if="columns.occuTime.visible" width="180" />
-      <el-table-column label="发生地点" align="center" prop="occuLoc" v-if="columns.occuLoc.visible" :show-overflow-tooltip="true" />
-      <el-table-column label="死亡/重伤/失踪" align="center" width="160" v-if="columns.casNum.visible">
-        <template #default="scope">
-          {{ scope.row.casNum || 0 }}/{{ scope.row.serInjNum || 0 }}/{{ scope.row.missNum || 0 }}
-        </template>
-      </el-table-column>
-
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="250">
-        <template #default="scope">
-          <el-tooltip content="修改" placement="top">
-            <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['acci:objacci:edit']"></el-button>
-          </el-tooltip>
-          <el-tooltip content="详情" placement="top">
-            <el-button link type="primary" icon="View" @click="handleDetail(scope.row)"></el-button>
-          </el-tooltip>
-          <el-tooltip content="催报" placement="top">
-            <el-button link type="primary" icon="Bell" @click="handlePushForward(scope.row)" v-hasPermi="['acci:objacci:edit']"></el-button>
-          </el-tooltip>
-          <el-tooltip content="删除" placement="top">
-            <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['acci:objacci:remove']"></el-button>
-          </el-tooltip>
-        </template>
-      </el-table-column>
+      <el-table-column label="发生时间" align="center" prop="occuTime" width="120" />
+      <el-table-column label="发生地点" align="center" prop="occuLoc" min-width="150" :show-overflow-tooltip="true" />
     </el-table>
     </div>
 
-    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
-
-    <!-- 添加或修改事故对话框 -->
-    <el-dialog :title="title" v-model="open" width="800px" append-to-body>
-      <el-form :model="form" :rules="rules" ref="objAcciRef" label-width="100px">
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="事故名称" prop="acciName">
-              <el-input v-model="form.acciName" placeholder="请输入事故名称" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="事故等级" prop="acciGrad">
-              <el-select v-model="form.acciGrad" placeholder="请选择事故等级">
-                <el-option v-for="dict in acci_grad" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="事故类别" prop="acciCate">
-              <el-select v-model="form.acciCate" placeholder="请选择事故类别">
-                <el-option v-for="dict in acci_cate" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="报告状态" prop="repStat">
-              <el-select v-model="form.repStat" placeholder="请选择报告状态">
-                <el-option v-for="dict in rep_stat" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="12">
-            <el-form-item label="发生时间" prop="occuTime">
-              <el-date-picker v-model="form.occuTime" type="date" placeholder="请选择发生时间" value-format="YYYY-MM-DD" style="width: 100%" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="发生地点" prop="occuLoc">
-              <el-input v-model="form.occuLoc" placeholder="请输入发生地点" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="6">
-            <el-form-item label="死亡" prop="casNum">
-              <el-input-number v-model="form.casNum" :min="0" style="width: 100%" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="6">
-            <el-form-item label="重伤" prop="serInjNum">
-              <el-input-number v-model="form.serInjNum" :min="0" style="width: 100%" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="6">
-            <el-form-item label="失踪" prop="missNum">
-              <el-input-number v-model="form.missNum" :min="0" style="width: 100%" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="6">
-            <el-form-item label="经济损失(万元)" prop="econLoss">
-              <el-input-number v-model="form.econLoss" :min="0" :precision="2" style="width: 100%" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="事故描述" prop="acciDesc">
-              <el-input v-model="form.acciDesc" type="textarea" placeholder="请输入事故描述" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="备注" prop="note">
-              <el-input v-model="form.note" type="textarea" placeholder="请输入备注" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">确 定</el-button>
-          <el-button @click="cancel">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
+    <pagination style="margin-top: 8px;" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
   </div>
 </template>
 
 <script setup name="ObjAcci">
+import { listObjAcci } from "@/api/slaj/acci"
 import { useTableHeight } from '@/hooks/useTableHeight'
 
 const { tableHeight, containerRef } = useTableHeight()
-
 const { proxy } = getCurrentInstance()
 const { acci_grad, acci_cate, rep_stat } = proxy.useDict("acci_grad", "acci_cate", "rep_stat")
 
 const objAcciList = ref([])
-const open = ref(false)
-const loading = ref(true)
-const showSearch = ref(true)
-const ids = ref([])
-const single = ref(true)
-const multiple = ref(true)
+const loading = ref(false)
 const total = ref(0)
-const title = ref("")
 const dateRange = ref([])
 
-const columns = ref({
-  acciName: { label: '事故名称', visible: true },
-  acciGrad: { label: '事故等级', visible: true },
-  acciCate: { label: '事故类别', visible: true },
-  repStat: { label: '报告状态', visible: true },
-  occuTime: { label: '发生时间', visible: true },
-  occuLoc: { label: '发生地点', visible: true },
-  casNum: { label: '伤亡人数', visible: true },
-  econLoss: { label: '经济损失(万元)', visible: true }
-})
-
-const data = reactive({
-  form: {},
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    acciName: undefined,
-    acciGrad: undefined,
-    acciCate: undefined,
-    repStat: undefined,
-    dataFrom: undefined,
-    orgGuid: undefined
-  },
-  rules: {
-    acciName: [{ required: true, message: "事故名称不能为空", trigger: "blur" }],
-    acciGrad: [{ required: true, message: "事故等级不能为空", trigger: "change" }],
-    acciCate: [{ required: true, message: "事故类别不能为空", trigger: "change" }],
-    repStat: [{ required: true, message: "报告状态不能为空", trigger: "change" }]
-  }
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  sgdwName: undefined,
+  acciGrad: undefined,
+  acciCate: undefined,
+  repStat: undefined,
+  beginTime: undefined,
+  endTime: undefined
 })
 
-const { queryParams, form, rules } = toRefs(data)
-
-const mockData = [
-  { guid: 'a001', acciName: '坝体渗漏事故', acciGrad: '1', acciCate: '1', repStat: '2', occuTime: '2025-03-15', occuLoc: '于桥水库主坝', casNum: 0, serInjNum: 2, missNum: 0, econLoss: 150, acciDesc: '主坝下游坡面出现渗漏', sgdwName: '天津市于桥水库管理中心', engGuid: 'e001' },
-  { guid: 'a002', acciName: '闸门启闭故障', acciGrad: '2', acciCate: '2', repStat: '1', occuTime: '2025-04-20', occuLoc: '引滦工程泄洪闸', casNum: 0, serInjNum: 0, missNum: 0, econLoss: 80, acciDesc: '泄洪闸无法正常启闭', sgdwName: '天津市引滦工程管理中心', engGuid: 'e002' },
-  { guid: 'a003', acciName: '施工坍塌事故', acciGrad: '3', acciCate: '3', repStat: '2', occuTime: '2025-05-10', occuLoc: '永定新河堤防段', casNum: 1, serInjNum: 3, missNum: 0, econLoss: 500, acciDesc: '堤防加固施工中发生局部坍塌', sgdwName: '永定新河管理处', engGuid: 'e003' },
-  { guid: 'a004', acciName: '泵站电气火灾', acciGrad: '2', acciCate: '4', repStat: '1', occuTime: '2025-06-02', occuLoc: '海河泵站', casNum: 0, serInjNum: 1, missNum: 0, econLoss: 200, acciDesc: '电气控制柜短路引发火灾', sgdwName: '海河管理处', engGuid: 'e004' },
-  { guid: 'a005', acciName: '水质污染事件', acciGrad: '1', acciCate: '5', repStat: '2', occuTime: '2025-06-18', occuLoc: '引滦输水管道', casNum: 0, serInjNum: 0, missNum: 0, econLoss: 300, acciDesc: '输水管道破裂导致水源污染', sgdwName: '引滦工程管理中心', engGuid: 'e002' }
-]
-
-function paginate(arr, page, size) { const s = (page - 1) * size; return { rows: arr.slice(s, s + size), total: arr.length } }
-
 function getList() {
   loading.value = true
-  setTimeout(() => {
-    let data = [...mockData]
-    if (queryParams.value.acciName) data = data.filter(d => d.acciName.includes(queryParams.value.acciName))
-    if (queryParams.value.acciGrad) data = data.filter(d => d.acciGrad === queryParams.value.acciGrad)
-    if (queryParams.value.acciCate) data = data.filter(d => d.acciCate === queryParams.value.acciCate)
-    if (queryParams.value.repStat) data = data.filter(d => d.repStat === queryParams.value.repStat)
-    const res = paginate(data, queryParams.value.pageNum, queryParams.value.pageSize)
-    objAcciList.value = res.rows; total.value = res.total; loading.value = false
-  }, 200)
-}
-
-function handleQuery() { queryParams.value.pageNum = 1; getList() }
-function resetQuery() { dateRange.value = []; proxy.resetForm("queryRef"); handleQuery() }
-function handleSelectionChange(selection) { ids.value = selection.map(item => item.guid); single.value = selection.length != 1; multiple.value = !selection.length }
-
-function handleAdd() { reset(); open.value = true; title.value = "添加事故" }
-function handleUpdate(row) { reset(); const guid = row.guid || ids.value; const d = mockData.find(m => m.guid === guid); if (d) { form.value = { ...d }; open.value = true; title.value = "修改事故" } }
-function handleDetail(row) { proxy.$router.push({ path: '/slaj/acci/detail', query: { guid: row.guid || ids.value } }) }
-
-function submitForm() {
-  proxy.$refs["objAcciRef"].validate(valid => {
-    if (!valid) return
-    if (form.value.guid) { const i = mockData.findIndex(m => m.guid === form.value.guid); if (i > -1) Object.assign(mockData[i], form.value) }
-    else { mockData.unshift({ ...form.value, guid: 'a' + Date.now() }) }
-    proxy.$modal.msgSuccess(form.value.guid ? "修改成功" : "新增成功")
-    open.value = false; getList()
-  })
+  const params = { ...queryParams }
+  if (dateRange.value && dateRange.value.length === 2) {
+    params.beginTime = dateRange.value[0]
+    params.endTime = dateRange.value[1]
+  }
+  listObjAcci(params).then(res => {
+    objAcciList.value = res.rows || []
+    total.value = res.total || 0
+    loading.value = false
+  }).catch(() => { loading.value = false })
 }
 
-function handlePushForward(row) { proxy.$confirm('确认催报该事故?', '提示', { type: 'warning' }).then(() => { proxy.$modal.msgSuccess("催报成功") }).catch(() => {}) }
-function handleBatchReport() { proxy.$confirm('确认将选中的事故上报至上级单位?', '提示', { type: 'warning' }).then(() => { proxy.$modal.msgSuccess("批量上报成功") }).catch(() => {}) }
-
-function handleDelete(row) {
-  const guid = row.guid || ids.value[0]
-  proxy.$modal.confirm('是否确认删除?').then(() => {
-    const i = mockData.findIndex(m => m.guid === guid); if (i > -1) mockData.splice(i, 1)
-    getList(); proxy.$modal.msgSuccess("删除成功")
-  }).catch(() => {})
+function handleQuery() {
+  queryParams.pageNum = 1
+  getList()
 }
 
-function cancel() { open.value = false; reset() }
-function handleExport() { proxy.$modal.msgSuccess("导出(模拟)") }
-
-/** 重置表单 */
-function reset() {
-  form.value = {
-    guid: undefined,
-    acciName: undefined,
-    acciGrad: undefined,
-    acciCate: undefined,
-    repStat: undefined,
-    occuTime: undefined,
-    occuLoc: undefined,
-    casNum: undefined,
-    serInjNum: undefined,
-    missNum: undefined,
-    econLoss: undefined,
-    acciDesc: undefined,
-    note: undefined,
-    orgGuid: undefined
+function handleExport() {
+  const params = { ...queryParams }
+  if (dateRange.value && dateRange.value.length === 2) {
+    params.beginTime = dateRange.value[0]
+    params.endTime = dateRange.value[1]
   }
-  proxy.resetForm("objAcciRef")
+  proxy.download("acci/objacci/export", params, `事故数据_${new Date().getTime()}.xlsx`)
 }
 
 onMounted(() => {

+ 67 - 29
gw-ui/src/views/slaj/acci/manage.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="app-container">
     <el-tabs v-model="activeTab" type="border-card" @tab-change="handleTabChange">
-      <el-tab-pane label="事故(事件)快报" name="fast">
+      <el-tab-pane v-if="hasAcciTabPermi('fast')" label="事故(事件)快报" name="fast">
         <el-form :model="queryParams1" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="事故等级" prop="acciGrad">
             <el-select v-model="queryParams1.acciGrad" placeholder="请选择" clearable style="width: 150px">
@@ -15,9 +15,9 @@
             <el-button type="primary" icon="Search" @click="handleQuery1">搜索</el-button>
           </el-form-item>
           <el-form-item style="margin-left:auto;">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd1">新建</el-button>
+            <el-button type="primary" plain icon="Plus" @click="handleAdd1" v-hasPermi="['acci:fast:add']">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport1">导出</el-button>
-            <el-button type="danger" plain icon="Delete" :disabled="multiple1" @click="handleDelete1">删除</el-button>
+            <el-button type="danger" plain icon="Delete" :disabled="multiple1" @click="handleDelete1" v-hasPermi="['acci:fast:remove']">删除</el-button>
           </el-form-item>
         </el-form>
         <div class="table-wrapper">
@@ -44,10 +44,10 @@
           <el-table-column label="是否已电话上报" align="center" width="110" prop="ifPhone" />
           <el-table-column label="操作" align="center" width="200" fixed="right">
             <template #default="scope">
-              <el-button link type="info" @click="handleFast(scope.row)">快报</el-button>
-              <el-button link type="warning" @click="handleSupplement(scope.row)">补报</el-button>
-              <el-button link type="primary" icon="Edit" @click="handleUpdate1(scope.row)" />
-              <el-button link type="danger" icon="Delete" @click="handleDelete1(scope.row)" />
+              <el-button link type="info" @click="handleFast(scope.row)" v-hasPermi="['acci:fast:report']">快报</el-button>
+              <el-button link type="warning" @click="handleSupplement(scope.row)" v-hasPermi="['acci:fast:edit']">补报</el-button>
+              <el-button link type="primary" icon="Edit" @click="handleUpdate1(scope.row)" v-hasPermi="['acci:fast:edit']" />
+              <el-button link type="danger" icon="Delete" @click="handleDelete1(scope.row)" v-hasPermi="['acci:fast:remove']" />
             </template>
           </el-table-column>
         </el-table>
@@ -55,7 +55,7 @@
         <pagination :total="total1" v-model:page="queryParams1.pageNum" v-model:limit="queryParams1.pageSize" @pagination="getList1" />
       </el-tab-pane>
 
-      <el-tab-pane label="事故月报" name="month">
+      <el-tab-pane v-if="hasAcciTabPermi('month')" label="事故月报" name="month">
         <el-form :model="queryParams2" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="事故等级" prop="acciGrad">
             <el-select v-model="queryParams2.acciGrad" placeholder="请选择" clearable style="width: 150px">
@@ -70,9 +70,9 @@
             <el-button :type="queryParams2.ifDuty ? 'danger' : ''" @click="filterDuty">{{ queryParams2.ifDuty ? '显示全部' : '剔除非责任事故' }}</el-button>
           </el-form-item>
           <el-form-item style="margin-left:auto;">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd2">新建</el-button>
+            <el-button type="primary" plain icon="Plus" @click="handleAdd2" v-hasPermi="['acci:month:add']">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport2">导出</el-button>
-            <el-button type="danger" plain icon="Delete" :disabled="multiple2" @click="handleDelete2">删除</el-button>
+            <el-button type="danger" plain icon="Delete" :disabled="multiple2" @click="handleDelete2" v-hasPermi="['acci:month:remove']">删除</el-button>
           </el-form-item>
         </el-form>
         <div class="table-wrapper">
@@ -98,9 +98,9 @@
           <el-table-column label="是否已电话上报" align="center" width="110" prop="ifPhone" />
           <el-table-column label="操作" align="center" width="180" fixed="right">
             <template #default="scope">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate2(scope.row)" />
-              <el-button link type="warning" @click="handleSupplement(scope.row)">补报</el-button>
-              <el-button link type="danger" icon="Delete" @click="handleDelete2(scope.row)" />
+              <el-button link type="primary" icon="Edit" @click="handleUpdate2(scope.row)" v-hasPermi="['acci:month:edit']" />
+              <el-button link type="warning" @click="handleSupplement(scope.row)" v-hasPermi="['acci:month:supplement']">补报</el-button>
+              <el-button link type="danger" icon="Delete" @click="handleDelete2(scope.row)" v-hasPermi="['acci:month:remove']" />
             </template>
           </el-table-column>
         </el-table>
@@ -108,7 +108,7 @@
         <pagination :total="total2" v-model:page="queryParams2.pageNum" v-model:limit="queryParams2.pageSize" @pagination="getList2" />
       </el-tab-pane>
 
-      <el-tab-pane label="下级单位快报事故(事件)查询" name="subFast">
+      <el-tab-pane v-if="hasAcciTabPermi('subFast')" label="下级单位快报事故(事件)查询" name="subFast">
         <el-form :model="queryParams3" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="选择下级单位" prop="orgName">
             <el-input v-model="queryParams3.orgName" placeholder="请输入单位名称" clearable style="width: 200px" @keyup.enter="handleQuery3" />
@@ -144,7 +144,7 @@
         <pagination :total="total3" v-model:page="queryParams3.pageNum" v-model:limit="queryParams3.pageSize" @pagination="getList3" />
       </el-tab-pane>
 
-      <el-tab-pane label="下级单位事故月报查询" name="subMonth">
+      <el-tab-pane v-if="hasAcciTabPermi('subMonth')" label="下级单位事故月报查询" name="subMonth">
         <el-form :model="queryParams4" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="选择下级单位" prop="orgName">
             <el-input v-model="queryParams4.orgName" placeholder="请输入单位名称" clearable style="width: 200px" @keyup.enter="handleQuery4" />
@@ -180,18 +180,38 @@
         <pagination :total="total4" v-model:page="queryParams4.pageNum" v-model:limit="queryParams4.pageSize" @pagination="getList4" />
       </el-tab-pane>
 
-      <el-tab-pane label="施工单位事故月报查询" name="consMonth">
+      <el-tab-pane v-if="hasAcciTabPermi('consMonth')" label="施工单位事故月报查询" name="consMonth">
         <el-form :model="queryParams5" :inline="true" v-show="showSearch" label-width="80px">
-          <el-form-item label="事故名称" prop="acciName">
-            <el-input v-model="queryParams5.acciName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery5" />
+          <el-form-item label="选择参建单位" prop="orgName">
+            <el-input v-model="queryParams5.orgName" placeholder="请输入" clearable style="width: 180px" @keyup.enter="handleQuery5" />
+          </el-form-item>
+          <el-form-item label="事故等级" prop="acciGrad">
+            <el-select v-model="queryParams5.acciGrad" placeholder="请选择" clearable style="width: 150px">
+              <el-option v-for="dict in acci_grad" :key="dict.value" :label="dict.label" :value="dict.value" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="发生时间">
+            <el-date-picker v-model="dateRange5" type="daterange" range-separator="至" start-placeholder="开始" end-placeholder="结束" value-format="YYYY-MM-DD" style="width: 240px" />
           </el-form-item>
           <el-form-item>
             <el-button type="primary" icon="Search" @click="handleQuery5">搜索</el-button>
           </el-form-item>
         </el-form>
         <div class="table-wrapper">
-        <el-table :height="tableHeight" :data="list5" border style="width:100%">
+        <el-table :height="tableHeight" :data="list5" border style="width:100%" :header-cell-style="{ 'text-align':'center' }">
           <el-table-column label="序号" align="center" type="index" width="60" />
+          <el-table-column label="事故单位类型" align="center" width="100">
+            <template #default="scope">{{ scope.row.acciWiunType === '1' ? '直属' : scope.row.acciWiunType === '2' ? '下级' : scope.row.acciWiunType === '3' ? '流域' : '' }}</template>
+          </el-table-column>
+          <el-table-column label="事故类型" align="center" prop="acciCate" width="90" />
+          <el-table-column label="发生时间" align="center" prop="occuTime" width="100" />
+          <el-table-column label="重伤人数" align="center" prop="serInjNum" width="80" />
+          <el-table-column label="死亡人数" align="center" prop="casNum" width="80" />
+          <el-table-column label="直接经济损失(万元)" align="center" prop="econLoss" min-width="130" />
+          <el-table-column label="事故原因" align="center" prop="acciCause" min-width="140" :show-overflow-tooltip="true" />
+          <el-table-column label="事故简要情况" align="center" prop="otlcolGuuiVicm" min-width="150" :show-overflow-tooltip="true" />
+          <el-table-column label="是否责任事故" align="center" width="100" prop="ifDuty" />
+          <el-table-column label="是否已电话上报" align="center" width="110" prop="ifPhone" />
         </el-table>
         </div>
         <pagination :total="total5" v-model:page="queryParams5.pageNum" v-model:limit="queryParams5.pageSize" @pagination="getList5" />
@@ -293,8 +313,8 @@
 
     <el-dialog title="事故(事件)快报补报记录" v-model="suppOpen" width="900px" append-to-body>
       <el-row :gutter="10" class="mb8">
-        <el-button type="primary" plain icon="Plus" @click="handleSuppAdd">新建</el-button>
-        <el-button type="danger" plain icon="Delete" :disabled="suppMultiple" @click="handleSuppDelete()">删除</el-button>
+        <el-button type="primary" plain icon="Plus" @click="handleSuppAdd" v-hasPermi="['acci:fast:edit']">新建</el-button>
+        <el-button type="danger" plain icon="Delete" :disabled="suppMultiple" @click="handleSuppDelete()" v-hasPermi="['acci:fast:remove']">删除</el-button>
       </el-row>
       <el-table :data="suppList" @selection-change="handleSuppSelect" border size="small" height="300">
         <el-table-column type="selection" width="40" align="center" />
@@ -306,8 +326,8 @@
         <el-table-column label="事故描述" align="center" prop="acciDesc" min-width="160" :show-overflow-tooltip="true" />
         <el-table-column label="操作" align="center" width="100">
           <template #default="scope">
-            <el-button link type="primary" icon="Edit" @click="handleSuppUpdate(scope.row)" />
-            <el-button link type="danger" icon="Delete" @click="handleSuppDelete(scope.row)" />
+            <el-button link type="primary" icon="Edit" @click="handleSuppUpdate(scope.row)" v-hasPermi="['acci:fast:edit']" />
+            <el-button link type="danger" icon="Delete" @click="handleSuppDelete(scope.row)" v-hasPermi="['acci:fast:remove']" />
           </template>
         </el-table-column>
       </el-table>
@@ -469,8 +489,8 @@
 
     <el-dialog title="事故月报补报记录" v-model="suppMonthOpen" width="950px" append-to-body>
       <el-row :gutter="10" class="mb8">
-        <el-button type="primary" plain icon="Plus" @click="handleSuppMonthAdd">新建</el-button>
-        <el-button type="danger" plain icon="Delete" :disabled="suppMonthMultiple" @click="handleSuppMonthDelete()">删除</el-button>
+        <el-button type="primary" plain icon="Plus" @click="handleSuppMonthAdd" v-hasPermi="['acci:month:supplement']">新建</el-button>
+        <el-button type="danger" plain icon="Delete" :disabled="suppMonthMultiple" @click="handleSuppMonthDelete()" v-hasPermi="['acci:month:remove']">删除</el-button>
       </el-row>
       <el-table :data="suppMonthList" @selection-change="handleSuppMonthSelect" border size="small" height="300">
         <el-table-column type="selection" width="40" align="center" />
@@ -482,7 +502,7 @@
         <el-table-column label="事故描述" align="center" prop="acciDesc" min-width="200" :show-overflow-tooltip="true" />
         <el-table-column label="操作" align="center" width="80">
           <template #default="scope">
-            <el-button link type="danger" icon="Delete" @click="handleSuppMonthDelete(scope.row)" />
+            <el-button link type="danger" icon="Delete" @click="handleSuppMonthDelete(scope.row)" v-hasPermi="['acci:month:remove']" />
           </template>
         </el-table-column>
       </el-table>
@@ -524,7 +544,19 @@ import { getToken } from "@/utils/auth"
 const { proxy } = getCurrentInstance()
 const { acci_grad } = proxy.useDict("acci_grad")
 
-const activeTab = ref('fast')
+const tabPermiMap = {
+  fast: 'acci:tab:fast',
+  month: 'acci:tab:month',
+  subFast: 'acci:tab:subFast',
+  subMonth: 'acci:tab:subMonth',
+  consMonth: 'acci:tab:consMonth'
+}
+function hasAcciTabPermi(name) {
+  const permi = tabPermiMap[name]
+  if (!permi) return true
+  return proxy.$auth.hasPermi(permi)
+}
+const activeTab = ref(Object.keys(tabPermiMap).find(k => hasAcciTabPermi(k)) || 'fast')
 const showSearch = ref(true)
 const tableHeight = 'calc(100vh - 240px)'
 
@@ -562,7 +594,8 @@ const queryParams3 = reactive({ pageNum: 1, pageSize: 10, orgName: undefined, ac
 const dateRange4 = ref([])
 
 const queryParams4 = reactive({ pageNum: 1, pageSize: 10, orgName: undefined, acciGrad: undefined })
-const queryParams5 = reactive({ pageNum: 1, pageSize: 10, acciName: undefined })
+const dateRange5 = ref([])
+const queryParams5 = reactive({ pageNum: 1, pageSize: 10, orgName: undefined, acciGrad: undefined })
 
 function getList1() {
   const p = { ...queryParams1 }
@@ -736,7 +769,12 @@ function getList4() {
 }
 function handleQuery4() { queryParams4.pageNum = 1; getList4() }
 
-function getList5() {}; function handleQuery5() {}
+function getList5() {
+  const p = { ...queryParams5 }
+  if (dateRange5.value && dateRange5.value.length === 2) { p.beginTime = dateRange5.value[0]; p.endTime = dateRange5.value[1] }
+  listObjAcci(p).then(res => { list5.value = res.rows || []; total5.value = res.total || 0 })
+}
+function handleQuery5() { queryParams5.pageNum = 1; getList5() }
 
 function handleTabChange() {
   if (activeTab.value === 'fast') getList1()

+ 8 - 8
gw-ui/src/views/slaj/acci/month.vue

@@ -28,24 +28,24 @@
             <el-radio value="1">直属单位上报</el-radio>
             <el-radio value="2">下级行政主管部门上报</el-radio>
           </el-radio-group>
-          <el-button size="small" @click="handlePendingApproval" style="margin-left:auto;">
+          <el-button size="small" @click="handlePendingApproval" style="margin-left:auto;" v-hasPermi="['acci:month:supervise']">
             待审批<el-badge v-if="pendingCount > 0" :value="pendingCount" :max="99" style="margin-left:4px;" />
           </el-button>
-          <el-button size="small" type="primary" @click="handleReport">上报</el-button>
-          <el-button size="small" @click="handleBatchRevoke">撤销</el-button>
+          <el-button size="small" type="primary" @click="handleReport" v-hasPermi="['acci:month:report']">上报</el-button>
+          <el-button size="small" @click="handleBatchRevoke" v-hasPermi="['acci:month:report']">撤销</el-button>
         </div>
         <div class="action-bar">
           <span class="filter-label">选择月份:</span>
           <el-select v-model="selectedMonth" placeholder="请选择月份" size="small" style="width:160px" @change="handleMonthChange">
             <el-option v-for="item in monthOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
-          <el-button size="small" @click="handleBatchUnlock" style="margin-left:12px;">一键解锁</el-button>
+          <el-button size="small" @click="handleBatchUnlock" style="margin-left:12px;" v-hasPermi="['acci:month:supervise']">一键解锁</el-button>
         </div>
         <el-table v-loading="loading" :data="statsList" stripe border height="calc(100vh - 280px)" style="width: 100%">
           <el-table-column label="序号" align="center" type="index" width="55" />
           <el-table-column label="上报单位" align="center" min-width="130" :show-overflow-tooltip="true">
             <template #default="scope">
-              <el-link type="primary" @click="handleOrgDetail(scope.row)">{{ scope.row.orgName || '--' }}</el-link>
+              <el-link type="primary" @click="handleOrgDetail(scope.row)" v-hasPermi="['acci:month:detail']">{{ scope.row.orgName || '--' }}</el-link>
             </template>
           </el-table-column>
           <el-table-column label="上报时间" align="center" width="90">
@@ -59,7 +59,7 @@
           <el-table-column label="直接经济损失(万元)" align="center" width="140" prop="econLoss" />
           <el-table-column label="操作" align="center" width="110" fixed="right">
             <template #default="scope">
-              <el-button v-if="scope.row.repAct !== '1'" link type="warning" @click="handleSupervise(scope.row)">督促上报</el-button>
+              <el-button v-if="scope.row.repAct !== '1'" link type="warning" @click="handleSupervise(scope.row)" v-hasPermi="['acci:month:supervise']">督促上报</el-button>
               <el-tag v-else type="success" size="small">已上报</el-tag>
             </template>
           </el-table-column>
@@ -101,8 +101,8 @@
         <el-table-column label="撤回原因" align="center" prop="revocDesc" min-width="150" :show-overflow-tooltip="true" />
         <el-table-column label="操作" align="center" width="140">
           <template #default="scope">
-            <el-button link type="primary" @click="handleApprove(scope.row)">同意</el-button>
-            <el-button link type="danger" @click="handleReject(scope.row)">不同意</el-button>
+            <el-button link type="primary" @click="handleApprove(scope.row)" v-hasPermi="['acci:month:supervise']">同意</el-button>
+            <el-button link type="danger" @click="handleReject(scope.row)" v-hasPermi="['acci:month:supervise']">不同意</el-button>
           </template>
         </el-table-column>
       </el-table>

+ 65 - 154
gw-ui/src/views/slaj/acci/stat.vue

@@ -1,173 +1,84 @@
 <template>
-  <div class="app-container">
-    <el-row :gutter="20" class="mb8">
-      <el-col :span="24">
-        <el-form :model="queryParams" inline>
-          <!-- 业务说明: 范围切换 — 统计数据按三种业务维度筛选: 1=直属单位(本级管辖范围),2=下级水行政(下级水利部门),3=流域机构(全流域汇总) -->
-          <el-form-item label="查询范围" prop="dataFrom">
-            <el-select v-model="queryParams.dataFrom" placeholder="查询范围" clearable style="width: 240px" @change="handleRangeChange">
-              <el-option label="直属单位" value="1" />
-              <el-option label="下级水行政" value="2" />
-              <el-option label="流域机构" value="3" />
-            </el-select>
-          </el-form-item>
-        </el-form>
-      </el-col>
-    </el-row>
-    <el-row :gutter="20" class="mb8">
-      <el-col :span="4" v-for="card in statCards" :key="card.key">
-        <el-card shadow="hover">
-          <template #header><span>{{ card.label }}</span></template>
-          <div class="stat-card">
-            <div class="stat-value" :style="{ color: card.color }">{{ summaryData[card.key] ?? 0 }}</div>
-          </div>
-        </el-card>
-      </el-col>
-    </el-row>
+  <div ref="containerRef" class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="单位性质" prop="orgNature">
+        <el-select v-model="queryParams.orgNature" placeholder="请选择" clearable style="width: 180px">
+          <el-option label="直属单位" value="1" />
+          <el-option label="下级水行政" value="2" />
+          <el-option label="流域机构" value="3" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="事故采集时间" prop="dateRange">
+        <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD" style="width: 260px" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+      </el-form-item>
+    </el-form>
 
-    <el-row :gutter="20" class="mb8">
-      <!-- 业务说明: 事故类别分布(饼图) — 按事故的业务分类维度(如工程事故、设备事故等)展示各类别占比 -->
-      <el-col :span="12">
-        <el-card shadow="hover">
-          <template #header><span>事故类别分布</span></template>
-          <div ref="pieChartRef" style="height: 400px;"></div>
-        </el-card>
-      </el-col>
-      <!-- 业务说明: 事故等级统计(柱状图) — 按一般/较大/重大/特别重大四级展示数量分布,用于快速掌握事故严重程度构成 -->
-      <el-col :span="12">
-        <el-card shadow="hover">
-          <template #header><span>事故等级统计</span></template>
-          <div ref="barChartRef" style="height: 400px;"></div>
-        </el-card>
-      </el-col>
+    <el-row :gutter="10" class="mb8">
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-row :gutter="20">
-      <!-- 业务说明: 事故趋势(折线图) — 按月份统计事故发生数量的时间序列,用于分析事故发生的周期性规律和趋势变化 -->
-      <el-col :span="24">
-        <el-card shadow="hover">
-          <template #header><span>事故趋势(按月份)</span></template>
-          <div ref="trendChartRef" style="height: 400px;"></div>
-        </el-card>
-      </el-col>
-    </el-row>
+    <div class="table-wrapper">
+      <el-table :height="tableHeight" v-loading="loading" :data="statList" border style="width:100%" :header-cell-style="{ 'text-align': 'center' }">
+        <el-table-column label="序号" align="center" type="index" width="60" />
+        <el-table-column label="单位名称" align="center" prop="orgname" min-width="160" :show-overflow-tooltip="true" />
+        <el-table-column label="事故数量" align="center" prop="accicount" width="100" />
+        <el-table-column label="死亡人数" align="center" prop="deathcount" width="100" />
+        <el-table-column label="重伤人数" align="center" prop="injurycount" width="100" />
+        <el-table-column label="直接经济损失(万元)" align="center" prop="econloss" width="160" />
+        <el-table-column label="平均死亡人数" align="center" prop="avgdeath" width="120" />
+        <el-table-column label="平均重伤人数" align="center" prop="avginjury" width="120" />
+        <el-table-column label="平均经济损失(万元)" align="center" prop="avgeconloss" width="170" />
+      </el-table>
+    </div>
+
+    <pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
   </div>
 </template>
 
 <script setup name="AcciStat">
-import { reactive, ref, onMounted, nextTick } from 'vue'
-import { getAcciSummary, getAcciByCategory, listObjAcci } from "@/api/slaj/acci"
-import * as echarts from "echarts"
-
-const queryParams = reactive({ dataFrom: undefined })
-
-function handleRangeChange() {
-  fetchSummary()
-  fetchCategory()
-}
+import { listAcciStat } from "@/api/slaj/acci"
+import { useTableHeight } from '@/hooks/useTableHeight'
 
-// 业务说明: 统计卡片 — 按事故严重程度划分为四个等级(一般/较大/重大/特别重大),对应不同颜色标识
-const statCards = [
-  { key: 'total', label: '事故总数', color: '#409eff' },
-  { key: 'general', label: '一般事故', color: '#67c23a' },
-  { key: 'larger', label: '较大事故', color: '#e6a23c' },
-  { key: 'major', label: '重大事故', color: '#f56c6c' },
-  { key: 'special', label: '特别重大事故', color: '#b22222' },
-]
+const { tableHeight, containerRef } = useTableHeight()
+const { proxy } = getCurrentInstance()
 
-const summaryData = ref({})
-const pieChartRef = ref(null)
-const barChartRef = ref(null)
-const trendChartRef = ref(null)
+const loading = ref(false)
+const showSearch = ref(true)
+const statList = ref([])
+const total = ref(0)
+const dateRange = ref([])
 
-function fetchSummary() {
-  getAcciSummary(queryParams).then(res => {
-    summaryData.value = res.data ?? {}
-    nextTick(() => {
-      initBarChart()
-      initTrendChart()
-    })
-  })
-}
-
-function fetchCategory() {
-  getAcciByCategory(queryParams).then(res => {
-    const data = res.data ?? {}
-    const pieData = Object.entries(data).map(([name, value]) => ({ name, value }))
-    nextTick(() => initPieChart(pieData))
-  })
-}
-
-/** 业务说明: 初始化事故类别分布饼图 — 按事故业务类别(如工程、设备、管理等)统计各维度占比 */
-function initPieChart(data) {
-  if (!pieChartRef.value) return
-  const chart = echarts.init(pieChartRef.value)
-  chart.setOption({
-    tooltip: { trigger: 'item', formatter: '{b}: {c} ({d}%)' },
-    legend: { orient: 'vertical', left: 'left' },
-    series: [{
-      name: '事故类别', type: 'pie', radius: '50%',
-      data: data.length > 0 ? data : [{ name: '暂无数据', value: 1 }],
-      emphasis: { itemStyle: { shadowBlur: 10 } }
-    }]
-  })
-}
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: 10,
+  orgNature: undefined,
+  beginTime: undefined,
+  endTime: undefined
+})
 
-/** 业务说明: 初始化事故等级统计柱状图 — 按一般/较大/重大/特别重大四个等级维度展示数量,柱状颜色从绿到红逐级加深 */
-function initBarChart() {
-  if (!barChartRef.value) return
-  const chart = echarts.init(barChartRef.value)
-  const levels = ['一般事故', '较大事故', '重大事故', '特别重大事故']
-  const keys = ['general', 'larger', 'major', 'special']
-  const data = keys.map(k => summaryData.value[k] ?? 0)
-  chart.setOption({
-    tooltip: { trigger: 'axis' },
-    grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
-    xAxis: { type: 'category', data: levels },
-    yAxis: { type: 'value' },
-    series: [{
-      name: '事故数量', type: 'bar', barWidth: '50%', data,
-      itemStyle: { color: (p) => ['#67c23a', '#e6a23c', '#f56c6c', '#b22222'][p.dataIndex] }
-    }]
-  })
+function getList() {
+  loading.value = true
+  const params = { ...queryParams }
+  if (dateRange.value && dateRange.value.length === 2) {
+    params.beginTime = dateRange.value[0]
+    params.endTime = dateRange.value[1]
+  }
+  listAcciStat(params).then(res => {
+    statList.value = res.rows || []
+    total.value = res.total || 0
+    loading.value = false
+  }).catch(() => { loading.value = false })
 }
 
-/** 业务说明: 初始化事故趋势折线图 — 按月统计事故发生数量,前端汇总所有事故的发生时间并归月,展示各月事故数量趋势,辅助分析事故高发时段 */
-function initTrendChart() {
-  if (!trendChartRef.value) return
-  listObjAcci({ pageNum: 1, pageSize: 1000 }).then(res => {
-    const list = res.rows || []
-    const monthMap = {}
-    list.forEach(item => {
-      if (item.occuTime) {
-        const mon = item.occuTime.substring(0, 7)
-        monthMap[mon] = (monthMap[mon] || 0) + 1
-      }
-    })
-    const sorted = Object.entries(monthMap).sort(([a], [b]) => a.localeCompare(b))
-    const chart = echarts.init(trendChartRef.value)
-    chart.setOption({
-      tooltip: { trigger: 'axis' },
-      grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true },
-      xAxis: { type: 'category', data: sorted.map(([m]) => m), axisLabel: { rotate: 45 } },
-      yAxis: { type: 'value' },
-      series: [{
-        name: '事故数量', type: 'line', smooth: true,
-        data: sorted.map(([, v]) => v),
-        areaStyle: { color: 'rgba(64,158,255,0.1)' },
-        itemStyle: { color: '#409eff' }
-      }]
-    })
-  })
+function handleQuery() {
+  queryParams.pageNum = 1
+  getList()
 }
 
 onMounted(() => {
-  fetchSummary()
-  fetchCategory()
+  getList()
 })
 </script>
-
-<style scoped>
-.stat-card { text-align: center; padding: 20px 0; }
-.stat-value { font-size: 32px; font-weight: bold; margin-bottom: 10px; }
-</style>

+ 4 - 4
gw-ui/src/views/slaj/hazard/engQuery.vue

@@ -2,7 +2,7 @@
   <div class="app-container">
     <el-tabs v-model="activeTab" type="border-card" @tab-change="onTabChange">
       <!-- 工程危险源 -->
-      <el-tab-pane label="工程危险源" name="eng">
+      <el-tab-pane v-hasPermi="['hazar:tab:queryEng']" label="工程危险源" name="eng">
         <el-form :model="queryParams" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="工程名称" prop="engName">
             <el-input v-model="queryParams.engName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery" />
@@ -12,7 +12,7 @@
           </el-form-item>
           <el-form-item>
             <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
+            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['hazar:query:export']">导出</el-button>
           </el-form-item>
         </el-form>
 
@@ -33,14 +33,14 @@
       </el-tab-pane>
 
       <!-- 非工程危险源 -->
-      <el-tab-pane label="非工程危险源" name="nonEng">
+      <el-tab-pane v-hasPermi="['hazar:tab:queryNonEng']" label="非工程危险源" name="nonEng">
         <el-form :model="queryParams2" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="组织机构" prop="orgName">
             <el-input v-model="queryParams2.orgName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery2" />
           </el-form-item>
           <el-form-item>
             <el-button type="primary" icon="Search" @click="handleQuery2">搜索</el-button>
-            <el-button type="warning" plain icon="Download" @click="handleExport2">导出</el-button>
+            <el-button type="warning" plain icon="Download" @click="handleExport2" v-hasPermi="['hazar:query:export']">导出</el-button>
           </el-form-item>
         </el-form>
 

+ 33 - 22
gw-ui/src/views/slaj/hazard/manage.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="app-container">
     <el-tabs v-model="activeTab" type="border-card" @tab-change="handleTabChange">
-      <el-tab-pane label="工程危险源管理" name="eng">
+      <el-tab-pane v-if="hasTabPermi2('eng')" label="工程危险源管理" name="eng">
         <el-form :model="queryParams" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="危险源名称" prop="hazName">
             <el-input v-model="queryParams.hazName" placeholder="请输入" clearable style="width: 180px" @keyup.enter="handleQuery" />
@@ -28,9 +28,9 @@
             <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
           </el-form-item>
           <el-form-item style="margin-left:auto;">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd">新建</el-button>
+            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['hazar:eng:add']">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
-            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">删除</el-button>
+            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['hazar:eng:remove']">删除</el-button>
           </el-form-item>
         </el-form>
 
@@ -59,21 +59,21 @@
           </el-table-column>
           <el-table-column label="操作" align="center" width="220" fixed="right">
             <template #default="scope">
-              <el-button link type="info" @click="handleRecord(scope.row)">填报记录</el-button>
-              <el-button v-if="scope.row.hazStat === '0'" link type="warning" @click="handleSubmit(scope.row)">报送</el-button>
+              <el-button link type="info" @click="handleRecord(scope.row)" v-hasPermi="['hazar:eng:record']">填报记录</el-button>
+              <el-button v-if="scope.row.hazStat === '0'" link type="warning" v-hasPermi="['hazar:eng:report']" @click="handleSubmit(scope.row)">报送</el-button>
               <el-tag v-else-if="scope.row.hazStat === '1'" type="warning" size="small">已报送</el-tag>
               <el-tag v-else-if="scope.row.hazStat === '2'" type="success" size="small">已监管</el-tag>
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
-              <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" />
+              <el-button link type="primary" icon="Edit" v-hasPermi="['hazar:eng:edit']" @click="handleUpdate(scope.row)" />
+              <el-button link type="danger" icon="Delete" v-if="canDelete(scope.row)" @click="handleDelete(scope.row)" />
             </template>
           </el-table-column>
         </el-table>
-        </div>
 
         <pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+        </div>
       </el-tab-pane>
 
-      <el-tab-pane label="标段危险源管理" name="tend">
+      <el-tab-pane v-if="hasTabPermi2('tend')" label="标段危险源管理" name="tend">
         <el-form :model="queryParams2" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="危险源名称" prop="hazName">
             <el-input v-model="queryParams2.hazName" placeholder="请输入" clearable style="width: 180px" @keyup.enter="handleQuery2" />
@@ -95,9 +95,9 @@
             <el-button type="primary" icon="Search" @click="handleQuery2">搜索</el-button>
           </el-form-item>
           <el-form-item style="margin-left:auto;">
-            <el-button type="primary" plain icon="Plus" @click="handleAdd">新建</el-button>
+            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['hazar:tend:add']">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport2">导出</el-button>
-            <el-button type="danger" plain icon="Delete" :disabled="multiple2" @click="handleDelete2()">删除</el-button>
+            <el-button type="danger" plain icon="Delete" :disabled="multiple2" @click="handleDelete2()" v-hasPermi="['hazar:tend:remove']">删除</el-button>
           </el-form-item>
         </el-form>
 
@@ -128,10 +128,10 @@
           </el-table-column>
           <el-table-column label="操作" align="center" width="220" fixed="right">
             <template #default="scope">
-              <el-button link type="info" @click="handleRecord(scope.row)">填报记录</el-button>
-              <el-button link type="primary" icon="Edit" @click="handleUpdate2(scope.row)" />
-              <el-button link type="danger" icon="Delete" @click="handleDelete2(scope.row)" />
-              <el-button v-if="scope.row.hazStat === '0'" link type="warning" @click="handleSubmit(scope.row)">报送</el-button>
+              <el-button link type="info" @click="handleRecord(scope.row)" v-hasPermi="['hazar:tend:record']">填报记录</el-button>
+              <el-button link type="primary" icon="Edit" v-hasPermi="['hazar:tend:edit']" @click="handleUpdate2(scope.row)" />
+              <el-button link type="danger" icon="Delete" v-if="canDelete(scope.row)" @click="handleDelete2(scope.row)" />
+              <el-button v-if="scope.row.hazStat === '0'" link type="warning" v-hasPermi="['hazar:tend:report']" @click="handleSubmit(scope.row)">报送</el-button>
               <el-tag v-else-if="scope.row.hazStat === '1'" type="warning" size="small">已报送</el-tag>
               <el-tag v-else-if="scope.row.hazStat === '2'" type="success" size="small">已监管</el-tag>
             </template>
@@ -142,7 +142,7 @@
         <pagination :total="total2" v-model:page="queryParams2.pageNum" v-model:limit="queryParams2.pageSize" @pagination="getList2" />
       </el-tab-pane>
 
-      <el-tab-pane label="危险物品登记" name="chem">
+      <el-tab-pane v-if="hasTabPermi2('chem')" label="危险物品登记" name="chem">
         <el-form :model="queryParams3" :inline="true" v-show="showSearch" label-width="90px">
           <el-form-item label="危险物品名称" prop="hachName">
             <el-input v-model="queryParams3.hachName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery3" />
@@ -154,9 +154,9 @@
             <el-button type="primary" icon="Search" @click="handleQuery3">搜索</el-button>
           </el-form-item>
           <el-form-item style="margin-left:auto;">
-            <el-button type="primary" plain icon="Plus" @click="handleChemAdd">新建</el-button>
+            <el-button type="primary" plain icon="Plus" @click="handleChemAdd" v-hasPermi="['hazar:chem:add']">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport3">导出</el-button>
-            <el-button type="danger" plain icon="Delete" :disabled="multiple3" @click="handleDelete3()">删除</el-button>
+            <el-button type="danger" plain icon="Delete" :disabled="multiple3" @click="handleDelete3()" v-hasPermi="['hazar:chem:remove']">删除</el-button>
           </el-form-item>
         </el-form>
 
@@ -174,9 +174,9 @@
           <el-table-column label="过期处理方式" align="center" prop="ovduProcMode" width="110" :show-overflow-tooltip="true" />
           <el-table-column label="操作" align="center" width="180" fixed="right">
             <template #default="scope">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate3(scope.row)" />
-              <el-button link type="danger" icon="Delete" @click="handleDelete3(scope.row)" />
-              <el-button link type="info" @click="handleChemRecord(scope.row)">出入库记录</el-button>
+              <el-button link type="primary" icon="Edit" @click="handleUpdate3(scope.row)" v-hasPermi="['hazar:chem:edit']" />
+              <el-button link type="danger" icon="Delete" @click="handleDelete3(scope.row)" v-hasPermi="['hazar:chem:remove']" />
+              <el-button link type="info" @click="handleChemRecord(scope.row)" v-hasPermi="['hazar:chem:record']">出入库记录</el-button>
             </template>
           </el-table-column>
         </el-table>
@@ -464,7 +464,18 @@ const userStore = useUserStore()
 const { proxy } = getCurrentInstance()
 const { haz_grad, haz_stat, risk_grad, sys_yes_no } = proxy.useDict("haz_grad", "haz_stat", "risk_grad", "sys_yes_no")
 
-const activeTab = ref('eng')
+const tabPermiMap2 = { eng: 'hazar:tab:manageEng', tend: 'hazar:tab:manageTend', chem: 'hazar:tab:manageChem' }
+function hasTabPermi2(name) {
+  const p = tabPermiMap2[name]
+  return !p || proxy.$auth.hasPermi(p)
+}
+const activeTab = ref(Object.keys(tabPermiMap2).find(k => hasTabPermi2(k)) || 'eng')
+
+function canDelete(row) {
+  if (proxy.$auth.hasPermi('hazar:objhaz:remove')) return true
+  if (proxy.$auth.hasPermi('hazar:objhaz:removeDraft') && row.hazStat === '0') return true
+  return false
+}
 const showSearch = ref(true)
 const tableHeight = 'calc(100vh - 240px)'
 

+ 1 - 1
gw-ui/src/views/slaj/hazard/patrol.vue

@@ -56,6 +56,7 @@
         </div>
 
         <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+        </div>
       </el-tab-pane>
 
       <!-- 巡查任务 -->
@@ -169,7 +170,6 @@
         </el-table>
 
         <pagination v-show="recordTotal > 0" :total="recordTotal" v-model:page="recordQueryParams.pageNum" v-model:limit="recordQueryParams.pageSize" @pagination="getRecordList" />
-        </div>
       </el-tab-pane>
     </el-tabs>
 

+ 7 - 2
gw-ui/src/views/slaj/hazard/supervise.vue

@@ -1,5 +1,9 @@
 <template>
   <div ref="containerRef" class="app-container">
+    <div v-if="!$auth.hasPermi('hazar:objhaz:supervise')" class="no-permission">
+      <el-empty description="您没有访问该页面的权限,请联系管理员" />
+    </div>
+    <template v-else>
     <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="80px">
       <el-form-item label="监管状态" prop="hazStat">
         <el-select v-model="queryParams.hazStat" placeholder="请选择" clearable style="width: 150px">
@@ -22,7 +26,7 @@
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-        <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
+        <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['hazar:supervise:export']">导出</el-button>
       </el-form-item>
     </el-form>
 
@@ -32,7 +36,7 @@
       <el-table-column label="单位名称" align="center" prop="orgName" min-width="140" :show-overflow-tooltip="true" />
       <el-table-column label="危险源名称" align="center" min-width="160" :show-overflow-tooltip="true">
         <template #default="scope">
-          <el-button link type="primary" @click="handleDetail(scope.row)">{{ scope.row.hazName }}</el-button>
+          <el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['hazar:supervise:detail']">{{ scope.row.hazName }}</el-button>
         </template>
       </el-table-column>
       <el-table-column label="所属工程" align="center" prop="engName" min-width="150" :show-overflow-tooltip="true" />
@@ -104,6 +108,7 @@
         <el-button @click="detailOpen = false">关 闭</el-button>
       </template>
     </el-dialog>
+    </template>
   </div>
 </template>
 

+ 3 - 3
gw-ui/src/views/slaj/hidd/engQuery.vue

@@ -14,7 +14,7 @@
           </el-form-item>
           <el-form-item>
             <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
+            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['hidd:query:export']">导出</el-button>
           </el-form-item>
         </el-form>
 
@@ -40,7 +40,7 @@
           </el-form-item>
           <el-form-item>
             <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
-            <el-button type="warning" plain icon="Download" @click="handleExport">导出</el-button>
+            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['hidd:query:export']">导出</el-button>
           </el-form-item>
         </el-form>
 
@@ -84,7 +84,7 @@ function getList() {
 }
 
 function handleQuery() { queryParams.pageNum = 1; getList() }
-function handleExport() { proxy.download("hidd/objhidd/export", { ...queryParams }, `隐患查询_${new Date().getTime()}.xlsx`) }
+function handleExport() { proxy.download("hidd/objhidd/groupBy/export", { ...queryParams }, `隐患查询_${new Date().getTime()}.xlsx`) }
 
 onMounted(() => { getList() })
 </script>

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

@@ -40,25 +40,25 @@
             <el-radio value="3">流域机构上报</el-radio>
             <el-radio value="2">下级水行政部门上报</el-radio>
           </el-radio-group>
-          <el-button size="small" @click="handlePendingApproval" style="margin-left:auto;">
+          <el-button size="small" @click="handlePendingApproval" style="margin-left:auto;" v-hasPermi="['hidd:month:supervise']">
             待审批<el-badge v-if="pendingCount > 0" :value="pendingCount" :max="99" style="margin-left:4px;" />
           </el-button>
-          <el-button size="small" type="primary" @click="handleReport">上报</el-button>
-          <el-button size="small" @click="handleBatchRevoke">撤销</el-button>
+          <el-button size="small" type="primary" @click="handleReport" v-hasPermi="['hidd:month:report']">上报</el-button>
+          <el-button size="small" @click="handleBatchRevoke" v-hasPermi="['hidd:month:report']">撤销</el-button>
         </div>
         <div class="action-bar">
           <span class="filter-label">选择月份:</span>
           <el-select v-model="selectedMonth" placeholder="请选择月份" size="small" style="width:160px" @change="handleMonthChange">
             <el-option v-for="item in monthOptions" :key="item.value" :label="item.label" :value="item.value" />
           </el-select>
-          <el-button size="small" @click="handleBatchUnlock" style="margin-left:12px;">一键解锁</el-button>
-          <el-button size="small" @click="handleCustomPeriod">自定义上报期</el-button>
+          <el-button size="small" @click="handleBatchUnlock" style="margin-left:12px;" v-hasPermi="['hidd:month:unlock']">一键解锁</el-button>
+          <el-button size="small" @click="handleCustomPeriod" v-hasPermi="['hidd:month:period']">自定义上报期</el-button>
         </div>
         <el-table v-loading="loading" :data="statsList" stripe border height="calc(100vh - 280px)" style="width: 100%">
           <el-table-column label="序号" align="center" type="index" width="55" />
           <el-table-column label="上报单位" align="center" min-width="130" :show-overflow-tooltip="true">
             <template #default="scope">
-              <el-link type="primary" @click="handleOrgDetail(scope.row)">{{ scope.row.repName || scope.row.orgName || '--' }}</el-link>
+              <el-link type="primary" @click="handleOrgDetail(scope.row)" v-hasPermi="['hidd:month:detail']">{{ scope.row.repName || scope.row.orgName || '--' }}</el-link>
             </template>
           </el-table-column>
           <el-table-column label="上报时间" align="center" width="90">
@@ -81,13 +81,13 @@
           <el-table-column label="操作" align="center" width="110" fixed="right">
             <template #default="scope">
               <template v-if="unitType === '0'">
-                <el-button v-if="scope.row.repAct === '1'" link type="primary" @click="handleRevocApply(scope.row)">回撤</el-button>
+                <el-button v-if="scope.row.repAct === '1'" link type="primary" @click="handleRevocApply(scope.row)" v-hasPermi="['hidd:month:report']">回撤</el-button>
                 <span v-else style="color: #999;">未上报</span>
               </template>
               <template v-else>
                 <el-tag v-if="scope.row.repAct === '1'" type="success" size="small">已上报</el-tag>
-                <el-button v-else link type="warning" @click="handleSupervise(scope.row)">督促上报</el-button>
-                <el-button v-if="scope.row.repAct === '1'" link type="danger" @click="handleReturn(scope.row)">退回</el-button>
+                <el-button v-else link type="warning" @click="handleSupervise(scope.row)" v-hasPermi="['hidd:month:urge']">督促上报</el-button>
+                <el-button v-if="scope.row.repAct === '1'" link type="danger" @click="handleReturn(scope.row)" v-hasPermi="['hidd:month:return']">退回</el-button>
               </template>
             </template>
           </el-table-column>
@@ -128,8 +128,8 @@
         <el-table-column label="撤回原因" align="center" prop="revocDesc" min-width="150" :show-overflow-tooltip="true" />
         <el-table-column label="操作" align="center" width="140">
           <template #default="scope">
-            <el-button link type="primary" @click="handleApprove(scope.row)">同意</el-button>
-            <el-button link type="danger" @click="handleReject(scope.row)">不同意</el-button>
+            <el-button link type="primary" @click="handleApprove(scope.row)" v-hasPermi="['hidd:month:supervise']">同意</el-button>
+            <el-button link type="danger" @click="handleReject(scope.row)" v-hasPermi="['hidd:month:supervise']">不同意</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -343,7 +343,7 @@ function handleOrgDetail(row) {
   const orgGuid = row.repOrgGuid || row.orgGuid
   const orgName = row.repName || ''
   detailTitle.value = '隐患月报详情'
-  detailUrl.value = `/slaj/hidd/monthDetail?guid=${row.guid}&month=${selectedMonth.value}&orgName=${encodeURIComponent(orgName)}`
+  detailUrl.value = `${import.meta.env.BASE_URL}slaj/hidd/monthDetail?guid=${row.guid}&month=${selectedMonth.value}&orgName=${encodeURIComponent(orgName)}`
   detailOpen.value = true
 }
 

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

@@ -39,7 +39,7 @@
             </span>
           </div>
           <div class="info-buttons">
-            <el-button type="success" plain size="small" @click="handleExport">导出</el-button>
+            <el-button type="success" plain size="small" @click="handleExport" v-hasPermi="['hidd:month:detailExport']">导出</el-button>
           </div>
         </div>
       </el-card>

+ 254 - 63
gw-ui/src/views/slaj/hidd/orgEngQuery.vue

@@ -1,8 +1,8 @@
 <template>
   <div class="app-container">
     <el-tabs v-model="activeTab" type="border-card" @tab-change="handleTabChange">
-      <el-tab-pane label="本单位工程隐患" name="selfEng">
-        <div ref="containerRef" class="table-page-wrap">
+      <el-tab-pane v-if="hasTabPermi('selfEng')" label="本单位工程隐患" name="selfEng">
+        <div class="table-page-wrap">
         <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
           <el-form-item label="隐患名称" prop="hiddName">
             <el-input v-model="queryParams.hiddName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery" />
@@ -14,6 +14,7 @@
             <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['hidd:objhidd:add']">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['hidd:objhidd:export']">导出</el-button>
             <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete" v-hasPermi="['hidd:objhidd:remove']">删除</el-button>
+            <el-button type="success" plain icon="Upload" :disabled="ids.length === 0" @click="handleReport" v-hasPermi="['hidd:objhidd:report']">上报</el-button>
           </el-form-item>
         </el-form>
 
@@ -34,6 +35,11 @@
               <dict-tag :options="hidd_clas" :value="scope.row.hiddClas" />
             </template>
           </el-table-column>
+          <el-table-column label="隐患来源" align="center" width="100">
+            <template #default="scope">
+              <dict-tag :options="hidd_sour" :value="scope.row.hiddSour" />
+            </template>
+          </el-table-column>
           <el-table-column label="排查日期" align="center" width="100" prop="inspDate" />
           <el-table-column label="要求整改完成日期" align="center" width="120" prop="requCompDate" />
           <el-table-column label="督办状态" align="center" width="90">
@@ -48,10 +54,10 @@
           </el-table-column>
           <el-table-column label="操作" align="center" width="200" fixed="right">
             <template #default="scope">
-              <el-button link type="primary" @click="handleRectify(scope.row)">整改</el-button>
-              <el-button v-if="scope.row.hiddStat==='2' && scope.row.supStat==='1' && scope.row.cancelState==='0'" link type="warning" @click="handleCancelApply(scope.row)">销号申请</el-button>
-              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" />
-              <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" />
+              <el-button v-if="scope.row.hiddStat==='0' || scope.row.hiddStat==='1'" link type="primary" v-hasPermi="['hidd:objhidd:rectify']" @click="handleRectify(scope.row)">整改</el-button>
+              <el-button v-if="scope.row.hiddStat==='2' && scope.row.supStat==='1' && scope.row.cancelState==='0'" link type="warning" v-hasPermi="['hidd:objhidd:writeoff']" @click="handleCancelApply(scope.row)">销号申请</el-button>
+              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['hidd:objhidd:edit']" />
+              <el-button link type="danger" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['hidd:objhidd:remove']" />
             </template>
           </el-table-column>
         </el-table>
@@ -61,8 +67,8 @@
         </div>
       </el-tab-pane>
 
-      <el-tab-pane label="下级单位隐患" name="subEng">
-        <div ref="containerRef2" class="table-page-wrap">
+      <el-tab-pane v-if="hasTabPermi('subEng')" label="下级单位隐患" name="subEng">
+        <div class="table-page-wrap">
         <el-form :model="queryParams2" :inline="true" v-show="showSearch" label-width="68px">
           <el-form-item label="隐患名称" prop="hiddName">
             <el-input v-model="queryParams2.hiddName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery2" />
@@ -75,11 +81,15 @@
           </el-form-item>
           <el-form-item style="margin-left:auto;">
             <el-button type="warning" plain icon="Download" @click="handleExport2">导出</el-button>
+            <el-button type="primary" plain icon="Position" :disabled="!ids2 || ids2.length === 0" @click="handleSupFromSub" v-hasPermi="['hidd:objhidd:supervise']">督办</el-button>
+            <el-button type="warning" plain icon="Back" :disabled="!ids2 || ids2.length === 0" @click="handleReturnFromSub" v-hasPermi="['hidd:objhidd:return']">退回</el-button>
+            <el-button type="success" plain icon="Upload" :disabled="!ids2 || ids2.length === 0" @click="handleReport2" v-hasPermi="['hidd:objhidd:report']">上报</el-button>
           </el-form-item>
         </el-form>
 
         <div class="table-wrapper">
-        <el-table :height="tableHeight" v-loading="loading2" :data="list2" border style="width:100%" :header-cell-style="{ 'text-align': 'center' }">
+        <el-table :height="tableHeight" v-loading="loading2" :data="list2" border style="width:100%" :header-cell-style="{ 'text-align': 'center' }" @selection-change="rows => ids2 = rows.map(r => r.guid)">
+          <el-table-column type="selection" width="50" align="center" />
           <el-table-column label="序号" align="center" type="index" width="60" />
           <el-table-column label="排查单位" align="center" prop="orgName" min-width="140" :show-overflow-tooltip="true" />
           <el-table-column label="隐患名称" align="center" prop="hiddName" min-width="160" :show-overflow-tooltip="true" />
@@ -89,6 +99,11 @@
               <dict-tag :options="hidd_clas" :value="scope.row.hiddClas" />
             </template>
           </el-table-column>
+          <el-table-column label="隐患来源" align="center" width="100">
+            <template #default="scope">
+              <dict-tag :options="hidd_sour" :value="scope.row.hiddSour" />
+            </template>
+          </el-table-column>
           <el-table-column label="录入时间" align="center" width="100" prop="collTime" />
           <el-table-column label="排查日期" align="center" width="100" prop="inspDate" />
           <el-table-column label="要求完成整改日期" align="center" width="130" prop="requCompDate" />
@@ -109,8 +124,8 @@
         </div>
       </el-tab-pane>
 
-      <el-tab-pane label="本单位标段隐患" name="bidEng">
-        <div ref="containerRef3" class="table-page-wrap">
+      <el-tab-pane v-if="hasTabPermi('bidEng')" label="本单位标段隐患" name="bidEng">
+        <div class="table-page-wrap">
         <el-form :model="queryParams3" ref="queryRef3" :inline="true" v-show="showSearch" label-width="68px">
           <el-form-item label="隐患名称" prop="hiddName">
             <el-input v-model="queryParams3.hiddName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery3" />
@@ -122,6 +137,7 @@
             <el-button type="primary" plain icon="Plus" @click="handleAdd3">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport3">导出</el-button>
             <el-button type="danger" plain icon="Delete" :disabled="multiple3" @click="handleDelete3">删除</el-button>
+            <el-button type="success" plain icon="Upload" :disabled="ids3.length === 0" @click="handleReport3" v-hasPermi="['hidd:objhidd:report']">上报</el-button>
           </el-form-item>
         </el-form>
 
@@ -142,6 +158,11 @@
               <dict-tag :options="hidd_clas" :value="scope.row.hiddClas" />
             </template>
           </el-table-column>
+          <el-table-column label="隐患来源" align="center" width="100">
+            <template #default="scope">
+              <dict-tag :options="hidd_sour" :value="scope.row.hiddSour" />
+            </template>
+          </el-table-column>
           <el-table-column label="录入时间" align="center" width="100" prop="collTime" />
           <el-table-column label="排查日期" align="center" width="100" prop="inspDate" />
           <el-table-column label="要求整改完成日期" align="center" width="130" prop="requCompDate" />
@@ -157,9 +178,10 @@
           </el-table-column>
           <el-table-column label="操作" align="center" width="150" fixed="right">
             <template #default="scope">
-              <el-button link type="primary" @click="handleRectify(scope.row)">整改</el-button>
-              <el-button link type="primary" icon="Edit" @click="handleUpdate3(scope.row)" />
-              <el-button link type="danger" icon="Delete" @click="handleDelete3(scope.row)" />
+              <el-button v-if="scope.row.hiddStat==='0' || scope.row.hiddStat==='1'" link type="primary" v-hasPermi="['hidd:objhidd:rectify']" @click="handleRectify(scope.row)">整改</el-button>
+              <el-button v-if="scope.row.hiddStat==='2' && scope.row.supStat==='1' && scope.row.cancelState==='0'" link type="warning" v-hasPermi="['hidd:objhidd:writeoff']" @click="handleCancelApply(scope.row)">销号申请</el-button>
+              <el-button link type="primary" icon="Edit" @click="handleUpdate3(scope.row)" v-hasPermi="['hidd:objhidd:edit']" />
+              <el-button link type="danger" icon="Delete" @click="handleDelete3(scope.row)" v-hasPermi="['hidd:objhidd:remove']" />
             </template>
           </el-table-column>
         </el-table>
@@ -169,8 +191,8 @@
         </div>
       </el-tab-pane>
 
-      <el-tab-pane label="施工单位隐患" name="consEng">
-        <div ref="containerRef4" class="table-page-wrap">
+      <el-tab-pane v-if="hasTabPermi('consEng')" label="施工单位隐患" name="consEng">
+        <div class="table-page-wrap">
         <el-form :model="queryParams4" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="隐患名称" prop="hiddName">
             <el-input v-model="queryParams4.hiddName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery4" />
@@ -185,6 +207,7 @@
             <el-button type="primary" plain icon="Plus" @click="handleAdd4">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport4">导出</el-button>
             <el-button type="danger" plain icon="Delete" :disabled="multiple4" @click="handleDelete4">删除</el-button>
+            <el-button type="success" plain icon="Upload" :disabled="ids4.length === 0" @click="handleReport4" v-hasPermi="['hidd:objhidd:report']">上报</el-button>
           </el-form-item>
         </el-form>
 
@@ -205,6 +228,11 @@
               <dict-tag :options="hidd_clas" :value="scope.row.hiddClas" />
             </template>
           </el-table-column>
+          <el-table-column label="隐患来源" align="center" width="100">
+            <template #default="scope">
+              <dict-tag :options="hidd_sour" :value="scope.row.hiddSour" />
+            </template>
+          </el-table-column>
           <el-table-column label="录入时间" align="center" width="100" prop="collTime" />
           <el-table-column label="排查日期" align="center" width="100" prop="inspDate" />
           <el-table-column label="要求整改完成日期" align="center" width="130" prop="requCompDate" />
@@ -220,8 +248,8 @@
           </el-table-column>
           <el-table-column label="操作" align="center" width="100" fixed="right">
             <template #default="scope">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate4(scope.row)" />
-              <el-button link type="danger" icon="Delete" @click="handleDelete4(scope.row)" />
+              <el-button link type="primary" icon="Edit" @click="handleUpdate4(scope.row)" v-hasPermi="['hidd:objhidd:edit']" />
+              <el-button link type="danger" icon="Delete" @click="handleDelete4(scope.row)" v-hasPermi="['hidd:objhidd:remove']" />
             </template>
           </el-table-column>
         </el-table>
@@ -231,8 +259,8 @@
         </div>
       </el-tab-pane>
 
-      <el-tab-pane label="参建单位隐患" name="partEng">
-        <div ref="containerRef5" class="table-page-wrap">
+      <el-tab-pane v-if="hasTabPermi('partEng')" label="参建单位隐患" name="partEng">
+        <div class="table-page-wrap">
         <el-form :model="queryParams5" :inline="true" v-show="showSearch" label-width="80px">
           <el-form-item label="隐患名称" prop="hiddName">
             <el-input v-model="queryParams5.hiddName" placeholder="请输入" clearable style="width: 200px" @keyup.enter="handleQuery5" />
@@ -247,6 +275,7 @@
             <el-button type="primary" plain icon="Plus" @click="handleAdd5">新建</el-button>
             <el-button type="warning" plain icon="Download" @click="handleExport5">导出</el-button>
             <el-button type="danger" plain icon="Delete" :disabled="multiple5" @click="handleDelete5">删除</el-button>
+            <el-button type="success" plain icon="Upload" :disabled="ids5.length === 0" @click="handleReport5" v-hasPermi="['hidd:objhidd:report']">上报</el-button>
           </el-form-item>
         </el-form>
 
@@ -267,6 +296,11 @@
               <dict-tag :options="hidd_clas" :value="scope.row.hiddClas" />
             </template>
           </el-table-column>
+          <el-table-column label="隐患来源" align="center" width="100">
+            <template #default="scope">
+              <dict-tag :options="hidd_sour" :value="scope.row.hiddSour" />
+            </template>
+          </el-table-column>
           <el-table-column label="录入时间" align="center" width="100" prop="collTime" />
           <el-table-column label="排查日期" align="center" width="100" prop="inspDate" />
           <el-table-column label="要求整改完成日期" align="center" width="130" prop="requCompDate" />
@@ -282,8 +316,8 @@
           </el-table-column>
           <el-table-column label="操作" align="center" width="100" fixed="right">
             <template #default="scope">
-              <el-button link type="primary" icon="Edit" @click="handleUpdate5(scope.row)" />
-              <el-button link type="danger" icon="Delete" @click="handleDelete5(scope.row)" />
+              <el-button link type="primary" icon="Edit" @click="handleUpdate5(scope.row)" v-hasPermi="['hidd:objhidd:edit']" />
+              <el-button link type="danger" icon="Delete" @click="handleDelete5(scope.row)" v-hasPermi="['hidd:objhidd:remove']" />
             </template>
           </el-table-column>
         </el-table>
@@ -516,7 +550,7 @@
           <tr>
             <td class="label-cell"><span class="required">*</span>隐患名称</td>
             <td class="value-cell">
-              <el-input v-model="form.hiddName" placeholder="请输入隐患名称" size="small" />
+              <el-autocomplete v-model="form.hiddName" :fetch-suggestions="queryHiddName" placeholder="请输入隐患名称(支持模糊搜索)" size="small" :trigger-on-focus="true" clearable style="width:100%" />
             </td>
             <td class="label-cell"><span class="required">*</span>排查日期</td>
             <td class="value-cell">
@@ -563,6 +597,14 @@
               </el-select>
             </td>
           </tr>
+          <tr>
+            <td class="label-cell"><span class="required">*</span>隐患来源</td>
+            <td class="value-cell" colspan="3">
+              <el-select v-model="form.hiddSour" placeholder="请选择隐患来源" size="small" style="width:100%">
+                <el-option v-for="dict in hidd_sour" :key="dict.value" :label="dict.label" :value="dict.value" />
+              </el-select>
+            </td>
+          </tr>
           <tr>
             <td class="label-cell"><span class="required">*</span>排查单位</td>
             <td class="value-cell">
@@ -573,6 +615,15 @@
               <el-input v-model="form.inspLeader" placeholder="请输入发现人" size="small" />
             </td>
           </tr>
+          <tr v-if="activeTab === 'consEng'">
+            <td class="label-cell"><span class="required">*</span>目标施工单位</td>
+            <td class="value-cell" colspan="3">
+              <el-select v-model="form.orgGuid" placeholder="请选择目标施工单位" size="small" style="width:100%" filterable
+                @change="val => { const o = consOrgList.find(o => o.value === val); if (o) form.orgName = o.label }">
+                <el-option v-for="item in consOrgList" :key="item.value" :label="item.label" :value="item.value" />
+              </el-select>
+            </td>
+          </tr>
           <tr>
             <td class="label-cell">职务</td>
             <td class="value-cell">
@@ -616,27 +667,91 @@
         <el-button type="primary" @click="submitFormDrawer" :loading="formLoading">保 存</el-button>
       </template>
     </el-dialog>
+
+    <!-- 退回弹窗 -->
+    <el-dialog title="隐患退回" v-model="returnOpen" width="500px" append-to-body>
+      <el-form :model="returnForm" label-width="80px">
+        <el-form-item label="退回说明" required>
+          <el-input v-model="returnForm.returnDesc" type="textarea" :rows="4" maxlength="500" show-word-limit placeholder="请输入退回说明(500字以内)" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button type="primary" @click="submitReturn">确 定</el-button>
+        <el-button @click="returnOpen = false">取 消</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 督办弹窗(从subEng发起) -->
+    <el-dialog title="隐患督办" v-model="supDialogOpen" width="700px" append-to-body>
+      <el-form :model="supDialogForm" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="隐患名称">
+              <el-input v-model="supDialogForm.hiddName" disabled />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="隐患级别">
+              <el-input :value="supDialogForm.hiddGrad === '2' ? '重大隐患' : '一般隐患'" disabled />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="督办文号" required>
+              <el-input v-model="supDialogForm.supLareId" placeholder="请输入督办文号" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="整改期限" required>
+              <el-date-picker v-model="supDialogForm.rectPeri" type="date" value-format="YYYY-MM-DD" placeholder="选择整改期限" style="width:100%" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="督办意见" required>
+          <el-input v-model="supDialogForm.supOpin" type="textarea" :rows="4" placeholder="请输入督办意见" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button type="primary" @click="submitSupDialog">确 定</el-button>
+        <el-button @click="supDialogOpen = false">取 消</el-button>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup name="OrgEngQuery">
-import { listObjHidd, delObjHidd, addObjHidd, updateObjHidd, compoundSaveHidd, getHiddGroupBy, listBisHiddRectImpl, addBisHiddRectImpl, updateBisHiddRectImpl, listBisHiddRectAcce, addBisHiddRectAcce, updateBisHiddRectAcce, listBisHiddRectProg, addBisHiddRectProg, listAttEngBase } from "@/api/slaj/hidd"
+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 { getToken } from "@/utils/auth"
-import { useTableHeight } from '@/hooks/useTableHeight'
 import useUserStore from '@/store/modules/user'
 
-const { tableHeight, containerRef } = useTableHeight()
-const containerRef2 = ref(null)
-const containerRef3 = ref(null)
-const containerRef4 = ref(null)
-const containerRef5 = ref(null)
+const tableHeight = ref('calc(100vh - 240px)')
 const { proxy } = getCurrentInstance()
-const { hidd_grad, hidd_stat, sup_stat, hidd_clas } = proxy.useDict("hidd_grad", "hidd_stat", "sup_stat", "hidd_clas")
+const { hidd_grad, hidd_stat, sup_stat, hidd_sour, hidd_clas } = proxy.useDict("hidd_grad", "hidd_stat", "sup_stat", "hidd_sour", "hidd_clas")
 const userStore = useUserStore()
 
-const activeTab = ref('selfEng')
+const tabPermiMap = {
+  selfEng: 'hidd:tab:selfEng',
+  subEng: 'hidd:tab:subEng',
+  bidEng: 'hidd:tab:bidEng',
+  consEng: 'hidd:tab:consEng',
+  partEng: 'hidd:tab:partEng'
+}
+function hasTabPermi(name) {
+  const permi = tabPermiMap[name]
+  if (!permi) return true
+  return proxy.$auth.hasPermi(permi)
+}
+const activeTab = ref(Object.keys(tabPermiMap).find(k => hasTabPermi(k)) || 'selfEng')
 const showSearch = ref(true)
 
+watch(activeTab, (val) => {
+  if (!hasTabPermi(val)) {
+    const first = Object.keys(tabPermiMap).find(k => hasTabPermi(k))
+    if (first) activeTab.value = first
+  }
+})
+
 // Tab1 本单位工程隐患
 const list = ref([]); const loading = ref(false); const total = ref(0)
 const ids = ref([]); const single = ref(true); const multiple = ref(true)
@@ -663,6 +778,7 @@ const fileAttachList = ref([])
 const engList = ref([])
 
 const tendList = ref([])
+const consOrgList = ref([])
 const filteredTendList = computed(() => {
   if (!form.value.engGuid) return tendList.value
   return tendList.value.filter(t => t.engGuid === form.value.engGuid)
@@ -694,6 +810,14 @@ const form = ref({})
 const formLoading = ref(false)
 const isEditMode = computed(() => !!form.value.guid)
 
+function queryHiddName(queryString, cb) {
+  if (!queryString) { cb([]); return }
+  getHiddListByName({ hiddName: queryString, pageSize: 20 }).then(res => {
+    const list = (res.rows || []).map(item => ({ value: item.hiddName, hiddGrad: item.hiddGrad, hiddClas: item.hiddClas, proPart: item.proPart }))
+    cb(list)
+  }).catch(() => cb([]))
+}
+
 function handleAdd() {
   formTitle.value = '本级单位工程隐患新增'
   form.value = { hiddSort: '1', hiddGrad: '1', hiddStat: '0', inspDate: '', inspLeader: '', inspLeaderPost: '', proPart: '', hiddDesc: '', engGuid: '', tendGuid: '', engName: '', tendName: '', orgGuid: userStore.orgGuid || '' }
@@ -761,6 +885,87 @@ function submitFormDrawer() {
 function handleExport() { proxy.download("hidd/objhidd/export", { ...queryParams }, `本单位工程隐患_${new Date().getTime()}.xlsx`) }
 function handleExport2() { proxy.download("hidd/objhidd/export", { ...queryParams2 }, `下级单位隐患_${new Date().getTime()}.xlsx`) }
 
+function handleReport() {
+  if (!ids.value.length) { proxy.$modal.msgWarning('请先选择要上报的隐患'); return }
+  proxy.$modal.confirm('确认上报选中的隐患?').then(() => {
+    reportHidd(ids.value).then(() => {
+      proxy.$modal.msgSuccess('上报成功')
+      getList()
+    })
+  }).catch(() => {})
+}
+function handleReport2() {
+  if (!ids2.value || !ids2.value.length) { proxy.$modal.msgWarning('请先选择要上报的隐患'); return }
+  proxy.$modal.confirm('确认逐级上报选中的隐患?').then(() => {
+    reportHidd(ids2.value).then(() => {
+      proxy.$modal.msgSuccess('上报成功')
+      getList2()
+    })
+  }).catch(() => {})
+}
+function handleReport3() {
+  if (!ids3.value.length) { proxy.$modal.msgWarning('请先选择要上报的隐患'); return }
+  proxy.$modal.confirm('确认上报选中的隐患?').then(() => {
+    reportHidd(ids3.value).then(() => {
+      proxy.$modal.msgSuccess('上报成功')
+      getList3()
+    })
+  }).catch(() => {})
+}
+function handleReport4() {
+  if (!ids4.value.length) { proxy.$modal.msgWarning('请先选择要上报的隐患'); return }
+  proxy.$modal.confirm('确认上报选中的隐患?').then(() => {
+    reportHidd(ids4.value).then(() => {
+      proxy.$modal.msgSuccess('上报成功')
+      getList4()
+    })
+  }).catch(() => {})
+}
+function handleReport5() {
+  if (!ids5.value.length) { proxy.$modal.msgWarning('请先选择要上报的隐患'); return }
+  proxy.$modal.confirm('确认上报选中的隐患?').then(() => {
+    reportHidd(ids5.value).then(() => {
+      proxy.$modal.msgSuccess('上报成功')
+      getList5()
+    })
+  }).catch(() => {})
+}
+
+const returnForm = ref({})
+const returnOpen = ref(false)
+function handleReturnFromSub() {
+  if (!ids2.value || !ids2.value.length) { proxy.$modal.msgWarning('请先选择要退回的隐患'); return }
+  returnForm.value = { guids: ids2.value, returnDesc: '' }
+  returnOpen.value = true
+}
+function submitReturn() {
+  if (!returnForm.value.returnDesc) { proxy.$modal.msgWarning('请填写退回说明'); return }
+  returnHidd(returnForm.value.guids, returnForm.value.returnDesc).then(() => {
+    proxy.$modal.msgSuccess('退回成功')
+    returnOpen.value = false
+    getList2()
+  })
+}
+
+const supDialogOpen = ref(false)
+const supDialogForm = ref({})
+function handleSupFromSub() {
+  if (!ids2.value || !ids2.value.length) { proxy.$modal.msgWarning('请先选择要督办的隐患'); return }
+  supDialogForm.value = { hiddGuids: ids2.value, hiddName: list2.value.find(r => ids2.value.includes(r.guid))?.hiddName || '', hiddGrad: list2.value.find(r => ids2.value.includes(r.guid))?.hiddGrad || '', proPart: list2.value.find(r => ids2.value.includes(r.guid))?.proPart || '', engName: list2.value.find(r => ids2.value.includes(r.guid))?.engName || '', supLareId: '', supDate: '', supWiunName: '', rectPeri: '', isList: '0', supOpin: '' }
+  supDialogOpen.value = true
+}
+function submitSupDialog() {
+  if (!supDialogForm.value.supOpin) { proxy.$modal.msgWarning('请填写督办意见'); return }
+  if (!supDialogForm.value.supLareId) { proxy.$modal.msgWarning('请填写督办文号'); return }
+  if (!supDialogForm.value.rectPeri) { proxy.$modal.msgWarning('请选择整改期限'); return }
+  const hiddGuid = supDialogForm.value.hiddGuids[0]
+  addBisMajHiddSup({ ...supDialogForm.value, hiddGuid }).then(() => {
+    proxy.$modal.msgSuccess('督办成功')
+    supDialogOpen.value = false
+    getList2()
+  })
+}
+
 function handleDelete(row) {
   const guids = row ? [row.guid] : ids.value
   if (!guids.length) { proxy.$modal.msgWarning('请先选择一条数据'); return }
@@ -779,13 +984,17 @@ function handleCancelApply(row) {
 function submitCancel() {
   cancelFormRef.value.validate(valid => {
     if (!valid) return
-    proxy.$modal.msgSuccess('销号申请已提交')
-    cancelOpen.value = false
+    applyWriteOffBisMajHiddSup({ guid: cancelForm.value.guid }).then(() => {
+      proxy.$modal.msgSuccess('销号申请已提交,等待上级审批')
+      cancelOpen.value = false
+      if (activeTab.value === 'bidEng') { getList3() } else if (activeTab.value === 'consEng') { getList4() } else if (activeTab.value === 'partEng') { getList5() } else { getList() }
+    }).catch(() => {})
   })
 }
 
 // Tab2-5 下级/标段/施工/参建
 const list2 = ref([]); const loading2 = ref(false); const total2 = ref(0)
+const ids2 = ref([])
 const queryParams2 = reactive({ pageNum: 1, pageSize: 10, hiddName: undefined, orgName: undefined })
 const list3 = ref([]); const loading3 = ref(false); const total3 = ref(0)
 const ids3 = ref([]); const single3 = ref(true); const multiple3 = ref(true)
@@ -807,8 +1016,11 @@ function getList4() {
 }
 function handleAdd4() {
   formTitle.value = '施工单位隐患新增'
-  form.value = { hiddSort: '1', hiddGrad: '1', hiddStat: '0', inspDate: '', inspLeader: '', inspLeaderPost: '', proPart: '', hiddDesc: '', engGuid: '', tendGuid: '', engName: '', tendName: '', orgName: '', orgGuid: userStore.orgGuid || '' }
+  form.value = { hiddSort: '1', 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 })) })
+  listAttOrgBase({ orgNature: '7' }).then(res => {
+    consOrgList.value = (res.rows || []).map(o => ({ value: o.guid, label: o.orgName }))
+  })
   fileAttachList.value = []
   uploadFileList.value = []
   formDrawer.value = true
@@ -838,7 +1050,7 @@ function handleQuery4() { queryParams4.pageNum = 1; getList4() }
 function handleExport4() { proxy.download("hidd/objhidd/export", { ...queryParams4, wiunProp: '7' }, `施工单位隐患_${new Date().getTime()}.xlsx`) }
 function getList2() {
   loading2.value = true
-  listObjHidd({ ...queryParams2, pageNum: queryParams2.pageNum, pageSize: queryParams2.pageSize }).then(res => {
+  listNextDepHidd({ ...queryParams2, pageNum: queryParams2.pageNum, pageSize: queryParams2.pageSize, orgGuid: userStore.orgGuid || undefined, hiddSort: '1' }).then(res => {
     list2.value = res.rows || []
     total2.value = res.total || 0
     loading2.value = false
@@ -846,7 +1058,7 @@ function getList2() {
 }
 function getList3() {
   loading3.value = true
-  listObjHidd({ ...queryParams3, pageNum: queryParams3.pageNum, pageSize: queryParams3.pageSize }).then(res => {
+  listObjHidd({ ...queryParams3, pageNum: queryParams3.pageNum, pageSize: queryParams3.pageSize, orgGuid: userStore.orgGuid || undefined, hiddSort: '1' }).then(res => {
     list3.value = res.rows || []
     total3.value = res.total || 0
     loading3.value = false
@@ -1010,6 +1222,11 @@ function submitRectify() {
     }
   })
   Promise.all([p1, p2, p3]).then(() => {
+    const completedRect = !!(rectAcceForm.value.requCompDate && rectAcceForm.value.accepLegPers)
+    const newHiddStat = completedRect ? '2' : '1'
+    if (rectifyRow.value.hiddStat !== newHiddStat) {
+      updateObjHidd({ guid: hiddGuid, hiddStat: newHiddStat }).catch(() => {})
+    }
     proxy.$modal.msgSuccess('保存成功')
     rectifyOpen.value = false
     rectifyLoading.value = false
@@ -1025,32 +1242,6 @@ function handleTabChange() {
   else if (activeTab.value === 'bidEng') getList3()
   else if (activeTab.value === 'consEng') getList4()
   else if (activeTab.value === 'partEng') getList5()
-  // 切换 tab 后重算表格高度,确保分页位置与本单位 tab 一致
-  setTimeout(() => {
-    const map = { selfEng: containerRef, subEng: containerRef2, bidEng: containerRef3, consEng: containerRef4, partEng: containerRef5 }
-    const el = map[activeTab.value]?.value
-    if (!el) return
-    const rect = el.getBoundingClientRect()
-    const ch = window.innerHeight - rect.top
-    if (ch <= 0) return
-    let used = 0
-    const cs = window.getComputedStyle(el)
-    used += parseFloat(cs.paddingTop) || 0
-    used += parseFloat(cs.paddingBottom) || 0
-    for (const child of el.children) {
-      if (child.classList?.contains('table-wrapper')) continue
-      if (child.classList?.contains('el-dialog')) continue
-      const oh = child.offsetHeight
-      if (oh === 0) {
-        if (child.classList?.contains('pagination-container')) used += 50
-        continue
-      }
-      const style = window.getComputedStyle(child)
-      used += oh + (parseFloat(style.marginTop) || 0) + (parseFloat(style.marginBottom) || 0)
-    }
-    const h = ch - used
-    if (h > 200) tableHeight.value = h
-  }, 50)
 }
 
 onMounted(() => { getList() })

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

@@ -4,8 +4,8 @@
       <el-form-item label="单位性质" prop="unitType">
         <el-select v-model="queryParams.unitType" placeholder="请选择" clearable style="width: 180px">
           <el-option label="直属单位" value="1" />
-          <el-option label="流域机构" value="2" />
-          <el-option label="下级水行政主管部门" value="3" />
+          <el-option label="下级水行政主管部门" value="2" />
+          <el-option label="流域机构" value="3" />
         </el-select>
       </el-form-item>
       <el-form-item label="单位名称" prop="orgName">

+ 13 - 7
gw-ui/src/views/slaj/hidd/supList.vue

@@ -58,9 +58,9 @@
           {{ formatDate(scope.row.collTime) }}
         </template>
       </el-table-column>
-      <el-table-column label="督办情况" align="center" prop="supStat" v-if="columns.supStat.visible" min-width="80">
+      <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="scope.row.supStat" />
+          <dict-tag :options="sup_stat" :value="supStatMap[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">
@@ -70,8 +70,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="scope.row.supStat === '0' && scope.row.hiddStat !== '2'" @click="handleSup(scope.row)" v-hasPermi="['hidd:majhiddsup:add']">督办</el-button>
-          <el-button link type="primary" v-if="scope.row.supStat === '2'" @click="handleWriteOff(scope.row)" v-hasPermi="['hidd:majhiddsup:edit']">销号</el-button>
+          <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" @click="handleDetail(scope.row)">详情</el-button>
         </template>
       </el-table-column>
@@ -160,7 +160,7 @@
                 :on-success="handleUploadSuccess"
                 :on-remove="handleUploadRemove"
                 :file-list="fileList"
-                :limit="1"
+                :limit="5"
               >
                 <el-button type="primary" size="small">选择附件</el-button>
               </el-upload>
@@ -249,7 +249,7 @@
 </template>
 
 <script setup name="BisMajHiddSup">
-import { listBisMajHiddSup, getBisMajHiddSup, addBisMajHiddSup, updateBisMajHiddSup, delBisMajHiddSup, writeOffBisMajHiddSup, cancelBisMajHiddSup, listBisHiddRectAcce } from "@/api/slaj/hidd"
+import { listBisMajHiddSup, getBisMajHiddSup, addBisMajHiddSup, updateBisMajHiddSup, delBisMajHiddSup, writeOffBisMajHiddSup, cancelBisMajHiddSup, listBisHiddRectAcce, approveWriteOffBisMajHiddSup } from "@/api/slaj/hidd"
 import { useTableHeight } from '@/hooks/useTableHeight'
 import { listObjHidd, getObjHidd } from "@/api/slaj/hidd"
 
@@ -284,6 +284,12 @@ const supRules = {
   rectPeri: [{ required: true, message: "请选择督办期限", trigger: "change" }]
 }
 
+const supStatMap = {
+  '已督办': '0',
+  '待销号': '2',
+  '已销号': '3'
+}
+
 const writeOffOpen = ref(false)
 const writeOffRow = ref({})
 
@@ -420,7 +426,7 @@ function handleWriteOff(row) {
 }
 
 function submitWriteOff() {
-  writeOffBisMajHiddSup({ guid: writeOffRow.value.guid }).then(response => {
+  approveWriteOffBisMajHiddSup({ hiddGuid: writeOffRow.value.hiddGuid, approved: true }).then(response => {
     proxy.$modal.msgSuccess("销号成功")
     writeOffOpen.value = false
     getList()