From da8dcef599d67dcc66742e53a872b45ead53b1ea Mon Sep 17 00:00:00 2001
From: 叶松 <2217086471@qq.com>
Date: 星期二, 10 十月 2023 16:36:56 +0800
Subject: [PATCH] Merge branch 'master' of http://111.30.93.211:10101/r/supipe

---
 web/src/views/SecureManage/RiskGrad/AreaGuarantee.vue                                                                    |  376 +++++++++++++++++
 web/src/views/ProjectManage/ProjectsIndex.vue                                                                            |   18 
 web/src/components/element/Table.vue                                                                                     |  151 ++++++
 hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/controller/TSteelNeedYearController.java    |   20 
 web/src/components/element/Pagination.vue                                                                                |   78 +++
 web/src/views/SecureManage/RiskGrad/DangerInform.vue                                                                     |  269 ++++++++++++
 hd/pipe/materialsManage/src/main/resources/mapping/TSteelNeedYearMapper.xml                                              |   72 +++
 web/src/views/ProjectManage/SectionManage.vue                                                                            |   61 +-
 web/src/plugins/directive.js                                                                                             |   13 
 web/src/style/layout-main.scss                                                                                           |    6 
 hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/TSteelNeedYearService.java          |    4 
 web/src/api/modules/safety.js                                                                                            |   28 +
 web/src/main.js                                                                                                          |    1 
 hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/mapper/TSteelNeedYearMapper.java            |   14 
 hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/impl/TSteelNeedYearServiceImpl.java |   26 +
 web/src/router/routerConfig.js                                                                                           |    4 
 web/package-lock.json                                                                                                    |  160 +++---
 17 files changed, 1,173 insertions(+), 128 deletions(-)

diff --git a/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/controller/TSteelNeedYearController.java b/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/controller/TSteelNeedYearController.java
index 2cda488..e3d3dc1 100644
--- a/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/controller/TSteelNeedYearController.java
+++ b/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/controller/TSteelNeedYearController.java
@@ -39,4 +39,24 @@
     public BasicResult needYearUpdate(@RequestBody Map<String,Object> values){
         return yearService.needYearUpdate(values);
     }
+
+    /**
+     * 钢筋笼生产计划-钢筋笼明细
+     * @param values
+     * @return
+     */
+    @PostMapping("/selectSteelInfo")
+    public BasicResult selectSteelInfo(@RequestBody Map<String,Object> values){
+        return yearService.selectSteelInfo(values);
+    }
+
+    /**
+     * 管片生产计划-管片明细
+     * @param values
+     * @return
+     */
+    @PostMapping("/selectPipeInfo")
+    public BasicResult selectPipeInfo(@RequestBody Map<String,Object> values){
+        return yearService.selectPipeInfo(values);
+    }
 }
diff --git a/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/mapper/TSteelNeedYearMapper.java b/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/mapper/TSteelNeedYearMapper.java
index d1affb9..c42bb9e 100644
--- a/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/mapper/TSteelNeedYearMapper.java
+++ b/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/mapper/TSteelNeedYearMapper.java
@@ -36,4 +36,18 @@
     List<Integer> needProSizePipe(@Param("proId") String proId,@Param("sizeId") String sizeId,@Param("reinforcementId") String reinforcementId,@Param("years") String years);
 
     List<TNeedNum> proIdAndHas(String proId);
+
+    /**
+     * 钢筋笼生产计划-钢筋笼明细
+     * @param map
+     * @return
+     */
+    List<Map<String,Object>> selectSteelInfo(Map<String,Object> map);
+
+    /**
+     * 钢筋笼生产计划-钢筋笼明细
+     * @param map
+     * @return
+     */
+    List<Map<String,Object>> selectPipeInfo(Map<String,Object> map);
 }
\ No newline at end of file
diff --git a/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/TSteelNeedYearService.java b/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/TSteelNeedYearService.java
index acec16d..4ff6562 100644
--- a/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/TSteelNeedYearService.java
+++ b/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/TSteelNeedYearService.java
@@ -14,4 +14,8 @@
     BasicResult needYearInfo(String steelNeedId);
 
     BasicResult needYearUpdate(Map<String, Object> values);
+
+    BasicResult selectSteelInfo(Map<String, Object> values);
+
+    BasicResult selectPipeInfo(Map<String, Object> values);
 }
diff --git a/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/impl/TSteelNeedYearServiceImpl.java b/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/impl/TSteelNeedYearServiceImpl.java
index e1fe3e1..06ae487 100644
--- a/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/impl/TSteelNeedYearServiceImpl.java
+++ b/hd/pipe/materialsManage/src/main/java/com/thhy/materials/modules/biz/concret/service/impl/TSteelNeedYearServiceImpl.java
@@ -192,4 +192,30 @@
         return BasicResult.success("修改成功");
     }
 
+    @Override
+    public BasicResult selectSteelInfo(Map<String, Object> values) {
+        SysUserInfo sysUserInfo = UserInfoUtils.getInstance().getUserInfo();
+        String companyId = sysUserInfo.getCompanyId();
+        values.put("companyId",companyId);
+        Integer pageSize = Integer.valueOf(values.get("pageSize").toString());
+        Integer pageNum = Integer.valueOf(values.get("pageNum").toString());
+        PageHelper.startPage(pageNum,pageSize);
+        List<Map<String, Object>> list = this.yearMapper.selectSteelInfo(values);
+        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(list);
+        return BasicResult.success(pageInfo);
+    }
+
+    @Override
+    public BasicResult selectPipeInfo(Map<String, Object> values) {
+        SysUserInfo sysUserInfo = UserInfoUtils.getInstance().getUserInfo();
+        String companyId = sysUserInfo.getCompanyId();
+        values.put("companyId",companyId);
+        Integer pageSize = Integer.valueOf(values.get("pageSize").toString());
+        Integer pageNum = Integer.valueOf(values.get("pageNum").toString());
+        PageHelper.startPage(pageNum,pageSize);
+        List<Map<String, Object>> list = this.yearMapper.selectPipeInfo(values);
+        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(list);
+        return BasicResult.success(pageInfo);
+    }
+
 }
