Browse Source

Merge branch 'dev-production-safety' into feat/production-safety

sunqijun 3 months ago
parent
commit
d5f3209073

+ 80 - 4
src/api/production-safety/responsibility-implementation/index.ts

@@ -6,7 +6,6 @@ import type { QueryPageRequest, QueryPageResponse } from '@/types/basic-query';
  * @param params - 分页查询参数,通常包含 username、pageNum、pageSize 等
  * @returns Promise<QueryPageResponse>
  */
-queryAvailableUserList
 export function queryAvailableUserList(params) {
   return http.request({
     url: `/admin/user/queryAvailableUserList`,
@@ -375,7 +374,7 @@ export function safetyNoticeAdminDelete(id) {
  * @returns Promise<any> 安全通知的完整详细信息,包括发布内容、接收部门、反馈状态等
  */
 export function safetyNoticeAdminQueryDetail(params) {
-   return http.request({
+  return http.request({
     url: `/safetyNotice/admin/queryDetail`,
     method: 'get',
     params
@@ -570,7 +569,7 @@ export function safetyRiskListChange(params) {
  * 查询安全风险清单详情           
  *  @param id - 安全风险清单 ID
  * @returns Promise<any> 安全风险清单详细信息
- */       
+ */
 export function safetyRiskListQueryDetail(id) {
   return http.request({
     url: `/safetyRisk/list/queryDetail?id=${id}`,
@@ -602,4 +601,81 @@ export function safetyHazardInventoryDelete(id) {
     url: `/safetyHazardInventory/delete?id=${id}`,
     method: 'delete',
   });
-}
+}
+
+/**
+  * 保存安全危险源清单     
+  * @param params - 安全危险源清单数据
+  * @returns Promise<void>
+  */
+export function safetyHazardInventorySaveHazard(params) {
+  return http.request({
+    url: `/safetyHazardInventory/saveHazard`,
+    method: 'post',
+    params
+  });
+}
+
+// safetyHazardInventory/queryDetail
+/**
+ * 查询安全危险源清单详情 
+ * @param id - 安全危险源清单 ID
+ *  @returns Promise<any> 安全危险源清单详细信息
+ */
+export function safetyHazardInventoryQueryDetail(id) {
+  return http.request({
+    url: `/safetyHazardInventory/queryDetail?id=${id}`,
+    method: 'get',
+  });
+}
+
+/**
+ * 更新安全危险源清单 
+ * @param params - 更新后的安全危险源清单数据(需包含 ID)
+ * @returns Promise<void>
+ */
+export function safetyHazardInventoryUpdateHazard(params) {
+  return http.request({
+    url: `/safetyHazardInventory/updateHazard`,
+    method: 'put',
+    params
+  });
+}
+
+/**
+ * 分页查询安全整改计划与方案列表 
+ * @param params - 分页及查询条件
+ * @returns Promise<QueryPageResponse> 安全整改计划与方案分页结果
+ */
+
+export function safetyHazardInventoryQueryPlanAndSchemePage(params) {
+  return http.request({
+    url: '/safetyHazardInventory/queryPlanAndSchemePage',
+    method: 'post',
+    params
+  });
+}
+
+/**
+ * 删除安全整改计划与方案 
+ * @param id - 安全整改计划与方案 ID
+ * @returns Promise<void>
+ */
+export function safetyHazardInventoryDeletePlan(id) {
+  return http.request({
+    url: `/safetyHazardInventory/deletePlan?id=${id}`,
+    method: 'delete',
+  });
+}
+
+/**
+ * 查询安全整改计划与方案详情 
+ * @param id - 安全整改计划与方案 ID    
+ * @returns Promise<any> 安全整改计划与方案详细信息
+ */
+export function safetyHazardInventoryQueryPlanDetail(id) {
+  return http.request({
+    url: `/safetyHazardInventory/queryPlanDetail?id=${id}`,
+    method: 'get',
+  });
+}

+ 55 - 39
src/views/production-safety/risk-identification-and-control/hazard-manage/add.vue

@@ -59,7 +59,8 @@
           />
         </el-form-item>
         <el-form-item label="风险管理部门" prop="riskManagementDept">
-          <el-cascader
+          <!-- <el-cascader
+            :ref="(el) => (cascaderRef['riskManagementDept'] = el)"
             v-model="formValue.riskManagementDeptId"
             size="large"
             style="width: 330px"
@@ -68,12 +69,14 @@
             :show-all-levels="false"
             placeholder="请选择"
             filterable
-            @change="handleDeptChange('riskManagementDept')"
-          />
+            @change="() => handleChangeDept('riskManagementDept')"
+          /> -->
+          <el-input size="large" placeholder="请选择" v-model="formValue.riskManagementDept" style="width: 330px" />
         </el-form-item>
         <el-form-item label="协作部门" prop="cooperationDept">
-          <el-cascader
+          <!-- <el-cascader
             v-model="formValue.cooperationDeptId"
+            :ref="(el) => (cascaderRef['cooperationDept'] = el)"
             size="large"
             style="width: 330px"
             :options="firstLevelDepts"
@@ -81,8 +84,9 @@
             :show-all-levels="false"
             placeholder="请选择"
             filterable
-            @change="handleDeptChange('cooperationDept')"
-          />
+            @change="handleChangeDept('cooperationDept')"
+          /> -->
+          <el-input size="large" placeholder="请选择" v-model="formValue.cooperationDept" style="width: 330px" />
         </el-form-item>
 
         <!-- 风险评估 -->
@@ -97,19 +101,22 @@
 
         <el-divider content-position="left">固有风险评估</el-divider>
         <el-form-item label="可能性(M)" prop="inherentRiskM">
-          <el-select v-model="formValue.inherentRiskM" size="large" placeholder="1-5" style="width: 330px">
+          <!-- <el-select v-model="formValue.inherentRiskM" size="large" placeholder="1-5" style="width: 330px">
             <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
-          </el-select>
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.inherentRiskM" :min="1" style="width: 330px" />
         </el-form-item>
         <el-form-item label="暴露频率(E)" prop="inherentRiskE">
-          <el-select v-model="formValue.inherentRiskE" size="large" placeholder="1-6" style="width: 330px">
+          <!-- <el-select v-model="formValue.inherentRiskE" size="large" placeholder="1-6" style="width: 330px">
             <el-option v-for="n in 6" :key="n" :label="n" :value="n" />
-          </el-select>
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.inherentRiskE" :min="1" style="width: 330px" />
         </el-form-item>
         <el-form-item label="严重度(S)" prop="inherentRiskS">
-          <el-select v-model="formValue.inherentRiskS" size="large" placeholder="1-5" style="width: 330px">
-            <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
-          </el-select>
+          <!-- <el-select v-model="formValue.inherentRiskS" size="large" placeholder="1-5" style="width: 330px">
+                  <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+                </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.inherentRiskS" :min="1" style="width: 330px" />
         </el-form-item>
         <el-form-item label="风险值(R)" prop="inherentRiskR">
           <el-input
@@ -122,10 +129,10 @@
         </el-form-item>
         <el-form-item label="风险等级" prop="inherentRiskLevel">
           <el-select v-model="formValue.inherentRiskLevel" size="large" placeholder="请选择" style="width: 330px">
-            <el-option label="A" value="A" />
+            <!-- <el-option label="A" value="A" /> -->
             <el-option label="B" value="B" />
             <el-option label="C" value="C" />
-            <el-option label="D" value="D" />
+            <!-- <el-option label="D" value="D" /> -->
           </el-select>
         </el-form-item>
         <el-form-item label="升级等级" prop="inherentRiskUpgrade">
@@ -145,8 +152,9 @@
           />
         </el-form-item>
         <el-form-item label="主责部门" prop="controlMainDept">
-          <el-cascader
+          <!-- <el-cascader
             v-model="formValue.controlMainDeptId"
+            :ref="(el) => (cascaderRef['controlMainDept'] = el)"
             size="large"
             style="width: 330px"
             :options="firstLevelDepts"
@@ -154,12 +162,14 @@
             :show-all-levels="false"
             placeholder="请选择"
             filterable
-            @change="handleDeptChange('controlMainDept')"
-          />
+            @change="handleChangeDept('controlMainDept')"
+          /> -->
+          <el-input size="large" placeholder="请选择" v-model="formValue.controlMainDept" style="width: 330px" />
         </el-form-item>
         <el-form-item label="协作部门" prop="controlCoopDept">
-          <el-cascader
+          <!-- <el-cascader
             v-model="formValue.controlCoopDeptId"
+            :ref="(el) => (cascaderRef['controlCoopDept'] = el)"
             size="large"
             style="width: 330px"
             :options="firstLevelDepts"
@@ -167,8 +177,9 @@
             :show-all-levels="false"
             placeholder="请选择"
             filterable
-            @change="handleDeptChange('controlCoopDept')"
-          />
+            @change="handleChangeDept('controlCoopDept')"
+          /> -->
+          <el-input size="large" placeholder="请选择" v-model="formValue.controlCoopDept" style="width: 330px" />
         </el-form-item>
         <el-form-item label="完成期限" prop="completionDeadline">
           <el-date-picker
@@ -201,19 +212,22 @@
         <!-- 剩余风险 -->
         <el-divider content-position="left">剩余风险评估</el-divider>
         <el-form-item label="可能性(M)" prop="controlRiskM">
-          <el-select v-model="formValue.controlRiskM" size="large" placeholder="1-5" style="width: 330px">
+          <!-- <el-select v-model="formValue.controlRiskM" size="large" placeholder="1-5" style="width: 330px">
             <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
-          </el-select>
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.controlRiskM" :min="1" style="width: 330px" />
         </el-form-item>
         <el-form-item label="暴露频率(E)" prop="controlRiskE">
-          <el-select v-model="formValue.controlRiskE" size="large" placeholder="1-6" style="width: 330px">
+          <!-- <el-select v-model="formValue.controlRiskE" size="large" placeholder="1-6" style="width: 330px">
             <el-option v-for="n in 6" :key="n" :label="n" :value="n" />
-          </el-select>
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.controlRiskE" :min="1" style="width: 330px" />
         </el-form-item>
         <el-form-item label="严重度(S)" prop="controlRiskS">
-          <el-select v-model="formValue.controlRiskS" size="large" placeholder="1-5" style="width: 330px">
+          <!-- <el-select v-model="formValue.controlRiskS" size="large" placeholder="1-5" style="width: 330px">
             <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
-          </el-select>
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.controlRiskS" :min="1" style="width: 330px" />
         </el-form-item>
         <el-form-item label="风险值(R)" prop="controlRiskR">
           <el-input
@@ -226,9 +240,9 @@
         </el-form-item>
         <el-form-item label="风险等级" prop="controlRiskLevel">
           <el-select v-model="formValue.controlRiskLevel" size="large" placeholder="请选择" style="width: 330px">
-            <el-option label="A" value="A" />
+            <!-- <el-option label="A" value="A" />
             <el-option label="B" value="B" />
-            <el-option label="C" value="C" />
+            <el-option label="C" value="C" /> -->
             <el-option label="D" value="D" />
           </el-select>
         </el-form-item>
@@ -239,14 +253,14 @@
             type="textarea"
             v-model="formValue.remarks"
             size="large"
-            :rows="3"
+            :rows="7"
             placeholder="例如:需每月提交检查报告"
           />
         </el-form-item>
       </el-form>
     </main>
     <footer class="safety-platform-container__footer">
-      <el-button @click="$router.push({ name: 'areaResponsibilities:public' })">返回</el-button>
+      <el-button @click="$router.push({ name: 'hazardManage' })">返回</el-button>
       <el-button type="primary" :loading="submiting" @click="handleSubmit">提交</el-button>
     </footer>
   </div>
@@ -261,6 +275,7 @@
   import {
     queryAvailableUserList,
     safetyRiskListSaveRiskList,
+    safetyHazardInventorySaveHazard,
   } from '@/api/production-safety/responsibility-implementation';
 
   const router = useRouter();
@@ -275,7 +290,7 @@
     value: 'id',
     label: 'deptName',
   };
-  const cascaderRef = ref<any>();
+  const cascaderRef = ref<any>({});
 
   const formValue = reactive({
     hazardCode: '',
@@ -334,13 +349,14 @@
   });
 
   const handleChangeDept = (prop) => {
-    const cascader = cascaderRef.value;
+    const cascader = cascaderRef.value?.[prop];
     const deptInfo = cascader?.getCheckedNodes();
-    formValue[prop] = deptInfo[0].label;
+    formValue[prop] = deptInfo[0]?.label;
     formRef.value.validateField(prop);
-    nextTick(() => {
-      handleQueryAvailableUserList(deptInfo[0].label, prop);
-    });
+
+    // nextTick(() => {
+    //   handleQueryAvailableUserList(deptInfo[0].label, prop);
+    // });
   };
 
   const getDeptData = () => {
@@ -384,12 +400,12 @@
     formRef.value?.validate((valid: boolean) => {
       if (valid) {
         submiting.value = true;
-        safetyRiskListSaveRiskList({
+        safetyHazardInventorySaveHazard({
           ...formValue,
         })
           .then(() => {
             ElMessage.success('创建成功!');
-            router.push({ name: 'riskManage' });
+            router.push({ name: 'hazardManage' });
           })
           .finally(() => {
             submiting.value = false;

+ 270 - 1
src/views/production-safety/risk-identification-and-control/hazard-manage/create-plan.vue

@@ -1 +1,270 @@
-<template>list</template>
+<template>
+  <div class="safety-platform-container">
+    <header class="safety-platform-container__header">
+      <div class="breadcrumb-title"> {{ detailData?.hazardName }} </div>
+      <div class="detail-content">
+        <span>编号:{{ detailData?.hazardCode }} </span>
+        <span>创建人:{{ detailData?.createdByName }} </span>
+        <span>创建时间:{{ detailData?.createdAt }} </span>
+      </div>
+      <el-tabs v-model="activeTab">
+        <el-tab-pane label="全部" name="" />
+        <el-tab-pane label="待开始" :name="1" />
+        <el-tab-pane label="进行中" :name="2" />
+        <el-tab-pane label="已完成" :name="3" />
+      </el-tabs>
+    </header>
+    <main class="safety-platform-container__main">
+      <div class="search-form">
+        <el-form :inline="true">
+          <el-form-item label="状态">
+            <el-select v-model="queryParams.queryParam.status" clearable placeholder="状态" style="width: 170px">
+              <el-option value="" label="全部" />
+              <el-option :value="1" label="待开始" />
+              <el-option :value="2" label="进行中" />
+              <el-option :value="3" label="已完成" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="部门名称">
+            <el-cascader
+              v-model="queryParams.queryParam.responsibleDepartmentId"
+              style="width: 170px"
+              ref="cascaderRef"
+              :options="firstLevelDepts"
+              :props="cascaderProp"
+              :show-all-levels="false"
+              placeholder="部门名称"
+              filterable
+              @change="handleChangeDept"
+            />
+          </el-form-item>
+          <el-form-item label="计划日期">
+            <el-date-picker
+              v-model="queryParams.queryParam.date"
+              clearable
+              type="daterange"
+              start-placeholder="开始时间"
+              end-placeholder="结束时间"
+              style="width: 230px"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
+            />
+          </el-form-item>
+        </el-form>
+
+        <div>
+          <el-button type="primary" @click="$router.push({ name: 'hazardManageAdd' })">添加 </el-button>
+          <el-button type="primary" @click="queryTableList">查询</el-button>
+          <el-button @click="handleRestParams">重置</el-button>
+        </div>
+      </div>
+
+      <div class="table-content">
+        <el-table :data="tableData.data">
+          <el-table-column type="index" label="序号" width="80" />
+          <el-table-column label="计划/方案名称" prop="planName" width="180" />
+
+          <el-table-column label="状态" prop="statusName" width="80" />
+          <el-table-column label="执行部门" prop="executorName" width="180" />
+          <el-table-column label="执行人" prop="executor" width="130" />
+          <el-table-column label="计划/方案描述" prop="planContent" width="180" />
+          <el-table-column label="计划开始时间" prop="planStartDate" width="180" />
+          <el-table-column label="计划结束时间" prop="planEndDate" width="180" />
+
+          <el-table-column fixed="right" min-width="240" label="操作">
+            <template #default="scope">
+              <el-button
+                type="primary"
+                link
+                @click="$router.push({ name: 'hazardManageEdit', query: { id: scope.row.id } })"
+              >
+                编辑
+              </el-button>
+
+              <el-button type="primary" link @click="handleConfirmDeleteRow(scope)">删除</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <div class="pagination-container" v-if="tableData.total > 0">
+        <el-pagination
+          background
+          :current-page="queryParams.pageNumber"
+          :page-size="queryParams.pageSize"
+          :total="tableData.total"
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </main>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { onMounted, reactive, ref } from 'vue';
+  import { ElMessage } from 'element-plus';
+  import { useRouter, useRoute } from 'vue-router';
+  import {
+    safetyHazardInventoryQueryPlanAndSchemePage,
+    safetyHazardInventoryDeletePlan,
+    safetyHazardInventoryQueryPlanDetail,
+  } from '@/api/production-safety/responsibility-implementation';
+  import { omit } from 'lodash-es';
+  import { useUserInfoHook } from '@/hooks/useUserInfoHook';
+  import { unformatAttachment } from '@/components/UploadFiles/utils';
+  import { downloadFile } from '@/views/disaster/utils';
+  import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
+  import { getAllDepartments } from '@/api/auth/dept';
+
+  const router = useRouter();
+  const route = useRoute();
+  const { id } = useUserInfoHook();
+  const firstLevelDepts = ref<any[]>([]);
+  const cascaderProp = {
+    expandTrigger: 'click',
+    checkStrictly: true,
+    // emitPath: false,
+    value: 'id',
+    label: 'deptName',
+  };
+  const activeTab = ref('');
+  const queryParams = reactive<any>({
+    pageNumber: 1,
+    pageSize: 10,
+    queryParam: {
+      status: '',
+      date: null,
+      execDepartment: '',
+    },
+  });
+  const cascaderRef = ref();
+  const detailData = reactive({
+    createdAt: '',
+    createdByName: '',
+    hazardName: '',
+    hazardCode: '',
+  });
+  const tableData = reactive({
+    data: [],
+    total: 0,
+  });
+
+  const handleSizeChange = (value) => {};
+  const handleCurrentChange = (value) => {
+    queryParams.pageNumber = value;
+    queryTableList();
+  };
+
+  const getDeptData = () => {
+    getAllDepartments().then((res) => {
+      firstLevelDepts.value = formatDeptTree(res);
+    });
+  };
+  const handleChangeDept = () => {
+    const deptInfo = cascaderRef.value?.getCheckedNodes();
+    if (deptInfo?.[0]) {
+      queryParams.queryParam.execDepartment = deptInfo[0].label;
+    }
+  };
+
+  const handleConfirmDeleteRow = (scope) => {
+    safetyHazardInventoryDeletePlan(scope.row.id).then(() => {
+      ElMessage.success('删除成功!');
+      queryTableList();
+    });
+  };
+
+  const queryTableList = () => {
+    safetyHazardInventoryQueryPlanAndSchemePage({
+      ...queryParams,
+
+      queryParam: {
+        ...omit(queryParams.queryParam, ['date', 'responsibleDepartmentId']),
+        hazardListId: route.query.id,
+
+        startTime: queryParams.queryParam.date ? queryParams.queryParam.date[0] : undefined,
+        endTime: queryParams.queryParam.date ? queryParams.queryParam.date[1] : undefined,
+      },
+    }).then((res) => {
+      tableData.data = res.records;
+      tableData.total = res.totalRow;
+    });
+  };
+  const handleRestParams = () => {
+    Object.assign(queryParams, {
+      pageNumber: 1,
+      pageSize: 10,
+      queryParam: {
+        ...queryParams.queryParam,
+        status: '',
+        date: null,
+        execDepartment: '',
+      },
+    });
+    queryTableList();
+  };
+
+  const handlesafetyHazardInventoryQueryPlanDetail = async () => {
+    const res = await safetyHazardInventoryQueryPlanDetail(route.query.id as string);
+    Object.assign(detailData, res);
+  };
+
+  onMounted(async () => {
+    await getDeptData();
+    handlesafetyHazardInventoryQueryPlanDetail();
+    queryTableList();
+  });
+</script>
+
+<style lang="scss" scoped>
+  @use '@/styles/page-details-layout.scss' as *;
+  @use '@/styles/page-main-layout.scss' as *;
+  @use '@/styles/basic-table-action.scss' as *;
+
+  :deep(.el-tabs__header) {
+    margin: 0;
+  }
+  :deep(.el-tabs__item) {
+    font-size: 14px !important;
+  }
+  :deep(.flexContent) {
+    display: flex;
+  }
+  :deep(.breadcrumb .title) {
+    margin-left: 0;
+  }
+
+  :deep(.el-form) {
+    flex: 1;
+    display: flex;
+    row-gap: 15px;
+    flex-wrap: wrap;
+  }
+  :deep(.el-form-item) {
+    margin-bottom: 0;
+  }
+  :deep(main) {
+    display: flex;
+    flex-direction: column;
+  }
+  .search-form {
+    min-width: 800px;
+    display: flex;
+
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20px;
+  }
+
+  .button-content {
+    margin-bottom: 20px;
+  }
+  .table-content {
+    flex: 1;
+    overflow: hidden;
+    overflow-y: auto;
+  }
+  .page-content {
+    display: flex;
+    justify-content: flex-end;
+  }
+</style>

+ 471 - 1
src/views/production-safety/risk-identification-and-control/hazard-manage/edit.vue

@@ -1 +1,471 @@
-<template>sdfsdf</template>
+<template>
+  <div class="safety-platform-container">
+    <header class="safety-platform-container__header">
+      <div class="breadcrumb-title">
+        <BreadcrumbBack />
+        编辑危险源清单
+      </div>
+    </header>
+    <main class="safety-platform-container__main">
+      <el-form ref="formRef" :inline="true" label-width="auto" :model="formValue" :rules="rules">
+        <!-- 基础信息 -->
+        <el-divider content-position="left">基础信息</el-divider>
+        <el-form-item label="危险源编号" prop="hazardCode">
+          <el-input
+            v-model="formValue.hazardCode"
+            size="large"
+            placeholder="例如:RD-202311-042"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="关键过程/作业单元" prop="keyProcessUnit">
+          <el-input
+            v-model="formValue.keyProcessUnit"
+            size="large"
+            placeholder="例如:张江快堆实验室(10号楼)"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="危险源名称" prop="hazardName">
+          <el-input
+            v-model="formValue.hazardName"
+            size="large"
+            placeholder="例如:高温熔融金属操作"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="是否重大危险源" prop="isMajorHazard">
+          <el-select v-model="formValue.isMajorHazard" size="large" placeholder="请选择" style="width: 330px">
+            <el-option :value="1" label="是" />
+            <el-option :value="0" label="否" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="危险源来源" prop="hazardSource">
+          <el-input
+            v-model="formValue.hazardSource"
+            size="large"
+            placeholder="例如:作业单元划分"
+            style="width: 330px"
+          />
+        </el-form-item>
+
+        <!-- 部门责任 -->
+        <el-form-item label="涉及部门" prop="involvedDepartment">
+          <el-input
+            v-model="formValue.involvedDepartment"
+            size="large"
+            placeholder="例如:核材料研究部/设备管理部(支持手动输入多部门)"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="风险管理部门" prop="riskManagementDept">
+          <!-- <el-cascader
+            :ref="(el) => (cascaderRef['riskManagementDept'] = el)"
+            v-model="formValue.riskManagementDeptId"
+            size="large"
+            style="width: 330px"
+            :options="firstLevelDepts"
+            :props="cascaderProp"
+            :show-all-levels="false"
+            placeholder="请选择"
+            filterable
+            @change="() => handleChangeDept('riskManagementDept')"
+          /> -->
+          <el-input size="large" placeholder="请选择" v-model="formValue.riskManagementDept" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="协作部门" prop="cooperationDept">
+          <!-- <el-cascader
+            v-model="formValue.cooperationDeptId"
+            :ref="(el) => (cascaderRef['cooperationDept'] = el)"
+            size="large"
+            style="width: 330px"
+            :options="firstLevelDepts"
+            :props="cascaderProp"
+            :show-all-levels="false"
+            placeholder="请选择"
+            filterable
+            @change="handleChangeDept('cooperationDept')"
+          /> -->
+          <el-input size="large" placeholder="请选择" v-model="formValue.cooperationDept" style="width: 330px" />
+        </el-form-item>
+
+        <!-- 风险评估 -->
+        <el-form-item label="可能后果" prop="possibleConsequences">
+          <el-input
+            v-model="formValue.possibleConsequences"
+            size="large"
+            placeholder="例如:灼伤、火灾"
+            style="width: 330px"
+          />
+        </el-form-item>
+
+        <el-divider content-position="left">固有风险评估</el-divider>
+        <el-form-item label="可能性(M)" prop="inherentRiskM">
+          <!-- <el-select v-model="formValue.inherentRiskM" size="large" placeholder="1-5" style="width: 330px">
+            <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.inherentRiskM" :min="1" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="暴露频率(E)" prop="inherentRiskE">
+          <!-- <el-select v-model="formValue.inherentRiskE" size="large" placeholder="1-6" style="width: 330px">
+            <el-option v-for="n in 6" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.inherentRiskE" :min="1" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="严重度(S)" prop="inherentRiskS">
+          <!-- <el-select v-model="formValue.inherentRiskS" size="large" placeholder="1-5" style="width: 330px">
+                  <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+                </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.inherentRiskS" :min="1" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="风险值(R)" prop="inherentRiskR">
+          <el-input
+            v-model="formValue.inherentRiskR"
+            size="large"
+            disabled
+            placeholder="自动计算: M×E×S"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="风险等级" prop="inherentRiskLevel">
+          <el-select v-model="formValue.inherentRiskLevel" size="large" placeholder="请选择" style="width: 330px">
+            <!-- <el-option label="A" value="A" /> -->
+            <el-option label="B" value="B" />
+            <el-option label="C" value="C" />
+            <!-- <el-option label="D" value="D" /> -->
+          </el-select>
+        </el-form-item>
+        <el-form-item label="升级等级" prop="inherentRiskUpgrade">
+          <el-input v-model="formValue.inherentRiskUpgrade" size="large" placeholder="例如:2级" style="width: 330px" />
+        </el-form-item>
+
+        <!-- 管控措施 -->
+        <el-divider content-position="left">管控措施</el-divider>
+        <el-form-item label="主要管控措施" prop="controlMeasures">
+          <el-input
+            type="textarea"
+            :rows="3"
+            v-model="formValue.controlMeasures"
+            size="large"
+            placeholder="每条措施用分号分隔,例如:1.穿戴防护服;2.设置隔离区;3.定期检查冷却系统"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="主责部门" prop="controlMainDept">
+          <!-- <el-cascader
+            v-model="formValue.controlMainDeptId"
+            :ref="(el) => (cascaderRef['controlMainDept'] = el)"
+            size="large"
+            style="width: 330px"
+            :options="firstLevelDepts"
+            :props="cascaderProp"
+            :show-all-levels="false"
+            placeholder="请选择"
+            filterable
+            @change="handleChangeDept('controlMainDept')"
+          /> -->
+          <el-input size="large" placeholder="请选择" v-model="formValue.controlMainDept" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="协作部门" prop="controlCoopDept">
+          <!-- <el-cascader
+            v-model="formValue.controlCoopDeptId"
+            :ref="(el) => (cascaderRef['controlCoopDept'] = el)"
+            size="large"
+            style="width: 330px"
+            :options="firstLevelDepts"
+            :props="cascaderProp"
+            :show-all-levels="false"
+            placeholder="请选择"
+            filterable
+            @change="handleChangeDept('controlCoopDept')"
+          /> -->
+          <el-input size="large" placeholder="请选择" v-model="formValue.controlCoopDept" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="完成期限" prop="completionDeadline">
+          <el-date-picker
+            v-model="formValue.completionDeadline"
+            type="date"
+            size="large"
+            placeholder="选择日期"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="完成状态" prop="completionStatus">
+          <el-input
+            v-model="formValue.completionStatus"
+            size="large"
+            placeholder="例如:措施1,2已完成"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="验证状态" prop="verificationStatus">
+          <el-input
+            v-model="formValue.verificationStatus"
+            size="large"
+            placeholder="例如:措施1已验证"
+            style="width: 330px"
+          />
+        </el-form-item>
+
+        <!-- 剩余风险 -->
+        <el-divider content-position="left">剩余风险评估</el-divider>
+        <el-form-item label="可能性(M)" prop="controlRiskM">
+          <!-- <el-select v-model="formValue.controlRiskM" size="large" placeholder="1-5" style="width: 330px">
+            <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.controlRiskM" :min="1" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="暴露频率(E)" prop="controlRiskE">
+          <!-- <el-select v-model="formValue.controlRiskE" size="large" placeholder="1-6" style="width: 330px">
+            <el-option v-for="n in 6" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.controlRiskE" :min="1" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="严重度(S)" prop="controlRiskS">
+          <!-- <el-select v-model="formValue.controlRiskS" size="large" placeholder="1-5" style="width: 330px">
+            <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number :step="1" :precision="0" v-model="formValue.controlRiskS" :min="1" style="width: 330px" />
+        </el-form-item>
+        <el-form-item label="风险值(R)" prop="controlRiskR">
+          <el-input
+            v-model="formValue.controlRiskR"
+            size="large"
+            disabled
+            placeholder="自动计算: M×E×S"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="风险等级" prop="controlRiskLevel">
+          <el-select v-model="formValue.controlRiskLevel" size="large" placeholder="请选择" style="width: 330px">
+            <!-- <el-option label="A" value="A" />
+            <el-option label="B" value="B" />
+            <el-option label="C" value="C" /> -->
+            <el-option label="D" value="D" />
+          </el-select>
+        </el-form-item>
+
+        <!-- 备注 -->
+        <el-form-item label="备注" prop="remarks" style="width: 87.2%">
+          <el-input
+            type="textarea"
+            v-model="formValue.remarks"
+            size="large"
+            :rows="7"
+            placeholder="例如:需每月提交检查报告"
+          />
+        </el-form-item>
+      </el-form>
+    </main>
+    <footer class="safety-platform-container__footer">
+      <el-button @click="$router.push({ name: 'hazardManage' })">返回</el-button>
+      <el-button type="primary" :loading="submiting" @click="handleSubmit">提交</el-button>
+    </footer>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { ref, reactive, onMounted, nextTick } from 'vue';
+  import { useRouter, useRoute } from 'vue-router';
+  import { ElMessage } from 'element-plus';
+  import { getAllDepartments } from '@/api/auth/dept';
+  import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
+
+  import {
+    queryAvailableUserList,
+    safetyHazardInventoryQueryDetail,
+    safetyHazardInventoryUpdateHazard,
+  } from '@/api/production-safety/responsibility-implementation';
+
+  const router = useRouter();
+  const route = useRoute();
+  const formRef = ref<any>(null);
+  const submiting = ref(false);
+
+  const userOptions = ref<any[]>([]);
+  const firstLevelDepts = ref<any[]>([]);
+  const cascaderProp = {
+    expandTrigger: 'click',
+    checkStrictly: true,
+    value: 'id',
+    label: 'deptName',
+  };
+  const cascaderRef = ref<any>({});
+
+  const formValue = reactive({
+    hazardCode: '',
+    keyProcessUnit: '',
+    hazardName: '',
+    isMajorHazard: undefined as number | undefined,
+    hazardSource: '',
+    involvedDepartment: '',
+    riskManagementDept: '',
+    // riskManagementDeptId: [] as number[],
+    cooperationDept: '',
+    // cooperationDeptId: [] as number[],
+    possibleConsequences: '',
+    inherentRiskM: undefined as number | undefined,
+    inherentRiskE: undefined as number | undefined,
+    inherentRiskS: undefined as number | undefined,
+    inherentRiskR: 0, // 自动计算
+    inherentRiskLevel: '',
+    inherentRiskUpgrade: '',
+    controlMeasures: '',
+    controlMainDept: '',
+    // controlMainDeptId: [] as number[],
+    controlCoopDept: '',
+    // controlCoopDeptId: [] as number[],
+    completionDeadline: '',
+    completionStatus: '',
+    verificationStatus: '',
+    controlRiskM: undefined as number | undefined,
+    controlRiskE: undefined as number | undefined,
+    controlRiskS: undefined as number | undefined,
+    controlRiskR: 0,
+    controlRiskLevel: '',
+    remarks: '',
+  });
+
+  const rules = reactive({
+    hazardCode: [{ required: true, message: '请输入危险源编号', trigger: 'blur' }],
+    keyProcessUnit: [{ required: true, message: '请输入关键工艺单元', trigger: 'blur' }],
+    hazardName: [{ required: true, message: '请输入危险源名称', trigger: 'blur' }],
+    isMajorHazard: [{ required: true, message: '请选择是否重大危险源', trigger: 'change' }],
+    hazardSource: [{ required: true, message: '请输入危险源来源', trigger: 'blur' }],
+    involvedDepartment: [{ required: true, message: '请输入涉及部门', trigger: 'blur' }],
+    riskManagementDept: [{ required: true, message: '请选择风险管理部门', trigger: 'change' }],
+    cooperationDept: [{ required: true, message: '请选择协作部门', trigger: 'change' }],
+    possibleConsequences: [{ required: true, message: '请输入可能后果', trigger: 'blur' }],
+    inherentRiskM: [{ required: true, message: '请选择可能性', trigger: 'change' }],
+    inherentRiskE: [{ required: true, message: '请选择暴露频率', trigger: 'change' }],
+    inherentRiskS: [{ required: true, message: '请选择严重度', trigger: 'change' }],
+    inherentRiskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
+    controlMeasures: [{ required: true, message: '请输入管控措施', trigger: 'blur' }],
+    controlMainDept: [{ required: true, message: '请选择主责部门', trigger: 'change' }],
+    controlRiskM: [{ required: true, message: '请选择剩余风险可能性', trigger: 'change' }],
+    controlRiskE: [{ required: true, message: '请选择剩余风险暴露频率', trigger: 'change' }],
+    controlRiskS: [{ required: true, message: '请选择剩余风险严重度', trigger: 'change' }],
+    controlRiskLevel: [{ required: true, message: '请选择剩余风险等级', trigger: 'change' }],
+  });
+
+  const handleChangeDept = (prop) => {
+    const cascader = cascaderRef.value?.[prop];
+    const deptInfo = cascader?.getCheckedNodes();
+    formValue[prop] = deptInfo[0]?.label;
+    formRef.value.validateField(prop);
+
+    // nextTick(() => {
+    //   handleQueryAvailableUserList(deptInfo[0].label, prop);
+    // });
+  };
+
+  const getDeptData = () => {
+    getAllDepartments().then((res) => {
+      firstLevelDepts.value = formatDeptTree(res);
+    });
+  };
+
+  const handleQueryAvailableUserList = (deptName, realname = '') => {
+    queryAvailableUserList({
+      pageNumber: 1,
+      pageSize: 200,
+      queryParam: {
+        deptName,
+        realname,
+      },
+    }).then((res: any) => {
+      userOptions.value = (res.records || []).map((u: any) => ({
+        value: u.userId || u.id,
+        label: u.realname,
+      }));
+    });
+  };
+  const loadDetailData = (id: number) => {
+    safetyHazardInventoryQueryDetail(id).then((res: any) => {
+      Object.keys(formValue).forEach((key) => {
+        if (res[key] !== undefined) {
+          formValue[key] = res[key];
+          // formValue['responsibleDepartmentId'] = res['responsibleDepartmentId']
+          //   ? res['responsibleDepartmentId'].split(',').map((item: string) => Number(item))
+          //   : [];
+        }
+      });
+    });
+  };
+  // const getUserData = () => {
+  //   getUserList({ pageNumber: 1, pageSize: 200, queryParam: {} }).then((res: any) => {
+  //     userOptions.value = (res.records || []).map((u: any) => ({
+  //       id: u.userId || u.id,
+  //       name: u.realName || u.username,
+  //     }));
+  //   });
+  // };
+
+  onMounted(() => {
+    getDeptData();
+    handleQueryAvailableUserList('');
+    loadDetailData(Number(route.query.id as unknown as number));
+    // getUserData();
+  });
+
+  const handleSubmit = () => {
+    formRef.value?.validate((valid: boolean) => {
+      if (valid) {
+        submiting.value = true;
+        safetyHazardInventoryUpdateHazard({
+          ...formValue,
+          id: route.query.id,
+        })
+          .then(() => {
+            ElMessage.success('创建成功!');
+            router.push({ name: 'hazardManage' });
+          })
+          .finally(() => {
+            submiting.value = false;
+          });
+      }
+    });
+  };
+</script>
+<style lang="scss" scoped>
+  @use '@/styles/page-main-layout.scss' as *;
+  @use '@/styles/page-details-layout.scss' as *;
+  @use '@/styles/basic-table-action.scss' as *;
+  .editor-container {
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+    margin-right: 20px;
+    overflow: hidden;
+
+    // :deep(.w-e-text-container) {
+    //   min-height: 400px;
+    //   overflow-y: auto;
+    // }
+  }
+  // :deep(.breadcrumb .title) {
+  //   margin-left: 0;
+  // }
+
+  // .main {
+  //   display: flex;
+  //   flex-direction: column;
+  //   padding: 20px;
+  //   flex: 1;
+  //   overflow: hidden;
+  //   background-color: #fff;
+  // }
+  // .button-content {
+  //   margin-bottom: 20px;
+  // }
+
+  // .page-content {
+  //   display: flex;
+  //   justify-content: flex-end;
+  // }
+  // // :deep(.el-form) {
+  // //   flex: 1;
+  // //   overflow: hidden;
+  // //   overflow-y: auto;
+  // // }
+</style>

+ 9 - 10
src/views/production-safety/risk-identification-and-control/hazard-manage/list.vue

@@ -67,15 +67,15 @@
       <div class="table-content">
         <el-table :data="tableData.data">
           <el-table-column type="index" label="序号" width="80" />
-          <el-table-column label="楼号/区域" prop="buildingArea" width="180" />
-          <el-table-column label="楼宇名称" prop="buildingName" width="180" />
-          <el-table-column label="楼层/位置" prop="floorLocation" width="180" />
-          <el-table-column label="房间号(名称)" prop="roomName" width="180" />
-          <el-table-column label="安全责任人" prop="roomSafetyResponsibleName" width="180" />
-          <el-table-column label="是否存在风险点" prop="hasRiskPointName" width="180" />
-          <el-table-column label="风险点类别" prop="riskCategoryName" width="180" />
-          <el-table-column label="变更原因" prop="changeReason" width="170" />
-          <el-table-column label="状态" prop="statusName" width="100" />
+          <el-table-column label="危险源编号" prop="hazardCode" width="180" />
+          <el-table-column label="关键过程/作业单元" prop="keyProcessUnit" width="180" />
+          <el-table-column label="危险源名称" prop="hazardName" width="180" />
+          <el-table-column label="是否重大危险" prop="isMajorHazard" width="180" />
+          <el-table-column label="危险源来源" prop="hazardSource" width="180" />
+          <el-table-column label="涉及型号" prop="involvedDepartment" width="180" />
+          <el-table-column label="危险源管理的主责单位/部门" prop="riskManagementDept" width="240" />
+          <el-table-column label="状态" prop="statusName" width="80" />
+          <el-table-column label="变更原因" prop="changeReason" width="120" />
           <el-table-column fixed="right" min-width="240" label="操作">
             <template #default="scope">
               <el-button
@@ -117,7 +117,6 @@
 </template>
 <script lang="ts" setup>
   import { onMounted, reactive, ref } from 'vue';
-  import dayjs from 'dayjs';
   import { ElMessage } from 'element-plus';
   import { useRouter } from 'vue-router';
   import {

+ 568 - 1
src/views/production-safety/risk-identification-and-control/hazard-manage/view.vue

@@ -1 +1,568 @@
-<template>sfsdf</template>
+<template>
+  <div class="safety-platform-container">
+    <header class="safety-platform-container__header">
+      <div class="breadcrumb-title">
+        <BreadcrumbBack />
+        查看危险源清单
+      </div>
+    </header>
+    <main class="safety-platform-container__main">
+      <el-form ref="formRef" :inline="true" label-width="auto" :model="formValue" :rules="rules">
+        <!-- 基础信息 -->
+        <el-divider content-position="left">基础信息</el-divider>
+        <el-form-item label="危险源编号" prop="hazardCode">
+          <el-input
+            disabled
+            v-model="formValue.hazardCode"
+            size="large"
+            placeholder="例如:RD-202311-042"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="关键过程/作业单元" prop="keyProcessUnit">
+          <el-input
+            disabled
+            v-model="formValue.keyProcessUnit"
+            size="large"
+            placeholder="例如:张江快堆实验室(10号楼)"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="危险源名称" prop="hazardName">
+          <el-input
+            disabled
+            v-model="formValue.hazardName"
+            size="large"
+            placeholder="例如:高温熔融金属操作"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="是否重大危险源" prop="isMajorHazard">
+          <el-select disabled v-model="formValue.isMajorHazard" size="large" placeholder="请选择" style="width: 330px">
+            <el-option :value="1" label="是" />
+            <el-option :value="0" label="否" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="危险源来源" prop="hazardSource">
+          <el-input
+            disabled
+            v-model="formValue.hazardSource"
+            size="large"
+            placeholder="例如:作业单元划分"
+            style="width: 330px"
+          />
+        </el-form-item>
+
+        <!-- 部门责任 -->
+        <el-form-item label="涉及部门" prop="involvedDepartment">
+          <el-input
+            disabled
+            v-model="formValue.involvedDepartment"
+            size="large"
+            placeholder="例如:核材料研究部/设备管理部(支持手动输入多部门)"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="风险管理部门" prop="riskManagementDept">
+          <!-- <el-cascader
+            disabled
+            :ref="(el) => (cascaderRef['riskManagementDept'] = el)"
+            v-model="formValue.riskManagementDeptId"
+            size="large"
+            style="width: 330px"
+            :options="firstLevelDepts"
+            :props="cascaderProp"
+            :show-all-levels="false"
+            placeholder="请选择"
+            filterable
+            @change="() => handleChangeDept('riskManagementDept')"
+          /> -->
+          <el-input
+            disabled
+            v-model="formValue.riskManagementDept"
+            size="large"
+            placeholder="请输入"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="协作部门" prop="cooperationDept">
+          <!-- <el-cascader
+            disabled
+            v-model="formValue.cooperationDeptId"
+            :ref="(el) => (cascaderRef['cooperationDept'] = el)"
+            size="large"
+            style="width: 330px"
+            :options="firstLevelDepts"
+            :props="cascaderProp"
+            :show-all-levels="false"
+            placeholder="请选择"
+            filterable
+            @change="handleChangeDept('cooperationDept')"
+          /> -->
+          <el-input
+            disabled
+            v-model="formValue.cooperationDept"
+            size="large"
+            placeholder="请输入"
+            style="width: 330px"
+          />
+        </el-form-item>
+
+        <!-- 风险评估 -->
+        <el-form-item label="可能后果" prop="possibleConsequences">
+          <el-input
+            disabled
+            v-model="formValue.possibleConsequences"
+            size="large"
+            placeholder="例如:灼伤、火灾"
+            style="width: 330px"
+          />
+        </el-form-item>
+
+        <el-divider content-position="left">固有风险评估</el-divider>
+        <el-form-item label="可能性(M)" prop="inherentRiskM">
+          <!-- <el-select v-model="formValue.inherentRiskM" size="large" placeholder="1-5" style="width: 330px">
+            <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number
+            disabled
+            :step="1"
+            :precision="0"
+            v-model="formValue.inherentRiskM"
+            :min="1"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="暴露频率(E)" prop="inherentRiskE">
+          <!-- <el-select v-model="formValue.inherentRiskE" size="large" placeholder="1-6" style="width: 330px">
+            <el-option v-for="n in 6" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number
+            disabled
+            :step="1"
+            :precision="0"
+            v-model="formValue.inherentRiskE"
+            :min="1"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="严重度(S)" prop="inherentRiskS">
+          <!-- <el-select v-model="formValue.inherentRiskS" size="large" placeholder="1-5" style="width: 330px">
+                  <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+                </el-select> -->
+          <el-input-number
+            disabled
+            :step="1"
+            :precision="0"
+            v-model="formValue.inherentRiskS"
+            :min="1"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="风险值(R)" prop="inherentRiskR">
+          <el-input
+            v-model="formValue.inherentRiskR"
+            size="large"
+            disabled
+            placeholder="自动计算: M×E×S"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="风险等级" prop="inherentRiskLevel">
+          <el-select
+            disabled
+            v-model="formValue.inherentRiskLevel"
+            size="large"
+            placeholder="请选择"
+            style="width: 330px"
+          >
+            <el-option label="B" value="B" />
+            <el-option label="C" value="C" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="升级等级" prop="inherentRiskUpgrade">
+          <el-input
+            disabled
+            v-model="formValue.inherentRiskUpgrade"
+            size="large"
+            placeholder="例如:2级"
+            style="width: 330px"
+          />
+        </el-form-item>
+
+        <!-- 管控措施 -->
+        <el-divider content-position="left">管控措施</el-divider>
+        <el-form-item label="主要管控措施" prop="controlMeasures">
+          <el-input
+            disabled
+            type="textarea"
+            :rows="3"
+            v-model="formValue.controlMeasures"
+            size="large"
+            placeholder="每条措施用分号分隔,例如:1.穿戴防护服;2.设置隔离区;3.定期检查冷却系统"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="主责部门" prop="controlMainDept">
+          <!-- <el-cascader
+            disabled
+            v-model="formValue.controlMainDeptId"
+            :ref="(el) => (cascaderRef['controlMainDept'] = el)"
+            size="large"
+            style="width: 330px"
+            :options="firstLevelDepts"
+            :props="cascaderProp"
+            :show-all-levels="false"
+            placeholder="请选择"
+            filterable
+            @change="handleChangeDept('controlMainDept')"
+          /> -->
+          <el-input
+            disabled
+            v-model="formValue.controlMainDept"
+            size="large"
+            placeholder="请输入"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="协作部门" prop="controlCoopDept">
+          <!-- <el-cascader
+            disabled
+            v-model="formValue.controlCoopDeptId"
+            :ref="(el) => (cascaderRef['controlCoopDept'] = el)"
+            size="large"
+            style="width: 330px"
+            :options="firstLevelDepts"
+            :props="cascaderProp"
+            :show-all-levels="false"
+            placeholder="请选择"
+            filterable
+            @change="handleChangeDept('controlCoopDept')"
+          /> -->
+          <el-input
+            disabled
+            v-model="formValue.controlCoopDept"
+            size="large"
+            placeholder="请输入"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="完成期限" prop="completionDeadline">
+          <el-date-picker
+            disabled
+            v-model="formValue.completionDeadline"
+            type="date"
+            size="large"
+            placeholder="选择日期"
+            format="YYYY-MM-DD"
+            value-format="YYYY-MM-DD"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="完成状态" prop="completionStatus">
+          <el-input
+            disabled
+            v-model="formValue.completionStatus"
+            size="large"
+            placeholder="例如:措施1,2已完成"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="验证状态" prop="verificationStatus">
+          <el-input
+            disabled
+            v-model="formValue.verificationStatus"
+            size="large"
+            placeholder="例如:措施1已验证"
+            style="width: 330px"
+          />
+        </el-form-item>
+
+        <!-- 剩余风险 -->
+        <el-divider content-position="left">剩余风险评估</el-divider>
+        <el-form-item label="可能性(M)" prop="controlRiskM">
+          <!-- <el-select v-model="formValue.controlRiskM" size="large" placeholder="1-5" style="width: 330px">
+            <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number
+            disabled
+            :step="1"
+            :precision="0"
+            v-model="formValue.controlRiskM"
+            :min="1"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="暴露频率(E)" prop="controlRiskE">
+          <!-- <el-select v-model="formValue.controlRiskE" size="large" placeholder="1-6" style="width: 330px">
+            <el-option v-for="n in 6" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number
+            disabled
+            :step="1"
+            :precision="0"
+            v-model="formValue.controlRiskE"
+            :min="1"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="严重度(S)" prop="controlRiskS">
+          <!-- <el-select v-model="formValue.controlRiskS" size="large" placeholder="1-5" style="width: 330px">
+            <el-option v-for="n in 5" :key="n" :label="n" :value="n" />
+          </el-select> -->
+          <el-input-number
+            disabled
+            :step="1"
+            :precision="0"
+            v-model="formValue.controlRiskS"
+            :min="1"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="风险值(R)" prop="controlRiskR">
+          <el-input
+            v-model="formValue.controlRiskR"
+            size="large"
+            disabled
+            placeholder="自动计算: M×E×S"
+            style="width: 330px"
+          />
+        </el-form-item>
+        <el-form-item label="风险等级" prop="controlRiskLevel">
+          <el-select
+            disabled
+            v-model="formValue.controlRiskLevel"
+            size="large"
+            placeholder="请选择"
+            style="width: 330px"
+          >
+            <!-- <el-option label="A" value="A" />
+            <el-option label="B" value="B" />
+            <el-option label="C" value="C" /> -->
+            <el-option label="D" value="D" />
+          </el-select>
+        </el-form-item>
+
+        <!-- 备注 -->
+        <el-form-item label="备注" prop="remarks" style="width: 87.2%">
+          <el-input
+            disabled
+            type="textarea"
+            v-model="formValue.remarks"
+            size="large"
+            :rows="7"
+            placeholder="例如:需每月提交检查报告"
+          />
+        </el-form-item>
+      </el-form>
+    </main>
+    <footer class="safety-platform-container__footer">
+      <el-button @click="$router.push({ name: 'hazardManage' })">返回</el-button>
+    </footer>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { ref, reactive, onMounted, nextTick } from 'vue';
+  import { useRouter, useRoute } from 'vue-router';
+  import { ElMessage } from 'element-plus';
+  import { getAllDepartments } from '@/api/auth/dept';
+  import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
+
+  import {
+    queryAvailableUserList,
+    safetyHazardInventoryQueryDetail,
+    safetyHazardInventorySaveHazard,
+  } from '@/api/production-safety/responsibility-implementation';
+
+  const router = useRouter();
+  const route = useRoute();
+  const formRef = ref<any>(null);
+  const submiting = ref(false);
+
+  const userOptions = ref<any[]>([]);
+  const firstLevelDepts = ref<any[]>([]);
+  const cascaderProp = {
+    expandTrigger: 'click',
+    checkStrictly: true,
+    value: 'id',
+    label: 'deptName',
+  };
+  const cascaderRef = ref<any>({});
+
+  const formValue = reactive({
+    hazardCode: '',
+    keyProcessUnit: '',
+    hazardName: '',
+    isMajorHazard: undefined as number | undefined,
+    hazardSource: '',
+    involvedDepartment: '',
+    riskManagementDept: '',
+    riskManagementDeptId: [] as number[],
+    cooperationDept: '',
+    cooperationDeptId: [] as number[],
+    possibleConsequences: '',
+    inherentRiskM: undefined as number | undefined,
+    inherentRiskE: undefined as number | undefined,
+    inherentRiskS: undefined as number | undefined,
+    inherentRiskR: 0, // 自动计算
+    inherentRiskLevel: '',
+    inherentRiskUpgrade: '',
+    controlMeasures: '',
+    controlMainDept: '',
+    controlMainDeptId: [] as number[],
+    controlCoopDept: '',
+    controlCoopDeptId: [] as number[],
+    completionDeadline: '',
+    completionStatus: '',
+    verificationStatus: '',
+    controlRiskM: undefined as number | undefined,
+    controlRiskE: undefined as number | undefined,
+    controlRiskS: undefined as number | undefined,
+    controlRiskR: 0,
+    controlRiskLevel: '',
+    remarks: '',
+  });
+
+  const rules = reactive({
+    hazardCode: [{ required: true, message: '请输入危险源编号', trigger: 'blur' }],
+    keyProcessUnit: [{ required: true, message: '请输入关键工艺单元', trigger: 'blur' }],
+    hazardName: [{ required: true, message: '请输入危险源名称', trigger: 'blur' }],
+    isMajorHazard: [{ required: true, message: '请选择是否重大危险源', trigger: 'change' }],
+    hazardSource: [{ required: true, message: '请输入危险源来源', trigger: 'blur' }],
+    involvedDepartment: [{ required: true, message: '请输入涉及部门', trigger: 'blur' }],
+    riskManagementDept: [{ required: true, message: '请选择风险管理部门', trigger: 'change' }],
+    cooperationDept: [{ required: true, message: '请选择协作部门', trigger: 'change' }],
+    possibleConsequences: [{ required: true, message: '请输入可能后果', trigger: 'blur' }],
+    inherentRiskM: [{ required: true, message: '请选择可能性', trigger: 'change' }],
+    inherentRiskE: [{ required: true, message: '请选择暴露频率', trigger: 'change' }],
+    inherentRiskS: [{ required: true, message: '请选择严重度', trigger: 'change' }],
+    inherentRiskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
+    controlMeasures: [{ required: true, message: '请输入管控措施', trigger: 'blur' }],
+    controlMainDept: [{ required: true, message: '请选择主责部门', trigger: 'change' }],
+    controlRiskM: [{ required: true, message: '请选择剩余风险可能性', trigger: 'change' }],
+    controlRiskE: [{ required: true, message: '请选择剩余风险暴露频率', trigger: 'change' }],
+    controlRiskS: [{ required: true, message: '请选择剩余风险严重度', trigger: 'change' }],
+    controlRiskLevel: [{ required: true, message: '请选择剩余风险等级', trigger: 'change' }],
+  });
+
+  const handleChangeDept = (prop) => {
+    const cascader = cascaderRef.value?.[prop];
+    const deptInfo = cascader?.getCheckedNodes();
+    formValue[prop] = deptInfo[0]?.label;
+    formRef.value.validateField(prop);
+
+    // nextTick(() => {
+    //   handleQueryAvailableUserList(deptInfo[0].label, prop);
+    // });
+  };
+
+  const getDeptData = () => {
+    getAllDepartments().then((res) => {
+      firstLevelDepts.value = formatDeptTree(res);
+    });
+  };
+
+  const loadDetailData = (id: number) => {
+    safetyHazardInventoryQueryDetail(id).then((res: any) => {
+      Object.keys(formValue).forEach((key) => {
+        if (res[key] !== undefined) {
+          formValue[key] = res[key];
+          formValue['responsibleDepartmentId'] = res['responsibleDepartmentId']
+            ? res['responsibleDepartmentId'].split(',').map((item: string) => Number(item))
+            : [];
+        }
+      });
+    });
+  };
+
+  const handleQueryAvailableUserList = (deptName, realname = '') => {
+    queryAvailableUserList({
+      pageNumber: 1,
+      pageSize: 200,
+      queryParam: {
+        deptName,
+        realname,
+      },
+    }).then((res: any) => {
+      userOptions.value = (res.records || []).map((u: any) => ({
+        value: u.userId || u.id,
+        label: u.realname,
+      }));
+    });
+  };
+
+  // const getUserData = () => {
+  //   getUserList({ pageNumber: 1, pageSize: 200, queryParam: {} }).then((res: any) => {
+  //     userOptions.value = (res.records || []).map((u: any) => ({
+  //       id: u.userId || u.id,
+  //       name: u.realName || u.username,
+  //     }));
+  //   });
+  // };
+
+  onMounted(() => {
+    getDeptData();
+    handleQueryAvailableUserList('');
+    loadDetailData(Number(route.query.id));
+    // getUserData();
+  });
+
+  const handleSubmit = () => {
+    formRef.value?.validate((valid: boolean) => {
+      if (valid) {
+        submiting.value = true;
+        safetyHazardInventorySaveHazard({
+          ...formValue,
+        })
+          .then(() => {
+            ElMessage.success('创建成功!');
+            router.push({ name: 'hazardManage' });
+          })
+          .finally(() => {
+            submiting.value = false;
+          });
+      }
+    });
+  };
+</script>
+<style lang="scss" scoped>
+  @use '@/styles/page-main-layout.scss' as *;
+  @use '@/styles/page-details-layout.scss' as *;
+  @use '@/styles/basic-table-action.scss' as *;
+  .editor-container {
+    border: 1px solid #dcdfe6;
+    border-radius: 4px;
+    margin-right: 20px;
+    overflow: hidden;
+
+    // :deep(.w-e-text-container) {
+    //   min-height: 400px;
+    //   overflow-y: auto;
+    // }
+  }
+  // :deep(.breadcrumb .title) {
+  //   margin-left: 0;
+  // }
+
+  // .main {
+  //   display: flex;
+  //   flex-direction: column;
+  //   padding: 20px;
+  //   flex: 1;
+  //   overflow: hidden;
+  //   background-color: #fff;
+  // }
+  // .button-content {
+  //   margin-bottom: 20px;
+  // }
+
+  // .page-content {
+  //   display: flex;
+  //   justify-content: flex-end;
+  // }
+  // // :deep(.el-form) {
+  // //   flex: 1;
+  // //   overflow: hidden;
+  // //   overflow-y: auto;
+  // // }
+</style>