diff --git a/hd/pipe/materialsManage/src/main/resources/mapping/TSteelNeedYearMapper.xml b/hd/pipe/materialsManage/src/main/resources/mapping/TSteelNeedYearMapper.xml
index 5ca7a4c..36bd77e 100644
--- a/hd/pipe/materialsManage/src/main/resources/mapping/TSteelNeedYearMapper.xml
+++ b/hd/pipe/materialsManage/src/main/resources/mapping/TSteelNeedYearMapper.xml
@@ -232,4 +232,76 @@
 	and print_time like concat('%',#{years},'%')
 	GROUP BY block_num
   </select>
+
+  <select id="selectSteelInfo" resultType="java.util.Map" parameterType="java.util.Map">
+    SELECT
+            tsp.produce_number produceNumber,
+            sp.pro_name proName,
+            sd1.dict_name sizeName,
+            sd2.dict_name reinforcementName,
+            sd3.dict_name blockName,
+            tsp.quality_time,
+            su1.real_name checkName,
+            su2.real_name createUser,
+            CASE tsp.is_qualified
+                    WHEN  1 THEN '合格'
+                    WHEN  2 THEN '不合格'
+                    END isQualified,
+            CASE tsp.is_model
+                    WHEN  1 THEN '入模'
+                    WHEN  2 THEN '未入模'
+                    END isModel,
+            IFNULL(sg.group_name,'无') groupName
+    FROM t_steel_produce tsp
+                 LEFT JOIN sys_project sp ON sp.pro_id = tsp.pro_id
+                 LEFT JOIN sys_dict sd1 ON sd1.dict_id = tsp.size_id
+                 LEFT JOIN sys_dict sd2 ON sd2.dict_id = tsp.reinforcement_id
+                 LEFT JOIN sys_dict sd3 ON sd3.dict_id = tsp.block_num
+                 LEFT JOIN sys_users su1 ON su1.user_id = tsp.quality_user
+                 LEFT JOIN sys_users su2 ON su2.user_id = tsp.create_user
+                 LEFT JOIN sys_group_user sgu ON sgu.user_id = tsp.create_user
+                 LEFT JOIN sys_group sg ON sg.group_id = sgu.group_id
+    WHERE
+            tsp.is_use = 1
+      AND tsp.is_qualified = 1
+      AND tsp.reinforcement_id = #{reinforcementId}
+      AND tsp.pro_id = #{proId}
+      AND tsp.size_id = #{sizeId}
+      AND tsp.print_time like concat(#{years},'%')
+      AND sp.company_id=#{companyId}
+  </select>
+    <select id="selectPipeInfo" resultType="java.util.Map" parameterType="java.util.Map">
+        SELECT
+                tpi.ring_num,
+                tpi.pipe_num,
+                sd1.dict_name turn,
+                sd2.dict_name reinforcement,
+                sd3.dict_name groutingHoles,
+                sd4.dict_name blockNum,
+                sm.mould_num mouldNum,
+                tpi.into_mod_time intoModTime,
+                IFNULL(tpi.pouring_time,' ') pouringTime,
+                tpi.check_time checkTime,
+                IFNULL(sg.group_name,'无') groupName,
+                sp.pro_name,
+                CASE tpi.check_result
+                        WHEN  1 THEN '合格'
+                        WHEN  2 THEN '不合格'
+                        END checkResult
+        FROM t_pipe_info tpi
+                     LEFT JOIN sys_project sp ON sp.pro_id = tpi.pro_id
+                     LEFT JOIN sys_group_user sgu ON sgu.user_id = tpi.check_user
+                     LEFT JOIN sys_group sg ON sg.group_id = sgu.group_id
+                     LEFT JOIN sys_dict sd1 ON sd1.dict_id = tpi.turn
+                     LEFT JOIN sys_dict sd2 ON sd2.dict_id = tpi.reinforcement
+                     LEFT JOIN sys_dict sd3 ON sd3.dict_id = tpi.grouting_holes
+                     LEFT JOIN sys_dict sd4 ON sd4.dict_id = tpi.block_num
+                     LEFT JOIN sys_mould sm ON sm.mould_id = tpi.mod_id
+        WHERE
+          tpi.check_result = 1
+          AND sp.pro_id = #{proId}
+          AND tpi.size= #{sizeId}
+          AND tpi.check_time like concat(#{yearAndMonth},'%')
+          AND sp.company_id=#{companyId}
+    </select>
 </mapper>
\ No newline at end of file
diff --git a/web/package-lock.json b/web/package-lock.json
index 301fe1f..c1c1899 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -1932,63 +1932,6 @@
           "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
           "dev": true
         },
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-          "dev": true,
-          "optional": true
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "loader-utils": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
-          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
         "ssri": {
           "version": "8.0.1",
           "resolved": "https://registry.npmmirror.com/ssri/-/ssri-8.0.1.tgz",
@@ -1996,28 +1939,6 @@
           "dev": true,
           "requires": {
             "minipass": "^3.1.1"
-          }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        },
-        "vue-loader-v16": {
-          "version": "npm:vue-loader@16.8.3",
-          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
-          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "chalk": "^4.1.0",
-            "hash-sum": "^2.0.0",
-            "loader-utils": "^2.0.0"
           }
         }
       }
@@ -12830,6 +12751,87 @@
         }
       }
     },
+    "vue-loader-v16": {
+      "version": "npm:vue-loader@16.8.3",
+      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
+      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
+      "dev": true,
+      "optional": true,
+      "requires": {
+        "chalk": "^4.1.0",
+        "hash-sum": "^2.0.0",
+        "loader-utils": "^2.0.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true,
+          "optional": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "loader-utils": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        }
+      }
+    },
     "vue-router": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.1.3.tgz",
diff --git a/web/src/api/modules/safety.js b/web/src/api/modules/safety.js
index 8998857..637f94b 100644
--- a/web/src/api/modules/safety.js
+++ b/web/src/api/modules/safety.js
@@ -207,4 +207,32 @@
   // 信息删除
   deletePunishInfo: params =>
     axios.post('/secure/encourage/encourageDel', params),
+
+  /**
+  * 风险分级管控
+  */
+  RiskGrad: {
+    // 危险源告知
+    warning : {
+      getLists: params =>
+        axios.post('/secure/regionHazardInform/findAll', params),
+      insert: params =>
+        axios.post('/secure/regionHazardInform/insert', params),
+      update: params =>
+        axios.post('/secure/regionHazardInform/update', params),
+      delete: params =>
+        axios.get('/secure/regionHazardInform/delete', { params }),
+    },
+    // 区域包保
+    allocation : {
+      getLists: params =>
+        axios.post('/secure/tRegionWarranty/findAll', params),
+      insert: params =>
+        axios.post('/secure/tRegionWarranty/insert', params),
+      update: params =>
+        axios.post('/secure/tRegionWarranty/update', params),
+      delete: params =>
+        axios.get('/secure/tRegionWarranty/delete', { params }),
+    }
+  }
 }
\ No newline at end of file
diff --git a/web/src/components/element/Pagination.vue b/web/src/components/element/Pagination.vue
new file mode 100644
index 0000000..46cfa39
--- /dev/null
+++ b/web/src/components/element/Pagination.vue
@@ -0,0 +1,78 @@
+<template>
+  <div class="pagination-container">
+    <el-pagination @current-change="handleCurrentChange" @size-change="handleSizeChange" :page-sizes="[10, 20, 30]"
+      :total="total" :current-page="pageNum" :page-size="pageSize"
+      layout="total, sizes, prev, pager, next, jumper"></el-pagination>
+  </div>
+</template>
+<script>
+export default {
+  name: "pagination",
+  data() {
+    return {};
+  },
+  props: {
+    // 总页数
+    total: {
+      type: Number,
+    },
+    // 当前页
+    pageNum: {
+      type: Number,
+    },
+    // 每页显示条数
+    pageSize: {
+      type: Number,
+    },
+  },
+  methods: {
+    // 当前页码变化
+    handleCurrentChange(val) {
+      this.$emit("change-page-num", val);
+    },
+    //  每页查看条数变化
+    handleSizeChange(val) {
+      this.$emit("change-page-size", val);
+    },
+  },
+  // watch: {
+  //   pageSize: {
+  //     // immediate: true,
+  //     handler(newValue, oldValue) {
+  //       this.page._pageSize = this.newValue;
+  //       console.log("pageSize", newValue, oldValue);
+  //     },
+  //   },
+  //   pageNum: {
+  //     // immediate: true,
+  //     handler(newValue, oldValue) {
+  //       this.page._currentPage = newValue;
+  //       console.log("pageNum", newValue, oldValue);
+  //     },
+  //   },
+  // },
+};
+</script>
+<style lang="scss" scoped>
+// 主体底部样式
+::v-deep.el-pagination .btn-prev,
+::v-deep.el-pagination .btn-next,
+::v-deep.el-pagination .el-pager li {
+  background-color: rgba(20, 25, 58, 0.4);
+  border: 1px solid rgba(255, 255, 255, 0.12);
+  font-weight: 400;
+  color: #E2E4E9;
+  border-radius: 4px;
+}
+
+::v-deep.el-pagination .el-pager li:not(.disabled).active {
+  color: #fff;
+  border: 1px solid #39B5FE;
+  background-color: #0B3562;
+  font-weight: 400;
+}
+
+.pagination-container {
+  margin-top: 30px;
+}
+</style>
\ No newline at end of file
diff --git a/web/src/components/element/Table.vue b/web/src/components/element/Table.vue
new file mode 100644
index 0000000..b266c54
--- /dev/null
+++ b/web/src/components/element/Table.vue
@@ -0,0 +1,151 @@
+<template>
+  <div>
+    <!-- elTable -->
+    <el-table v-loading="tableLoading" :data="tableData" :ref="tableRef" :size="tableSize" @row-click="rowClick"
+      @row-dblclick="rowDblClick" @selection-change="handleSelectionChange" border stripe>
+      <template v-for="(col, index) in tableColumns">
+        <!-- 选择框 -->
+        <el-table-column v-if="col.selection" :key="`selection${index}`" width="50" type="selection" align="center">
+        </el-table-column>
+
+        <!-- 序号 -->
+        <el-table-column v-else-if="col.index" :key="`index${index}`" width="50" :label="col.name || '序号'" type="index"
+          align="center">
+        </el-table-column>
+
+        <!-- 操作 -->
+        <el-table-column v-else-if="col.operation" :key="`operation${col.name}`" :width="col.width" :label="col.name"
+          align="center">
+          <template #default="{ row }">
+            <el-button v-for="subCol in col.value" :key="subCol.name" :class="subCol.class || ''" :icon="subCol.icon || ''"
+              v-permission="subCol.permission || ''" @click="subCol.handleRow ? subCol.handleRow(row) : emptyFn">
+              {{ subCol.name }}
+            </el-button>
+          </template>
+        </el-table-column>
+
+        <!-- 常规col -->
+        <el-table-column v-else :key="col.name" :width="col.width" :label="col.name" :prop="col.key"
+          :show-overflow-tooltip="col.showOverflowTip || false" :align="col.align || 'center'">
+          <template #default="{ row }">
+            <!-- slotのcol -->
+            <template v-if="col.slot">
+              <slot :name="col.slot" :row="row"></slot>
+            </template>
+            <!-- 需处理数据のcol -->
+            <template v-else-if="col.formatter">
+              {{ col.formatter(row) }}
+            </template>
+            <!-- 普通のcol -->
+            <template v-else>
+              {{ row[col.key] }}
+            </template>
+          </template>
+        </el-table-column>
+      </template>
+    </el-table>
+    <!-- 分页组件 -->
+    <cPagination :total="pageTotal" :page-num.sync="pageNum" :page-size.sync="pageSize" @change-page-num="changePageNum"
+      @change-page-size="changePageSize" />
+  </div>
+</template>
+<script>
+import cPagination from "./Pagination"
+export default {
+  name: "cTable",
+  data() {
+    return {
+      time: null,
+      emptyFn: () => { }
+    };
+  },
+  props: {
+    tableData: {
+      type: Array,
+      default() {
+        return [];
+      }
+    },
+    tableHeight: {
+      type: Number,
+      default: null
+    },
+    tableLoading: {
+      type: Boolean,
+      default: false
+    },
+    tableRef: {
+      type: String,
+      default: "multipleTable"
+    },
+    tableSize: {
+      type: String,
+      default: "mini"
+    },
+    tableColumns: {
+      type: Array,
+      default() {
+        return [];
+      }
+    },
+    pageTotal: {
+      type: Number
+    },
+    pageNum: {
+      type: Number,
+      default: 1
+    },
+    pageSize: {
+      type: Number,
+      default: 10
+    },
+    pageChange: {
+      type: Function,
+      default: () => { }
+    },
+    handleSelection: {
+      type: Function,
+      default: () => { }
+    }
+  },
+  components: {
+    cPagination
+  },
+  methods: {
+    changePageNum(val) {
+      // console.log(val)
+      // this.pageNum = val
+      this.$emit("update:pageNum", val);
+      this.pageChange();
+    },
+    changePageSize(val) {
+      this.$emit("update:pageSize", val);
+      if (val * (this.pageNum - 1) <= this.pageTotal) {
+        this.pageChange();
+      }
+    },
+    // 单击
+    rowClick() {
+      // this.time && clearTimeout(this.time);
+      // this.time = setTimeout(() => {
+      //   this.$refs[this.tableRef].toggleRowSelection(row);
+      // }, 200);
+    },
+    // 双击
+    rowDblClick() {
+      // this.time && clearTimeout(this.time);
+    },
+    clearSelection() {
+      this.$refs[this.tableRef].clearSelection();
+    },
+    handleSelectionChange(val) {
+      this.handleSelection(val);
+    }
+  }
+};
+</script>
+<style lang="scss" scoped>
+.el-table {
+  border: none;
+}
+</style>
\ No newline at end of file
diff --git a/web/src/main.js b/web/src/main.js
index f596b68..174925e 100644
--- a/web/src/main.js
+++ b/web/src/main.js
@@ -7,6 +7,7 @@
 // import './style/element-variables.scss'
 import "@/style/font/font.scss";
 import './plugins/index'; // 引入挂载的vue实例方法文件
+import './plugins/directive' // 全局指令:按钮权限
 import { createPinia, PiniaVuePlugin } from 'pinia';
 import './router/routerConfig'; // 引入路由守卫
 import App from './App.vue';
diff --git a/web/src/plugins/directive.js b/web/src/plugins/directive.js
new file mode 100644
index 0000000..08742f4
--- /dev/null
+++ b/web/src/plugins/directive.js
@@ -0,0 +1,13 @@
+import Vue from 'vue'
+import { buttonPinia } from '@/pinia/index'
+
+Vue.directive('permission', {
+  inserted: (el, binding) => {
+    const { value } = binding
+    const pinia = buttonPinia()
+    const piniaBtns = pinia.$state.buttonInfo
+    if (value && !piniaBtns.includes(value)) {
+      el.parentNode.removeChild(el)
+    }
+  }
+})
diff --git a/web/src/router/routerConfig.js b/web/src/router/routerConfig.js
index 82aa1bd..e7408a9 100644
--- a/web/src/router/routerConfig.js
+++ b/web/src/router/routerConfig.js
@@ -67,9 +67,11 @@
         let list = res.data.map(item => item.buttonHtmlId)
         pinia.changeMenuButtonInfo(list);
       }
+      next()
     })
+  } else {
+    next()
   }
-  next();
 })
 
 router.afterEach(() => {
diff --git a/web/src/style/layout-main.scss b/web/src/style/layout-main.scss
index 5ebc614..3eb82ea 100644
--- a/web/src/style/layout-main.scss
+++ b/web/src/style/layout-main.scss
@@ -81,7 +81,7 @@
     }
   }
 
-  .search_btn {
+  ::v-deep .search_btn {
     border: 0 none;
     color: #fff;
     background: url('~@/assets/search_bg.png') no-repeat;
@@ -91,7 +91,7 @@
     }
   }
 
-  .table_btn {
+  ::v-deep .table_btn {
     border: 0 none;
     color: #39B5FE;
     background: url('~@/assets/table_btn.png') no-repeat;
@@ -101,7 +101,7 @@
     }
   }
 
-  .delete_btn {
+  ::v-deep .delete_btn {
     border: 0 none;
     color: #F94550;
     background: url('~@/assets/error_btn.png') no-repeat;
diff --git a/web/src/views/ProjectManage/ProjectsIndex.vue b/web/src/views/ProjectManage/ProjectsIndex.vue
index 2c0d9cf..b164f44 100644
--- a/web/src/views/ProjectManage/ProjectsIndex.vue
+++ b/web/src/views/ProjectManage/ProjectsIndex.vue
@@ -4,7 +4,7 @@
     <!-- header-->
     <div class="main_header" style="flex-direction: row-reverse;">
       <div class="header_item" style="margin-right:0px">
-        <el-button class="search_btn" icon="el-icon-plus" v-if="showButton('insert')" @click="addRow">新增</el-button>
+        <el-button class="search_btn" icon="el-icon-plus" v-permission="'insert'" @click="addRow">新增</el-button>
       </div>
     </div>
     <!-- content-->
@@ -66,9 +66,8 @@
         <el-table-column prop="planOutput" label="总需求(环)" align="center"></el-table-column>
         <el-table-column label="操作" align="center" width="140">
           <template #default="scope">
-            <el-button class="table_btn" size="mini" v-if="showButton('stop')"
-              @click="deleteRow(scope.row)">停用</el-button>
-            <el-button class="delete_btn" size="mini" v-if="showButton('update')"
+            <el-button class="table_btn" size="mini" v-permission="'stop'" @click="deleteRow(scope.row)">停用</el-button>
+            <el-button class="delete_btn" size="mini" v-permission="'update'"
               @click="updateRow(scope.$index)">修改</el-button>
           </template>
         </el-table-column>
@@ -177,7 +176,7 @@
     <!-- detail dialog -->
     <el-dialog class="prop_dialog" v-if="detail.isRenderDetail" title="管片数量" :visible.sync="detail.asyncVisible"
       width="800px">
-      <cpnTable :table-index="true" :table-data="detail.tableData" :table-columns-config="detail.tableColumns"
+      <cpnTable :table-index="true" :table-data="detail.tableData" :table-columns="detail.tableColumns"
         :page-total="detail.total" :page-num.sync="detail.pageNum" :page-size.sync="detail.pageSize"
         :page-change="pageChange">
       </cpnTable>
@@ -186,9 +185,8 @@
 </template>
 
 <script>
-import {buttonPinia} from '../../pinia/index';
 import {throttle} from '../../plugins/public'; // 导入节流、动态切换组件尺寸方法
-import cpnTable from '@/components/table/Table'
+import cpnTable from '@/components/element/Table'
 export default {
   data() {
     return {
@@ -433,11 +431,6 @@
         }
       })
     }, 1000),
-    // 判断按钮权限信息
-    showButton(str) {
-      const pinia = buttonPinia();
-      return pinia.$state.buttonInfo.includes(str);
-    },
     changePageNum(page) {
       this.queryInfo.pageNum = page;
       this.getLists();
@@ -466,7 +459,6 @@
           if (!detailData.tableColumns.length) {
             detailData.tableColumns = [
               {index: true},
-              {slot: "name"},
               {name: "环号", key: "ringNum"},
               {name: "管片编号", key: "pipeNum", width: 140},
               {name: "转向", key: "turnName", width: 106},
diff --git a/web/src/views/ProjectManage/SectionManage.vue b/web/src/views/ProjectManage/SectionManage.vue
index f29dffd..09e277f 100644
--- a/web/src/views/ProjectManage/SectionManage.vue
+++ b/web/src/views/ProjectManage/SectionManage.vue
@@ -14,24 +14,17 @@
         </el-select>
       </div>
       <div class="header_item">
-        <el-button icon="el-icon-search" v-if="showButton('search')" @click="queryReset">查询</el-button>
-        <el-button class="search_btn" icon="el-icon-plus" v-if="showButton('insert')" @click="addRow">新增</el-button>
+        <el-button icon="el-icon-search" v-permission="'search'" @click="queryReset">查询</el-button>
+        <el-button class="search_btn" icon="el-icon-plus" v-permission="'insert'" @click="addRow">新增</el-button>
       </div>
     </div>
     <div class="main_content">
-      <cpnTable :table-index="true" :table-data="dataList" :table-columns-config="tableColumns" :page-total="total"
+      <cpnTable :table-index="true" :table-data="dataList" :table-columns="tableColumns" :page-total="total"
         :page-num.sync="queryInfo.pageNum" :page-size.sync="queryInfo.pageSize" :page-change="pageChange">
-        <el-table-column slot="finished" label="已完成(块)" align="center">
-          <template #default="{ row }">
-            <div style="cursor: pointer;" @click="showDetail(row)">{{ row.completedQuantity }}</div>
-          </template>
-        </el-table-column>
-        <el-table-column slot="action" label="操作" width="140" align="center">
-          <template #default="{ row }">
-            <el-button class="table_btn" size="mini" v-if="showButton('update')" @click="updateRow(row)">修改</el-button>
-            <el-button class="delete_btn" size="mini" v-if="showButton('delete')" @click="deleteRow(row)">删除</el-button>
-          </template>
-        </el-table-column>
+
+        <template #finished="{ row }">
+          <div style="cursor: pointer;" @click="showDetail(row)">{{ row.completedQuantity }}</div>
+        </template>
       </cpnTable>
     </div>
     <!-- dialog -->
@@ -105,7 +98,7 @@
           </template>
         </div>
       </el-card>
-      <cpnTable :table-index="true" :table-data="detail.tableData" :table-columns-config="detail.tableColumns"
+      <cpnTable :table-index="true" :table-data="detail.tableData" :table-columns="detail.tableColumns"
         :page-total="detail.total" :page-num.sync="detail.pageNum" :page-size.sync="detail.pageSize"
         :page-change="detailPageChange">
       </cpnTable>
@@ -114,9 +107,8 @@
 </template>
 
 <script>
-import {buttonPinia} from '../../pinia/index';
 import {throttle} from '../../plugins/public'; // 导入节流、动态切换组件尺寸方法
-import cpnTable from '@/components/table/Table'
+import cpnTable from '@/components/element/Table'
 export default {
   data() {
     return {
@@ -206,11 +198,11 @@
     cpnTable
   },
   computed: {
-    dialogTitle() {
-      return this.submitMode === 'update' ? '修改新增单位工程' : '新增单位工程'
-    },
     isUpdate() {
       return this.submitMode === 'update'
+    },
+    dialogTitle() {
+      return this.isUpdate ? '修改新增单位工程' : '新增单位工程'
     },
   },
   created() {
@@ -222,6 +214,7 @@
     // this.getAllBlocks() // 暂时没用,先屏蔽
   },
   methods: {
+    // 获取table列表数据
     getLists() {
       this.loading = true
       let params = this.queryInfo
@@ -282,6 +275,7 @@
         }
       })
     },
+    // 已完成 table信息
     getDetailLists() {
       let detailData = this.detail
       this.$api.DuctpiecePLM.searchDuctpiecePLMList({
@@ -295,6 +289,7 @@
         }
       })
     },
+    // 已完成 title信息
     getDetailInfos(id) {
       this.$api.Engineer.detailsProjects({proId: id}).then(res => {
         if (res.success) {
@@ -302,6 +297,7 @@
         }
       })
     },
+    // 初始化 ruleform
     setFormProps(options = {}) {
       let _form = {
         proId: '', // 项目名称id
@@ -317,10 +313,11 @@
       }
       this.ruleForm = Object.keys(options).length ? options : _form
     },
+    // 初始化 table 配置
     setTableColumn() {
       this.tableColumns = [
         {index: true},
-        {slot: "finished"},
+        {slot: "finished", name: "已完成(块)"},
         {name: "项目名称", key: "proName", width: 160},
         {name: "起讫里程", key: "mileage"},
         {name: "单位工程名称", key: "unitProjectName"},
@@ -330,11 +327,15 @@
         {name: "工期", key: "duration"},
         {name: "站点", key: "station"},
         {name: "负责人", key: "realName"},
-        {slot: 'action'},
+        {
+          operation: true, name: "操作", width: 140, value: [
+            {name: "修改", class: "table_btn", permission: "update", handleRow: this.updateRow},
+            {name: "删除", class: "delete_btn", permission: "delete", handleRow: this.deleteRow},
+          ]
+        },
       ]
       this.detail.tableColumns = [
         {index: true},
-        {slot: "name"},
         {name: "环号", key: "ringNum"},
         {name: "管片编号", key: "pipeNum", width: 140},
         {name: "转向", key: "turnName", width: 106},
@@ -350,13 +351,16 @@
         {name: "质量标注", key: "checkResultStr"},
       ]
     },
+    // 重置表单
     resetForm(formName) {
       this.$refs[formName].resetFields()
     },
+    // 显示表单
     showForm() {
       !this.isRender && (this.isRender = true)
       this.asyncVisible = true
     },
+    // 隐藏表单
     closeForm() {
       this.asyncVisible = false
       this.resetForm('ruleForm')
@@ -368,10 +372,12 @@
       this.queryInfo.pageSize = 10
       this.getLists()
     },
+    // 添加数据
     addRow() {
       this.submitMode = 'add'
       this.showForm()
     },
+    // 更新数据
     async updateRow(row) {
       this.submitMode = 'update'
       this.showForm()
@@ -384,6 +390,7 @@
       this.ruleForm.segmentId = row.segmentId
       this.ruleForm.segmentList = segmentList
     },
+    // 删除数据
     deleteRow(row) {
       this.$confirm("该操作将删除该信息,是否继续删除?", "提示", {
         confirmButtonText: "确定",
@@ -433,6 +440,7 @@
         }
       })
     },
+    // 提交表单
     onSubmit: throttle(function () {
       this.$refs.ruleForm.validate(valid => {
         if (!valid) return
@@ -462,11 +470,6 @@
         }
       })
     }, 1000),
-    // 判断按钮权限信息
-    showButton(str) {
-      const pinia = buttonPinia();
-      return pinia.$state.buttonInfo.includes(str);
-    },
     showDetail(row) {
       let detailData = this.detail
       !detailData.isRenderDetail && (detailData.isRenderDetail = true)
@@ -478,9 +481,11 @@
       this.getDetailInfos(row.proId)
       this.getDetailLists()
     },
+    // 分页改变
     pageChange() {
       this.getLists();
     },
+    // 已完成の分页改变
     detailPageChange() {
       this.getDetailLists();
     },
diff --git a/web/src/views/SecureManage/RiskGrad/AreaGuarantee.vue b/web/src/views/SecureManage/RiskGrad/AreaGuarantee.vue
index 609ac44..24c03e1 100644
--- a/web/src/views/SecureManage/RiskGrad/AreaGuarantee.vue
+++ b/web/src/views/SecureManage/RiskGrad/AreaGuarantee.vue
@@ -1,3 +1,375 @@
 <template>
-    <div>区域包保</div>
-</template>
\ No newline at end of file
+    <!-- 安全管理 ==> 风险分级管控 => 区域包保-->
+    <div class="main">
+        <!-- header -->
+        <div class="main_header">
+            <div class="header_item">
+                <span class="header_label">区域名称:</span>
+                <el-select v-model="queryInfo.regionHazardInformId" clearable placeholder="请选择域名称">
+                    <el-option v-for="item in areaNames" :key="item.id" :label="item.region" :value="item.id">
+                    </el-option>
+                </el-select>
+            </div>
+            <div class="header_item">
+                <el-button icon="el-icon-search" v-permission="'search'" @click="queryReset">查询</el-button>
+                <el-button class="search_btn" icon="el-icon-plus" v-permission="'insert'" @click="addRow">新增</el-button>
+            </div>
+        </div>
+
+        <!-- table -->
+        <div class="main_content">
+            <cpnTable :table-index="true" :table-data="dataList" :table-columns="tableColumns" :page-total="total"
+                :page-num.sync="queryInfo.pageNum" :page-size.sync="queryInfo.pageSize" :page-change="pageChange">
+            </cpnTable>
+        </div>
+
+        <!-- dialog -->
+        <el-dialog class="prop_dialog" v-if="isRender" :title="dialogTitle" :visible.sync="asyncVisible" @close="closeForm">
+            <el-form ref="ruleForm" :model="ruleForm" :rules="rules" label-width="auto" class="rule_form">
+                <el-form-item label="区域名称:" prop="regionHazardInformId">
+                    <el-select v-model="ruleForm.regionHazardInformId" placeholder="请选择区域名称">
+                        <el-option v-for="item in areaNames" :key="item.id" :label="item.region" :value="item.id">
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+
+                <el-form-item label="包保领导:" prop="leader">
+                    <el-select v-model="ruleForm.leader" filterable multiple placeholder="请选择包保领导">
+                        <el-option v-for="item in allPersons" :key="item.key" :label="item.label" :value="item.key">
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+
+                <el-form-item label="小组成员:" prop="staff">
+                    <el-transfer ref="transfer" v-model="ruleForm.staff" filterable :filter-method="filterMethod"
+                        filter-placeholder="请输入员工姓名" :titles="['未选择', '已选择']" :data="allPersons">
+                    </el-transfer>
+                </el-form-item>
+
+                <el-form-item label="风险源情况:" prop="riskSourceSituation">
+                    <el-input type="textarea" v-model="ruleForm.riskSourceSituation" clearable placeholder="请输入风险源情况">
+                    </el-input>
+                </el-form-item>
+
+                <el-form-item label="应对措施:" prop="countermeasures">
+                    <el-input type="textarea" v-model="ruleForm.countermeasures" clearable placeholder="请输入应对措施">
+                    </el-input>
+                </el-form-item>
+            </el-form>
+            <div slot="footer">
+                <el-button @click="asyncVisible = false">取 消</el-button>
+                <el-button class="submit_btn" @click="onSubmit('ruleForm')">提 交</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+  
+<script>
+import {throttle} from '@/plugins/public'; // 导入节流、动态切换组件尺寸方法
+import cpnTable from '@/components/element/Table'
+export default {
+    data() {
+        return {
+            isRender: false,
+            loading: false,
+            asyncVisible: false,
+            submitMode: '', // add update
+            total: 0,
+            queryInfo: {
+                pageNum: 1,
+                pageSize: 10,
+                regionHazardInformId: '',
+            },
+            areaNames: [], // 区域名称
+            allPersons: [], // 所有人员渲染数据.穿梭框和选择框一起使用.
+            dataList: [], // table渲染数据
+            tableColumns: [], // table配置
+            ruleForm: {}, // 按钮表单
+            rules: {
+                regionHazardInformId: [{required: true, message: '请选择区域名称', trigger: 'change'}],
+                leader: [{required: true, message: '请选择包保领导', trigger: 'change'}],
+                staff: [{required: true, message: '请选择小组成员', trigger: 'blur'}],
+                riskSourceSituation: [{required: true, message: '请输入风险源情况', trigger: 'blur'}],
+                countermeasures: [{required: true, message: '请输入应对措施', trigger: 'blur'}],
+            },
+            $http: '', // api路径赋值
+        }
+    },
+    components: {
+        cpnTable
+    },
+    computed: {
+        isUpdate() {
+            return this.submitMode === 'update'
+        },
+        dialogTitle() {
+            return this.isUpdate ? '修改区域' : '新增区域'
+        },
+    },
+    created() {
+        this.$http = this.$api.Safety.RiskGrad.allocation
+        this.setFormProps()
+        this.setTableColumn()
+        this.getLists()
+        this.getAreaName()
+    },
+    methods: {
+        // 获取table列表数据
+        getLists() {
+            this.loading = true
+            let params = this.queryInfo
+            this.$http.getLists(params).then(res => {
+                if (res.statusMsg === 'ok') {
+                    this.total = res.data.total
+                    this.dataList = res.data.list
+                }
+                this.loading = false
+            })
+        },
+        // 获取管服人员数据...showDialog时调用
+        getPerson() {
+            this.getPerson = this.runOnce(() => {
+                return new Promise(resolve => {
+                    this.$api.Personnerl.SEARCHMORTGAGEELIST({
+                        userType: 1,
+                        pageNum: 1,
+                        pageSize: 9999
+                    }).then((res) => {
+                        if (res.success) {
+                            const list = res.data.list
+                            const out = []
+                            list.forEach(item => {
+                                out.push({
+                                    label: item.realName, // 穿梭框规定字段, 可绑定props属性修改默认规定的字段.
+                                    key: item.userId, // 穿梭框规定使字段
+                                })
+                            })
+                            this.allPersons = out
+                            resolve()
+                        }
+                    })
+                })
+            })
+            return this.getPerson()
+        },
+        // 获取区域信息
+        getAreaName() {
+            this.$api.Safety.RiskGrad.warning.getLists({
+                pageNum: 1,
+                pageSize: 9999
+            }).then((res) => {
+                if (res.success) {
+                    const list = res.data.list
+                    const out = []
+                    list.forEach(item => {
+                        out.push({
+                            id: item.id,
+                            region: item.region,
+                        })
+                    })
+                    this.areaNames = out
+                }
+            })
+        },
+        // 初始化 ruleform
+        setFormProps(options = {}) {
+            let _form = {
+                regionHazardInformId: '', // 区域名称id
+                leader: [],  // 包保领导
+                staff: [],  // 小组成员
+                riskSourceSituation: '', // 风险源情况
+                countermeasures: '',  // 应对措施
+            }
+            this.ruleForm = Object.keys(options).length ? options : _form
+        },
+        // 初始化 table 配置
+        setTableColumn() {
+            this.tableColumns = [
+                {index: true},
+                {
+                    name: "区域名称", key: "regionHazardInformId", formatter: (row) => {
+                        return row.region
+                    }
+                },
+                {
+                    name: "包保领导", key: "leaderList", formatter: (row) => {
+                        let el = ''
+                        row.leaderList.forEach(item => {
+                            el += item.realName + '、'
+                        })
+                        return el
+                    }
+                },
+                {
+                    name: "小组成员", key: "staffList", formatter: (row) => {
+                        let el = ''
+                        row.staffList.forEach(item => {
+                            el += item.realName + '、'
+                        })
+                        return el
+                    }
+                },
+                {name: "风险源情况", key: "riskSourceSituation"},
+                {name: "应对措施", key: "countermeasures"},
+                {
+                    operation: true, name: "操作", width: 140, value: [
+                        {name: "修改", class: "table_btn", permission: "update", handleRow: this.updateRow},
+                        {name: "删除", class: "delete_btn", permission: "delete", handleRow: this.deleteRow},
+                    ]
+                },
+            ]
+        },
+        runOnce(fn, context) { //控制让函数只触发一次
+            return () => {
+                if (!fn) return
+                try {
+                    return fn.apply(context || this, arguments)
+                }
+                finally {
+                    fn = null
+                }
+            }
+        },
+        // 穿梭框搜索关键字变化时触发
+        filterMethod(query, item) {
+            return item.label.indexOf(query) > -1
+        },
+        // 重置表单
+        resetForm(formName) {
+            this.$refs[formName].resetFields()
+        },
+        // 重置穿梭框选中状态
+        resetTransfer(transferName) {
+            this.$refs[transferName].$refs.leftPanel.checked = []
+            this.$refs[transferName].$refs.rightPanel.checked = []
+        },
+        // 显示表单
+        async showForm() {
+            !this.isRender && (this.isRender = true)
+            this.asyncVisible = true
+            await this.getPerson()
+        },
+        // 隐藏表单
+        closeForm() {
+            this.asyncVisible = false
+            this.resetForm('ruleForm')
+            this.resetTransfer('transfer')
+        },
+        // 查询按钮列表信息
+        queryReset() {
+            this.queryInfo.pageNum = 1
+            this.queryInfo.pageSize = 10
+            this.getLists()
+        },
+        // 添加数据
+        addRow() {
+            this.submitMode = 'add'
+            this.showForm()
+        },
+        // 更新数据
+        async updateRow(row) {
+            this.submitMode = 'update'
+            await this.showForm()
+            this.$nextTick(() => {
+                this.ruleForm.id = ''
+                const strongObj = {
+                    staff: [],
+                    leader: [],
+                }
+                row.staffList.forEach(item => {
+                    strongObj.staff.push(item.userId)
+                })
+                row.leaderList.forEach(item => {
+                    strongObj.leader.push(item.userId)
+                })
+                Object.keys(this.ruleForm).forEach(item => {
+                    if (row.hasOwnProperty.call(row, item)) {
+                        this.ruleForm[item] = strongObj[item] || row[item]
+                    }
+                })
+            })
+        },
+        // 删除数据
+        deleteRow(row) {
+            const params = {id: row.id}
+            this.$confirm("该操作将删除该信息,是否继续删除?", "提示", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            }).then(() => {
+                this.$http.delete(params).then(res => {
+                    if (res.statusMsg === 'ok') {
+                        this.queryReset();
+                        this.$message.success("删除成功!")
+                    } else {
+                        this.$message.warning(res.statusMsg)
+                    }
+                })
+            }).catch(() => {
+                this.$message.warning("您已取消")
+            })
+        },
+        // 提交表单
+        onSubmit: throttle(function (formName) {
+            this.$refs[formName].validate(valid => {
+                if (!valid) return
+                const params = this.ruleForm
+                if (this.isUpdate) {
+                    // 更新
+                    this.$http.update(params).then((res) => {
+                        if (res.statusMsg === 'ok') {
+                            this.closeForm()
+                            this.getLists()
+                            this.$message.success('更新成功!')
+                        } else {
+                            this.$message.warning(res.statusMsg)
+                        }
+                    })
+                } else {
+                    // 添加
+                    this.$http.insert(params).then((res) => {
+                        if (res.statusMsg === 'ok') {
+                            this.closeForm()
+                            this.getLists()
+                            this.$message.success('添加成功!')
+                        } else {
+                            this.$message.warning(res.statusMsg)
+                        }
+                    })
+                }
+            })
+        }, 1000),
+        // 分页改变
+        pageChange() {
+            this.getLists()
+        },
+    }
+}
+</script>
+  
+<style lang="scss" scoped>
+@import '@/style/layout-main.scss';
+
+/deep/ {
+    &::-webkit-scrollbar {
+        width: 8px;
+        height: 8px;
+    }
+
+    &::-webkit-scrollbar-corner {
+        background-color: transparent;
+    }
+
+    &::-webkit-scrollbar-thumb {
+        border-radius: 10px;
+        box-shadow: inset 0 0 5px transparent;
+        background: #39B5FE;
+    }
+
+    &::-webkit-scrollbar-track {
+        box-shadow: inset 0 0 5px transparent;
+        border-radius: 10px;
+        background: rgba(76, 188, 254, .3);
+    }
+}
+</style>
\ No newline at end of file
diff --git a/web/src/views/SecureManage/RiskGrad/DangerInform.vue b/web/src/views/SecureManage/RiskGrad/DangerInform.vue
index 79198d0..b994119 100644
--- a/web/src/views/SecureManage/RiskGrad/DangerInform.vue
+++ b/web/src/views/SecureManage/RiskGrad/DangerInform.vue
@@ -1,3 +1,268 @@
 <template>
-    <div>危险源告知</div>
-</template>
\ No newline at end of file
+    <!-- 安全管理 ==> 风险分级管控 => 危险源告知-->
+    <div class="main">
+        <!-- header -->
+        <div class="main_header">
+            <div class="header_item">
+                <span class="header_label">安全等级:</span>
+                <el-select v-model="queryInfo.levelType" placeholder="请选择安全等级" clearable>
+                    <el-option v-for="item in safetyLevels" :key="item.levelType" :label="item.name"
+                        :value="item.levelType">
+                    </el-option>
+                </el-select>
+            </div>
+            <div class="header_item">
+                <el-button icon="el-icon-search" v-permission="'search'" @click="queryReset">查询</el-button>
+                <el-button class="search_btn" icon="el-icon-plus" v-permission="'insert'" @click="addRow">新增</el-button>
+            </div>
+        </div>
+
+        <!-- table -->
+        <div class="main_content">
+            <cpnTable :table-index="true" :table-data="dataList" :table-columns="tableColumns" :page-total="total"
+                :page-num.sync="queryInfo.pageNum" :page-size.sync="queryInfo.pageSize" :page-change="pageChange">
+            </cpnTable>
+        </div>
+
+        <!-- dialog -->
+        <el-dialog class="prop_dialog" v-if="isRender" :title="dialogTitle" :visible.sync="asyncVisible" width="460px"
+            @close="closeForm">
+            <el-form ref="ruleForm" :model="ruleForm" :rules="rules" label-width="auto" class="rule_form">
+                <el-form-item label="区域名称:" prop="region">
+                    <el-input v-model="ruleForm.region" clearable placeholder="请输入区域名称"></el-input>
+                </el-form-item>
+                <el-form-item label="安全等级:" prop="levelType">
+                    <el-select v-model="ruleForm.levelType" placeholder="请选择">
+                        <el-option v-for="item in safetyLevels" :key="item.levelType" :label="item.name"
+                            :value="item.levelType">
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="区域颜色:" prop="regionColor">
+                    <el-input v-model="ruleForm.regionColor" placeholder="请选择区域颜色" disabled></el-input>
+                    <el-color-picker v-model="ruleForm.regionColor"></el-color-picker>
+                </el-form-item>
+            </el-form>
+            <div slot="footer">
+                <el-button @click="asyncVisible = false">取 消</el-button>
+                <el-button class="submit_btn" @click="onSubmit('ruleForm')">提 交</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+  
+<script>
+import {throttle} from '@/plugins/public'; // 导入节流、动态切换组件尺寸方法
+import cpnTable from '@/components/element/Table'
+export default {
+    data() {
+        return {
+            isRender: false,
+            loading: false,
+            asyncVisible: false,
+            submitMode: '', // add update
+            total: 0,
+            queryInfo: {
+                pageNum: 1,
+                pageSize: 10,
+                levelType: '',
+            },
+            safetyLevelMap: {
+                1: {name: 'IV-A级', levelType: 1},
+                2: {name: 'IV-B级', levelType: 1},
+                3: {name: 'IV-C级', levelType: 1},
+                4: {name: 'IV-D级', levelType: 1},
+            }, //  安全等级 map
+            safetyLevels: [
+                {name: 'IV-A级', levelType: 1},
+                {name: 'IV-B级', levelType: 2},
+                {name: 'IV-C级', levelType: 3},
+                {name: 'IV-D级', levelType: 4},
+            ], // 安全等级 arr
+            dataList: [],
+            tableColumns: [], // table配置
+            ruleForm: {}, // 按钮表单
+            rules: {
+                region: [{required: true, message: '请输入区域名称', trigger: 'blur'}],
+                levelType: [{required: true, message: '请选择安全等级', trigger: 'change'}],
+                regionColor: [{required: true, message: '请选择区域颜色', trigger: 'change'}],
+            },
+            $http: '', // api路径赋值
+        }
+    },
+    components: {
+        cpnTable
+    },
+    computed: {
+        isUpdate() {
+            return this.submitMode === 'update'
+        },
+        dialogTitle() {
+            return this.isUpdate ? '修改区域' : '新增区域'
+        },
+    },
+    created() {
+        this.$http = this.$api.Safety.RiskGrad.warning
+        this.setFormProps()
+        this.setTableColumn()
+        this.getLists()
+    },
+    methods: {
+        // 获取table列表数据
+        getLists() {
+            this.loading = true
+            let params = this.queryInfo
+            this.$http.getLists(params).then(res => {
+                if (res.statusMsg === 'ok') {
+                    this.total = res.data.total
+                    this.dataList = res.data.list
+                }
+                this.loading = false
+            })
+        },
+        // 初始化 ruleform
+        setFormProps(options = {}) {
+            let _form = {
+                region: '', // 区域名称
+                levelType: '', // 安全等级
+                regionColor: '',  // 区域等级颜色
+            }
+            this.ruleForm = Object.keys(options).length ? options : _form
+        },
+        // 初始化 table 配置
+        setTableColumn() {
+            this.tableColumns = [
+                {index: true},
+                {name: "区域名称", key: "region"},
+                {name: "安全等级", key: "levelType", formatter: (row) => {return this.safetyLevelMap[row.levelType].name}},
+                {name: "区域颜色", key: "regionColor"},
+                {
+                    operation: true, name: "操作", width: 140, value: [
+                        {name: "修改", class: "table_btn", permission: "update", handleRow: this.updateRow},
+                        {name: "删除", class: "delete_btn", permission: "delete", handleRow: this.deleteRow},
+                    ]
+                },
+            ]
+        },
+        // 重置表单
+        resetForm(formName) {
+            this.$refs[formName].resetFields()
+        },
+        // 显示表单
+        showForm() {
+            !this.isRender && (this.isRender = true)
+            this.asyncVisible = true
+        },
+        // 隐藏表单
+        closeForm() {
+            this.asyncVisible = false
+            this.resetForm('ruleForm')
+        },
+        // 查询按钮列表信息
+        queryReset() {
+            this.queryInfo.pageNum = 1
+            this.queryInfo.pageSize = 10
+            this.getLists()
+        },
+        // 添加数据
+        addRow() {
+            this.submitMode = 'add'
+            this.showForm()
+        },
+        // 更新数据
+        updateRow(row) {
+            this.submitMode = 'update'
+            this.showForm()
+            this.$nextTick(() => {
+                this.ruleForm.id = ''
+                Object.keys(this.ruleForm).forEach(item => {
+                    if (row.hasOwnProperty.call(row, item)) {
+                        this.ruleForm[item] = row[item]
+                    }
+                })
+            })
+        },
+        // 删除数据
+        deleteRow(row) {
+            const params = {id: row.id}
+            this.$confirm("该操作将删除该信息,是否继续删除?", "提示", {
+                confirmButtonText: "确定",
+                cancelButtonText: "取消",
+                type: "warning"
+            }).then(() => {
+                this.$http.delete(params).then(res => {
+                    if (res.statusMsg === 'ok') {
+                        this.queryReset();
+                        this.$message.success("删除成功!")
+                    } else {
+                        this.$message.warning(res.statusMsg)
+                    }
+                })
+            }).catch(() => {
+                this.$message.warning("您已取消")
+            })
+        },
+        // 提交表单
+        onSubmit: throttle(function () {
+            this.$refs.ruleForm.validate(valid => {
+                if (!valid) return
+                const params = this.ruleForm
+                if (this.isUpdate) {
+                    // 更新
+                    this.$http.update(params).then((res) => {
+                        if (res.statusMsg === 'ok') {
+                            this.closeForm()
+                            this.getLists()
+                            this.$message.success('更新成功!')
+                        } else {
+                            this.$message.warning(res.statusMsg)
+                        }
+                    })
+                } else {
+                    // 添加
+                    this.$http.insert(params).then((res) => {
+                        if (res.statusMsg === 'ok') {
+                            this.closeForm()
+                            this.getLists()
+                            this.$message.success('添加成功!')
+                        } else {
+                            this.$message.warning(res.statusMsg)
+                        }
+                    })
+                }
+            })
+        }, 1000),
+        // 分页改变
+        pageChange() {
+            this.getLists()
+        },
+    }
+}
+</script>
+  
+<style lang="scss" scoped>
+@import '@/style/layout-main.scss';
+
+/deep/ {
+    &::-webkit-scrollbar {
+        width: 8px;
+        height: 8px;
+    }
+
+    &::-webkit-scrollbar-corner {
+        background-color: transparent;
+    }
+
+    &::-webkit-scrollbar-thumb {
+        border-radius: 10px;
+        box-shadow: inset 0 0 5px transparent;
+        background: #39B5FE;
+    }
+
+    &::-webkit-scrollbar-track {
+        box-shadow: inset 0 0 5px transparent;
+        border-radius: 10px;
+        background: rgba(76, 188, 254, .3);
+    }
+}
+</style>
\ No newline at end of file

--
Gitblit v1.9.3