Преглед на файлове

fix:修复风险清单管理

sunqijun преди 1 месец
родител
ревизия
b20686c499
променени са 18 файла, в които са добавени 305 реда и са изтрити 223 реда
  1. 2 0
      src/api/inventory/index.ts
  2. 18 1
      src/api/safety-organization-management/index.ts
  3. 16 1
      src/api/safety-system-construction-work-plan/index.ts
  4. 14 12
      src/router/routers/production-safety-router/productionSafetySystem.ts
  5. 8 31
      src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/safetyOrganizationSystemManagementDetail.vue
  6. 6 6
      src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/configs/tables.ts
  7. 45 49
      src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagement.vue
  8. 1 1
      src/views/production-safety/productionSafetySystem/safetySystemConstructionWorkPlanManagement/configs/tables.ts
  9. 46 1
      src/views/production-safety/productionSafetySystem/safetySystemConstructionWorkPlanManagement/safetySystemConstructionWorkPlanManagement.vue
  10. 25 14
      src/views/production-safety/risk-identification-and-control/hazard-approval-manage/add.vue
  11. 38 33
      src/views/production-safety/risk-identification-and-control/risk-manage/add.vue
  12. 13 12
      src/views/production-safety/risk-identification-and-control/risk-manage/change.vue
  13. 36 21
      src/views/production-safety/risk-identification-and-control/risk-manage/edit.vue
  14. 4 2
      src/views/production-safety/risk-identification-and-control/risk-manage/list.vue
  15. 1 1
      src/views/production-safety/risk-identification-and-control/risk-manage/view.vue
  16. 6 5
      src/views/production-safety/safetyAssessment/inventory/inventory.vue
  17. 0 12
      src/views/production-safety/safetyTrainingAndEducation/educationTrainingPlanManagement/educationTrainingPlanManagement.vue
  18. 26 21
      src/views/production-safety/safetyTrainingAndEducation/educationTrainingPlanManagementDept/components/addTrainingInformation.vue

+ 2 - 0
src/api/inventory/index.ts

@@ -31,6 +31,7 @@ export interface BusinessCertification {
   departmentCode: string; // 部门编码
   templateId?: any; // 审批模板ID
   departmentName?: string; // 部门名称
+  inStoreTime?: string; // 入库日期
 }
 
 /**
@@ -73,6 +74,7 @@ export interface SaveApprovalReq {
   /** 退回原因 */
   returnReason?: string;
   templateId?: string;
+  code?: string | number;
 }
 
 /**

+ 18 - 1
src/api/safety-organization-management/index.ts

@@ -2,7 +2,7 @@
  * @Author: liuJie
  * @Date: 2026-02-05 11:15:09
  * @LastEditors: liuJie
- * @LastEditTime: 2026-02-09 16:13:40
+ * @LastEditTime: 2026-03-07 22:05:07
  * @Describe: 安全组织体系管理
  */
 
@@ -97,3 +97,20 @@ export const delEmployee = (id) => {
     method: 'delete',
   });
 };
+
+    
+/**
+ * 导出数据
+ * @param params - 导出筛选条件
+ * @returns Promise<Blob> Excel 文件流
+ */
+export const exportSafetyOrganizationSystemManagement = (params)=>{
+  return http.request({
+    url: `/safetyorguser/exportSafetyOrgUser`,
+    method: 'get',
+    params,
+    responseType: 'blob',
+  }, {
+    isTransformResponse: false,
+  });
+}

+ 16 - 1
src/api/safety-system-construction-work-plan/index.ts

@@ -2,7 +2,7 @@
  * @Author: liuJie
  * @Date: 2026-02-06 16:29:04
  * @LastEditors: liuJie
- * @LastEditTime: 2026-02-09 16:16:14
+ * @LastEditTime: 2026-03-07 22:19:23
  * @Describe: 安全体系建设工作计划管理(管理员)
  */
 import { http } from '@/utils/http/axios';
@@ -211,6 +211,21 @@ export function queryViewSender(data: ViewSenderParamsType) {
   });
 }
 
+/**
+ * @description: 导出
+ * @return {*}
+ */
+export const exportTableData = (params)=> {
+    return http.request({
+        url: `/safety-culture/exportProductionEducationTrainingPlan`,
+        method: 'get',
+        params,
+        responseType: 'blob',
+    }, {
+        isTransformResponse: false,
+    });
+}
+
 // —————————————————部门端———————————————————
 /**
  * 查询安全体系建设工作计划列表(部门端分页)

+ 14 - 12
src/router/routers/production-safety-router/productionSafetySystem.ts

@@ -212,13 +212,13 @@ const productionSafetySystemRoutes: RouteComponent[] = [{
       },
     },
     {
-      id: 90027,
+      id: 90028,
       parentId: 9002,
-      name: 'SafetyOrganizationSystemManagement',
-      path: 'safety-organization-system-management',
-      component: '/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagement',
+      name: 'SafetySystemConstructionWorkPlanManagementViewSender',
+      path: 'safety-system-construction-work-plan-management-view-sender',
+      component: '/production-safety/productionSafetySystem/safetySystemConstructionWorkPlanManagement/safetySystemConstructionWorkPlanManagementViewSender',
       meta: {
-        title: '安全组织体系管理',
+        title: '安全体系建设工作计划管理(管理员)-查看发送对象',
         icon: 'OverviewIcon',
         isRoot: false,
         hidden: false,
@@ -226,14 +226,15 @@ const productionSafetySystemRoutes: RouteComponent[] = [{
       },
     },
     {
-      id: 90028,
+      id: 90027,
       parentId: 9002,
-      name: 'SafetySystemConstructionWorkPlanManagementViewSender',
-      path: 'safety-system-construction-work-plan-management-view-sender',
-      component: '/production-safety/productionSafetySystem/safetySystemConstructionWorkPlanManagement/safetySystemConstructionWorkPlanManagementViewSender',
+      name: 'SafetyOrganizationSystemManagement',
+      path: 'safety-organization-system-management',
+      component: '/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagement',
       meta: {
-        title: '安全体系建设工作计划管理(管理员)-查看发送对象',
+        title: '安全组织体系管理',
         icon: 'OverviewIcon',
+        activeMenu: '/work-safety/productionSafetySystem/safetyOrganizationSystemManagement',
         isRoot: false,
         hidden: false,
         noCache: false,
@@ -243,10 +244,11 @@ const productionSafetySystemRoutes: RouteComponent[] = [{
         id: 90029,
         parentId: 9002,
         name: 'SafetyOrganizationSystemManagementItem',
-        path: '/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagementItem',
-        component: () => import('/src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagementItem.vue'),
+        path: 'safety-organization-systemManagement-item',
+        component: '/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagementItem',
         meta: {
             title: '安全组织体系管理详情',
+            activeMenu: '/work-safety/productionSafetySystem/safetyOrganizationSystemManagement',
             icon: 'OverviewIcon',
             isRoot: false,
             hidden: false,

+ 8 - 31
src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/safetyOrganizationSystemManagementDetail.vue

@@ -43,8 +43,8 @@
       <!-- 状态 -->
       <el-form-item label="状态:" prop="status" required>
         <el-radio-group v-model="form.status" :disabled="isViewMode">
-          <el-radio value="1">启用</el-radio>
-          <el-radio value="2">禁用</el-radio>
+          <el-radio :value="1">启用</el-radio>
+          <el-radio :value="2">禁用</el-radio>
         </el-radio-group>
       </el-form-item>
     </el-form>
@@ -61,7 +61,7 @@
   import { computed, onMounted, ref } from 'vue';
   import { useRoute, useRouter } from 'vue-router';
   import { ElMessage } from 'element-plus';
-  import { INVENTORY_FORM_CONFIG, INVENTORY_FORM_DATA, FORM_RULES } from '../configs/form';
+  import { FORM_RULES } from '../configs/form';
   import {
     getSafetySystemList,
     addEmployee,
@@ -79,26 +79,13 @@
   const isEditMode = computed(() => operate.value === 'employee-edit');
   const isViewMode = computed(() => operate.value === 'employee-view');
 
-  // const { ruleFormData, formRules, ruleFormConfig, cloneRuleFormData, beforeRouteLeave } =
-  //     useFormConfigHook(INVENTORY_FORM_CONFIG, INVENTORY_FORM_DATA);
-
-  // 查看模式下,所有字段设为只读
-  const viewFormConfig = ref(
-    INVENTORY_FORM_CONFIG.map((item) => ({
-      ...item,
-      componentProps: {
-        ...item.componentProps,
-        disabled: true,
-      },
-    })),
-  );
   interface FormDataType {
     id?: number;
     orgId?: string;
     employeeId: string;
     employeeName: string;
     jobResp: string;
-    status: string;
+    status: string|number;
     selectedOrg?: any;
   }
 
@@ -108,7 +95,7 @@
     employeeId: '',
     employeeName: '',
     jobResp: '',
-    status: '1',
+    status: 1,
   });
   const selectedOrg = ref({});
   // 表单验证规则
@@ -159,7 +146,6 @@
         }
       }
     }
-
     return null;
   };
 
@@ -174,12 +160,6 @@
       selectedOrg.value = selectedNode;
     }
   };
-  const computedFormConfig = computed(() => {
-    if (isViewMode.value) {
-      return viewFormConfig.value;
-    }
-    // return ruleFormConfig.value;
-  });
 
   const formRef = ref();
 
@@ -194,12 +174,11 @@
     try {
       const res = await employeeDetail(currentId.value);
       if (res) {
-        // 映射接口字段到表单字段
+        // 详情页面(映射接口字段到表单字段
         Object.assign(form.value, res);
       }
-      // cloneRuleFormData();
     } catch (e) {
-      console.error('获取物品库存详情失败:', e);
+      console.error('获取详情失败:', e);
       ElMessage.error('获取详情失败');
     }
   };
@@ -223,15 +202,13 @@
 
       router.back();
     } catch (e) {
-      console.error('保存物品库存失败:', e);
+      console.error('保存失败:', e);
       ElMessage.error('保存失败,请重试');
     }
   };
 
   onMounted(() => {
     fetchSafetyOrganizationTeamList();
-    // cloneRuleFormData();
-    // beforeRouteLeave();
     if (isEditMode.value || isViewMode.value) {
       getDetail();
     }

+ 6 - 6
src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/configs/tables.ts

@@ -2,7 +2,7 @@
  * @Author: liuJie
  * @Date: 2026-01-27 16:29:28
  * @LastEditors: liuJie
- * @LastEditTime: 2026-02-06 15:07:32
+ * @LastEditTime: 2026-03-07 20:34:07
  * @Describe: file describe
  */
 import type { TableColumnProps } from '@/types/basic-table';
@@ -14,7 +14,7 @@ export const TABLE_OPTIONS = {
   maxHeight: 'calc(70vh - 150px)',
 };
 
-export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
+export const TABLE_COLUMNS: TableColumnProps[] = [
   {
     label: '编号',
     type: 'index',
@@ -36,6 +36,7 @@ export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
   {
     label: '状态',
     prop: 'status',
+    slot: 'status',
     align: 'left',
     minWidth: '120px',
   },
@@ -44,7 +45,7 @@ export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
     label: '组织名称',
     prop: 'orgName',
     align: 'left',
-    minWidth: '120px',
+    minWidth: '140px',
   },
   {
     label: '岗位职责',
@@ -54,10 +55,9 @@ export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
   },
   {
     label: '添加时间',
-    prop: 'status',
-    slot: 'status',
+    prop: 'createdAt',
     align: 'center',
-    minWidth: '100px',
+    minWidth: '140px',
   },
   {
     label: '操作',

+ 45 - 49
src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagement.vue

@@ -6,20 +6,24 @@
     <main class="safety-platform-container__main flex">
       <div class="nav">
         <el-button type="primary" :icon="Plus" @click="addTeam('parent')"> 添加组织 </el-button>
+        
         <div class="collapse-wrapper">
+            <!-- expand-icon-position="left" 版本小了,不支持 -->
           <el-collapse accordion v-model="activeName" v-if="fetchSafetyOrganizationList.length > 0">
             <el-collapse-item :name="item.orgId" v-for="item in fetchSafetyOrganizationList">
               <template #title="{ isActive }">
                 <div :class="['title-wrapper', { 'is-active': isActive }]">
-                  <span @click.stop="querySafetyTeamData('parent', item)">{{ item.orgName }}</span>
+                  <span @click.stop="querySafetyTeamData('parent', item)">
+                    {{ item.orgName }}
+                  </span>
                   <div class="handler">
-                    <el-button link size="small" type="primary" @click.stop="handleCreateSafetySystem('children', item)"
-                      >新增子组织</el-button
+                    <el-button :icon="Plus" size="small" type="default" dashed @click.stop="handleCreateSafetySystem('children', item)"
+                      ></el-button
                     >
-                    <el-button link size="small" type="primary" @click.stop="handleEditSafetySystem('parent', item, '')"
+                    <el-button size="small" type="primary" link @click.stop="handleEditSafetySystem('parent', item, '')"
                       >编辑</el-button
                     >
-                    <el-button link size="small" type="danger" @click.stop="handleDelSafetySystem('parent', item)"
+                    <el-button  size="small" type="danger" link @click.stop="handleDelSafetySystem('parent', item)"
                       >删除</el-button
                     >
                   </div>
@@ -67,7 +71,11 @@
           @confirmAddSafetySystem="confirmAddSafetySystemCallback"
         />
       </div>
-      <div class="search-table-container">
+      <div class="search-table-container table-content">
+        <div style="margin-bottom:20px">
+            <el-button type="primary"  @click="handleCreate"> 添加 </el-button>
+            <el-button plain  @click="handleImport">导入</el-button>
+        </div>
         <header>
           <div class="act-search">
             <section class="select-box">
@@ -82,8 +90,8 @@
               <div class="select-box--item">
                 <span>状态:</span>
                 <el-select v-model="tableQuery.queryParam.status" placeholder="请选择状态" clearable>
-                  <el-option label="启用" value="1" />
-                  <el-option label="禁用" value="2" />
+                  <el-option label="启用" :value="1" />
+                  <el-option label="禁用" :value="2" />
                 </el-select>
               </div>
               <div class="select-box--item">
@@ -103,20 +111,12 @@
             <section class="search-btn">
               <el-button type="primary" @click="handleSearch">查询</el-button>
               <el-button @click="handleReset">重置</el-button>
+              <el-button plain  @click="handleDownload">导出</el-button>
             </section>
           </div>
         </header>
 
         <div class="batch-table">
-          <div style="position: relative">
-            <el-button type="primary" class="search-table-container--button" @click="handleCreate"> 添加 </el-button>
-            <!-- <el-button plain class="search-table-container--button" @click="handleImport">
-                            导入
-                        </el-button>
-                        <el-button plain class="search-table-container--button" @click="handleDownload">
-                            导出
-                        </el-button> -->
-          </div>
           <BasicTable
             ref="basicTableRef"
             :tableData="tableData"
@@ -151,7 +151,7 @@
       :visible="batchImportVisible"
       :import-api-url="importApiUrl"
       :template-url="templateUrl"
-      template-name="下载模板"
+      template-name="安全组织体系"
       :show-template="false"
       @close="batchImportVisible = false"
       @update="handleUpdate"
@@ -162,14 +162,12 @@
 <script setup lang="ts">
   import { onMounted, reactive, ref } from 'vue';
   import { ElMessage, ElMessageBox } from 'element-plus';
-  import { Plus } from '@element-plus/icons-vue';
   import BasicTable from '@/components/BasicTable.vue';
   import useTableConfig from '@/hooks/useTableConfigHook';
   import ActionButton from '@/components/ActionButton.vue';
-  import { TABLE_OPTIONS, INVENTORY_TABLE_COLUMNS } from './configs/tables';
+  import { TABLE_OPTIONS, TABLE_COLUMNS } from './configs/tables';
   import { useRouter } from 'vue-router';
   import type { QueryPageRequest } from '@/types/basic-query';
-  import { queryInventoryManage, deleteInventory, exportInventory } from '@/api/inventory';
   import {
     getSafetySystemList,
     addSafetySystem,
@@ -177,21 +175,26 @@
     deleteSafetySystem,
     fetchTableList,
     delEmployee,
+    exportSafetyOrganizationSystemManagement
   } from '@/api/safety-organization-management';
   import { downloadByData } from '@/utils/file/download';
   import BatchImport from '@/components/batch-import/BatchImport.vue';
   import { useGlobSetting } from '@/hooks/setting';
   import urlJoin from 'url-join';
-  import { OptionsProps } from '@/types/log/constants';
-  import { calculateTreeData } from '@/utils';
-  import { getAllDepartments } from '@/api/auth/dept';
   import AddSafetySystem from './components/addSafetySystem.vue';
+  import {
+  Delete,
+  Edit,
+  Plus,
+} from '@element-plus/icons-vue'
+
+const position = ref('left')
 
   const router = useRouter();
   // 表格
   const basicTableRef = ref<InstanceType<typeof BasicTable>>();
 
-  const { tableConfig, pagination } = useTableConfig(INVENTORY_TABLE_COLUMNS, TABLE_OPTIONS);
+  const { tableConfig, pagination } = useTableConfig(TABLE_COLUMNS, TABLE_OPTIONS);
 
   const tableData = ref<any[]>([]);
 
@@ -230,21 +233,11 @@
     try {
       const res = await fetchTableList(tableQuery);
       if (res) {
-        // 映射返回数据字段到表格字段
-        tableData.value = res.records.map((item) => ({
-          id: item.id,
-          itemName: item.stuffName, // 物品名称
-          warehouseDate: item.inStoreTime, // 入库日期
-          itemQuantity: item.stuffQty, // 物品数量
-          handler: item.createdUserName, // 经办人
-          remarks: item.remark, // 备注
-          status: item.status, // 状态:1-启用,2-禁用
-          statusName: item.statusName, // 状态名称
-        }));
+        tableData.value = res.records
         pagination.total = res.totalRow;
       }
     } catch (e) {
-      console.error('获取物品库存列表失败:', e);
+      console.error('获取列表失败:', e);
       tableData.value = [];
       pagination.total = 0;
     } finally {
@@ -402,7 +395,7 @@
   // 批量导入
   const batchImportVisible = ref(false);
   const { urlPrefix } = useGlobSetting();
-  const importApiUrl = ref(urlJoin(urlPrefix, '/inventory/importInventory'));
+  const importApiUrl = ref(urlJoin(urlPrefix, '/safetyorguser/importSafetyOrgUser'));
   const templateUrl = ref('./skyeye-file-upload/sfysecurity/TEMPLATE/import-inventory-template.xlsx');
 
   const handleImport = () => {
@@ -416,19 +409,14 @@
 
   const handleDownload = async () => {
     try {
-      const exportParams = {
-        stuffName: tableQuery.queryParam.stuffName || undefined,
-        status: tableQuery.queryParam.status,
-        ids: tableQuery.queryParam.ids.length > 0 ? tableQuery.queryParam.ids : undefined,
-      };
-      const response = await exportInventory(exportParams);
+      const response = await exportSafetyOrganizationSystemManagement(tableQuery.queryParam);
       if (response) {
-        const fileName = `物品库存管理_${new Date().toISOString().split('T')[0]}.xlsx`;
+        const fileName = `安全组织体系管理_${new Date().toISOString().split('T')[0]}.xlsx`;
         downloadByData(response, fileName);
         ElMessage.success('导出成功');
       }
     } catch (e) {
-      console.error('导出物品库存失败:', e);
+      console.error('导出安全组织体系管理失败:', e);
       ElMessage.error('导出失败,请重试');
     }
   };
@@ -484,13 +472,21 @@
   @use '@/styles/page-main-layout.scss' as *;
   @use '@/styles/basic-table-action.scss' as *;
   @use '@/views/traffic/violation/style/act-search-table.scss' as *;
-
+  .table-content {
+  }
   .nav {
-    width: 500px;
+    flex: 0 0 300px;
     margin-right: 15px;
     padding-right: 15px;
     border-right: 1px solid #eee;
-
+    :deep(.collapse-title) {
+        flex: 1 0 90%;
+        order: 1;
+        .el-collapse-item__header {
+            flex: 1 0 auto;
+            order: -1;
+        }
+    }
     .collapse-wrapper {
       margin-top: 10px;
 

+ 1 - 1
src/views/production-safety/productionSafetySystem/safetySystemConstructionWorkPlanManagement/configs/tables.ts

@@ -74,7 +74,7 @@ export const WORK_PLAN_TABLE_COLUMNS: TableColumnProps[] = [
   },
   {
     label: '责任部门',
-    prop: 'responsibleDeptNames',
+    prop: 'responsibleDeptName',
     align: 'left',
     minWidth: '120px',
   },

+ 46 - 1
src/views/production-safety/productionSafetySystem/safetySystemConstructionWorkPlanManagement/safetySystemConstructionWorkPlanManagement.vue

@@ -8,6 +8,7 @@
         <header>
           <div style="position: relative">
             <el-button type="primary" class="search-table-container--button" @click="handleCreate"> 添加 </el-button>
+            <el-button plain  class="search-table-container--button" @click="handleImport">导入</el-button>
           </div>
 
           <div class="act-search">
@@ -64,6 +65,7 @@
             <section class="search-btn">
               <el-button type="primary" @click="handleSearch">查询</el-button>
               <el-button @click="handleReset">重置</el-button>
+              <el-button plain  @click="handleDownload">导出</el-button>
             </section>
           </div>
         </header>
@@ -128,7 +130,7 @@
               {{ (scope.row.issuedCount === 0 && scope.row.status === 1) ? '-' : scope.row.issuedCount }}
             </template>
             <template #feedbackRatio="scope">
-              {{ (scope.row.feedbackRatio === 0 && scope.row.status === 1) ? '-' : scope.row.feedbackRatio }}
+              {{ (scope.row.feedbackRatio === 0 && scope.row.status === 1) ? '-' : scope.row.feedbackRatio+'%' }}
             </template>
           </BasicTable>
         </div>
@@ -181,6 +183,16 @@
         </template>
       </el-dialog>
     </main>
+    <BatchImport
+      v-if="batchImportVisible"
+      :visible="batchImportVisible"
+      :import-api-url="importApiUrl"
+      :template-url="templateUrl"
+      template-name="安全组织体系"
+      :show-template="false"
+      @close="batchImportVisible = false"
+      @update="handleUpdate"
+    />
   </div>
 </template>
 
@@ -203,11 +215,16 @@
     cancelWorkPlan,
     issueWorkPlan,
     deleteWorkPlan,
+    exportTableData,
     type IssueWorkPlanParams,
   } from '@/api/safety-system-construction-work-plan';
 
   import { queryUserGroupPage } from '@/api/system/person-group';
   import { IssueWorkPlanFormRules } from './configs/form';
+  import { downloadByData } from '@/utils/file/download';
+  import BatchImport from '@/components/batch-import/BatchImport.vue';
+  import { useGlobSetting } from '@/hooks/setting';
+  import urlJoin from 'url-join';
 
   const router = useRouter();
   const groupList = ref<any>([]);
@@ -443,6 +460,34 @@
       },
     });
   };
+    // 批量导入
+  const batchImportVisible = ref(false);
+  const { urlPrefix } = useGlobSetting();
+  const importApiUrl = ref(urlJoin(urlPrefix, '/safety-culture/importProductionEducationTrainingPlan'));
+  const templateUrl = ref('./skyeye-file-upload/sfysecurity/TEMPLATE/import-inventory-template.xlsx');
+  // 导入
+  const handleImport = () => {
+    batchImportVisible.value = true;
+  };
+  
+  const handleUpdate = () => {
+    batchImportVisible.value = false;
+    getTableData();
+  };
+  // 导出
+  const handleDownload = async () => {
+    try {
+      const response = await exportTableData(tableQuery.queryParam);
+      if (response) {
+        const fileName = `教育培训计划管理(管理员)_${new Date().toISOString().split('T')[0]}.xlsx`;
+        downloadByData(response, fileName);
+        ElMessage.success('导出成功');
+      }
+    } catch (e) {
+      console.error('导出教育培训计划管理(管理员)失败:', e);
+      ElMessage.error('导出失败,请重试');
+    }
+  };
 
   onMounted(() => {
     getTableData();

+ 25 - 14
src/views/production-safety/risk-identification-and-control/hazard-approval-manage/add.vue

@@ -8,25 +8,15 @@
       <el-form ref="formRef" :model="formValue" :rules="rules" label-width="160px" label-position="right">
         <div class="section-title">基础信息</div>
         <div class="form-grid">
-          <el-form-item label="审批流程" prop="templateId" class="span-full">
-            <el-select v-model="formValue.templateId" placeholder="请选择审批流程" size="large" clearable>
-              <el-option v-for="opt in approvalOptions" :key="opt.id" :label="opt.templateName" :value="opt.id" />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="作业类型" prop="hazardOperationType">
-            <el-select size="large" v-model="formValue.hazardOperationType" class="w-100">
-              <el-option :value="1" label="有限空间作业" />
-              <el-option :value="2" label="高处作业" />
-              <el-option :value="3" label="临时用电" />
-              <el-option :value="4" label="动火作业" />
-            </el-select>
-          </el-form-item>
+
           <el-form-item label="申请单位" prop="applicationUnitName"
             ><el-input size="large" v-model="formValue.applicationUnitName"
           /></el-form-item>
+
           <el-form-item label="申请人" prop="applicantName"
             ><el-input size="large" v-model="formValue.applicantName"
           /></el-form-item>
+
           <el-form-item label="申请部门" prop="applicationDepartment"
             ><el-cascader
               v-model="formValue.applicationDepartmentId"
@@ -40,9 +30,29 @@
               @change="handleChangeDept"
               style="width: 100%"
           /></el-form-item>
-          <el-form-item label="联系电话" prop="applicantPhone"
+
+          <el-form-item label="申请人电话" prop="applicantPhone"
             ><el-input size="large" v-model="formValue.applicantPhone"
           /></el-form-item>
+
+          <el-form-item label="危险作业类型" prop="hazardOperationType">
+            <el-select size="large" v-model="formValue.hazardOperationType" placeholder="选择危险作业类别" class="w-100">
+              <el-option :value="1" label="有限空间" />
+              <el-option :value="2" label="高处作业" />
+              <el-option :value="3" label="临时用电" />
+              <el-option :value="4" label="动火作业" />
+            </el-select>
+          </el-form-item>
+
+          <el-form-item label="审批流程" prop="templateId" class="span-full">
+            <el-select v-model="formValue.templateId" placeholder="请选择审批流程" size="large" clearable>
+              <el-option v-for="opt in approvalOptions" :key="opt.id" :label="opt.templateName" :value="opt.id" />
+            </el-select>
+          </el-form-item>
+
+
+
+
           <el-form-item label="备注信息" prop="remark" class="span-full">
             <el-input size="large" v-model="formValue.remark" type="textarea" :rows="2" placeholder="备注信息..." />
           </el-form-item>
@@ -574,6 +584,7 @@
     applicantName: [r],
     applicationDepartment: [r],
     applicantPhone: [r],
+    hazardOperationType:[r],
     remark: [r],
     // 有限空间
     'space.confinedSpaceUnit': [r],

+ 38 - 33
src/views/production-safety/risk-identification-and-control/risk-manage/add.vue

@@ -22,12 +22,14 @@
         <el-form-item label="安全责任人" prop="safetyResponsibleBuilding">
           <el-select
             v-model="formValue.safetyResponsibleBuilding"
-            placeholder="请选择"
+            placeholder="请选择楼宇安全责任人"
             size="large"
+            :remote-method="changeUser"
             style="width: 330px"
             filterable
+            remote
           >
-            <el-option v-for="item in userOptions" :key="item.value" :label="item.label" :value="item.value" />
+            <el-option v-for="item in userOptions" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
         </el-form-item>
         <el-form-item label="楼层/位置" prop="floorLocation">
@@ -39,20 +41,16 @@
           />
         </el-form-item>
         <el-form-item label="安全责任人" prop="safetyResponsibleFloor">
-          <!-- <el-input
-            v-model="formValue.safetyResponsibleFloor"
-            size="large"
-            placeholder="请输入楼层/位置安全责任人姓名"
-            style="width: 330px"
-          /> -->
           <el-select
             v-model="formValue.safetyResponsibleFloor"
-            placeholder="请选择"
+            placeholder="请选择楼层/位置安全责任人"
             size="large"
+            :remote-method="changeUser"
             style="width: 330px"
             filterable
+            remote
           >
-            <el-option v-for="item in userOptions" :key="item.value" :label="item.label" :value="item.value" />
+            <el-option v-for="item in userOptions" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
         </el-form-item>
         <el-form-item label="房间号(名称)" prop="roomName">
@@ -78,20 +76,16 @@
           />
         </el-form-item>
         <el-form-item label="安全责任人" prop="roomSafetyResponsible">
-          <!-- <el-input
-            v-model="formValue.roomSafetyResponsible"
-            size="large"
-            placeholder="请输入房间安全责任人姓名"
-            style="width: 330px"
-          /> -->
           <el-select
             v-model="formValue.roomSafetyResponsible"
-            placeholder="请选择"
+            placeholder="请选择房间号安全责任人"
             size="large"
             style="width: 330px"
+            :remote-method="remoteMethod"
             filterable
+            remote
           >
-            <el-option v-for="item in userOptions" :key="item.value" :label="item.label" :value="item.value" />
+            <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
         </el-form-item>
         <el-form-item label="是否存在风险点" prop="hasRiskPoint">
@@ -237,7 +231,7 @@
       </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: 'riskManage' })">返回</el-button>
       <el-button type="primary" :loading="submiting" @click="handleSubmit">提交</el-button>
     </footer>
   </div>
@@ -259,6 +253,7 @@
   const submiting = ref(false);
 
   const userOptions = ref<any[]>([]);
+  const userList = ref<any[]>([]);
   const firstLevelDepts = ref<any[]>([]);
   const cascaderProp = {
     expandTrigger: 'click',
@@ -322,12 +317,13 @@
     riskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
     remarks: [],
   });
-
+  const changeDept = ref('')
   const handleChangeDept = (prop) => {
     const cascader = cascaderRef.value;
     const deptInfo = cascader?.getCheckedNodes();
     formValue[prop] = deptInfo[0].label;
     formRef.value.validateField(prop);
+    changeDept.value = deptInfo[0].label
     nextTick(() => {
       handleQueryAvailableUserList(deptInfo[0].label, prop);
     });
@@ -339,35 +335,44 @@
     });
   };
 
+  const remoteMethod = (realname)=>{
+    handleQueryAvailableUserList(changeDept.value,realname)
+  }
   const handleQueryAvailableUserList = (deptName, realname = '') => {
     queryAvailableUserList({
       pageNumber: 1,
-      pageSize: 200,
+      pageSize: 20,
       queryParam: {
         deptName,
         realname,
       },
     }).then((res: any) => {
-      userOptions.value = (res.records || []).map((u: any) => ({
-        value: u.userId || u.id,
-        label: u.realname,
+      userList.value = (res.records || []).map((u: any) => ({
+        id: u.id,
+        name: 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,
-  //     }));
-  //   });
-  // };
+  // 选择责任人
+  const changeUser = (value)=>{
+    getUserData(value)
+  }
+  const getUserData = (realname) => {
+    queryAvailableUserList({ pageNumber: 1, pageSize: 20, queryParam: {
+        realname
+    } }).then((res: any) => {
+      userOptions.value = (res.records || []).map((u: any) => ({
+        id: u.id,
+        name: u.realname,
+      }));
+    });
+  };
 
   onMounted(() => {
     getDeptData();
     handleQueryAvailableUserList('');
-    // getUserData();
+    getUserData('');
   });
 
   const handleSubmit = () => {

+ 13 - 12
src/views/production-safety/risk-identification-and-control/risk-manage/change.vue

@@ -306,7 +306,7 @@
       </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: 'riskManage' })">返回</el-button>
       <el-button type="primary" :loading="submiting" @click="handleSubmit">提交</el-button>
     </footer>
   </div>
@@ -420,7 +420,7 @@
   const handleQueryAvailableUserList = (deptName = '', prop = '', realname = '') => {
     queryAvailableUserList({
       pageNumber: 1,
-      pageSize: 200,
+      pageSize: 300,
       queryParam: {
         deptName,
         realname,
@@ -430,7 +430,7 @@
         case 'responsibleDepartmentTodo':
           formValue.roomSafetyResponsibleTodo = '';
           roomSafetyResponsibleTodoOptions.value = (res.records || []).map((u: any) => ({
-            value: u.userId || u.id,
+            value: u.id,
             label: u.realname,
           }));
           break;
@@ -454,19 +454,20 @@
     });
   };
 
-  // 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,
-  //     }));
-  //   });
-  // };
+  const getUserData = () => {
+    queryAvailableUserList({ pageNumber: 1, pageSize: 200, queryParam: {} }).then((res: any) => {
+      userOptions.value = (res.records || []).map((u: any) => ({
+        value: u.id,
+        label: u.realname,
+      }));
+    });
+  };
 
   onMounted(() => {
+    handleQueryAvailableUserList('');
+    getUserData()
     getDeptData();
     loadDetailData(Number(route.query.id));
-    handleQueryAvailableUserList('');
   });
 
   const handleSubmit = () => {

+ 36 - 21
src/views/production-safety/risk-identification-and-control/risk-manage/edit.vue

@@ -22,12 +22,14 @@
         <el-form-item label="安全责任人" prop="safetyResponsibleBuilding">
           <el-select
             v-model="formValue.safetyResponsibleBuilding"
-            placeholder="请选择"
+            placeholder="请选择楼宇安全责任人"
             size="large"
+            :remote-method="changeUser"
             style="width: 330px"
             filterable
+            remote
           >
-            <el-option v-for="item in userOptions" :key="item.value" :label="item.label" :value="item.value" />
+            <el-option v-for="item in userOptions" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
         </el-form-item>
         <el-form-item label="楼层/位置" prop="floorLocation">
@@ -41,12 +43,14 @@
         <el-form-item label="安全责任人" prop="safetyResponsibleFloor">
           <el-select
             v-model="formValue.safetyResponsibleFloor"
-            placeholder="请选择"
+            placeholder="请选择楼层/位置安全责任人"
             size="large"
+            :remote-method="changeUser"
             style="width: 330px"
             filterable
+            remote
           >
-            <el-option v-for="item in userOptions" :key="item.value" :label="item.label" :value="item.value" />
+            <el-option v-for="item in userOptions" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
         </el-form-item>
         <el-form-item label="房间号(名称)" prop="roomName">
@@ -74,12 +78,14 @@
         <el-form-item label="安全责任人" prop="roomSafetyResponsible">
           <el-select
             v-model="formValue.roomSafetyResponsible"
-            placeholder="请选择"
+            placeholder="请选择房间号安全责任人"
             size="large"
             style="width: 330px"
+            :remote-method="remoteMethod"
             filterable
+            remote
           >
-            <el-option v-for="item in userOptions" :key="item.value" :label="item.label" :value="item.value" />
+            <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
         </el-form-item>
         <el-form-item label="是否存在风险点" prop="hasRiskPoint">
@@ -225,7 +231,7 @@
       </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: 'riskManage' })">返回</el-button>
       <el-button type="primary" :loading="submiting" @click="handleSubmit">提交</el-button>
     </footer>
   </div>
@@ -249,6 +255,7 @@
   const submiting = ref(false);
 
   const userOptions = ref<any[]>([]);
+  const userList = ref<any[]>([]);
   const firstLevelDepts = ref<any[]>([]);
   const cascaderProp = {
     expandTrigger: 'click',
@@ -312,12 +319,13 @@
     riskLevel: [{ required: true, message: '请选择风险等级', trigger: 'change' }],
     remarks: [],
   });
-
+  const changeDept = ref('')
   const handleChangeDept = (prop) => {
     const cascader = cascaderRef.value;
     const deptInfo = cascader?.getCheckedNodes();
     formValue[prop] = deptInfo[0].label;
     formRef.value.validateField(prop);
+    changeDept.value = deptInfo[0].label
     nextTick(() => {
       handleQueryAvailableUserList(deptInfo[0].label, prop);
     });
@@ -328,7 +336,9 @@
       firstLevelDepts.value = formatDeptTree(res);
     });
   };
-
+  const remoteMethod = (realname)=>{
+    handleQueryAvailableUserList(changeDept.value,realname)
+  }
   const handleQueryAvailableUserList = (deptName, realname = '') => {
     queryAvailableUserList({
       pageNumber: 1,
@@ -338,13 +348,26 @@
         realname,
       },
     }).then((res: any) => {
+      userList.value = (res.records || []).map((u: any) => ({
+        id: u.id,
+        name: u.realname,
+      }));
+    });
+  };
+  // 选择责任人
+  const changeUser = (value)=>{
+    getUserData(value)
+  }
+  const getUserData = (realname) => {
+    queryAvailableUserList({ pageNumber: 1, pageSize: 300, queryParam: {
+        realname
+    } }).then((res: any) => {
       userOptions.value = (res.records || []).map((u: any) => ({
-        value: u.userId || u.id,
-        label: u.realname,
+        id: u.id,
+        name: u.realname,
       }));
     });
   };
-
   const loadDetailData = (id: number) => {
     safetyRiskListQueryDetail(id).then((res: any) => {
       Object.keys(formValue).forEach((key) => {
@@ -358,17 +381,9 @@
     });
   };
 
-  // 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();
+    getUserData('');
     loadDetailData(Number(route.query.id));
     handleQueryAvailableUserList('');
   });

+ 4 - 2
src/views/production-safety/risk-identification-and-control/risk-manage/list.vue

@@ -89,7 +89,7 @@
                 >编辑</el-button
               >
               <el-button type="primary" link @click="handleConfirmDeleteRow(scope)">删除</el-button>
-              <el-button type="primary" link>查看</el-button>
+              <el-button type="primary" link @click="handleView(scope.row.id)">查看</el-button>
               <el-button
                 type="primary"
                 link
@@ -180,7 +180,9 @@
       queryParams.queryParam.responsibleDepartment = deptInfo[0].label;
     }
   };
-
+  const handleView = (id)=>{
+    router.push({ name: 'riskManageView', query: { id} })
+  } 
   const handleApprove = (scope, approveType) => {
     safetyRiskListApprove({
       id: scope.row.id,

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

@@ -264,7 +264,7 @@
       </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: 'riskManage' })">返回</el-button>
     </footer>
   </div>
 </template>

+ 6 - 5
src/views/production-safety/safetyAssessment/inventory/inventory.vue

@@ -11,9 +11,7 @@
             <el-button plain class="search-table-container--button" @click="handleImport">
               导入
             </el-button>
-            <el-button plain class="search-table-container--button" @click="handleDownload">
-              导出
-            </el-button>
+
           </div>
 
           <div class="act-search">
@@ -37,6 +35,9 @@
             <section class="search-btn">
               <el-button type="primary" @click="handleSearch">查询</el-button>
               <el-button @click="handleReset">重置</el-button>
+              <el-button plain class="search-table-container--button" @click="handleDownload">
+              导出
+            </el-button>
             </section>
           </div>
         </header>
@@ -205,7 +206,7 @@
         downloadByData(response, fileName);
         ElMessage.success('导出成功');
       }
-    } catch (e) {
+    } catch (e:any) {
       console.error('导出奖品库存失败:', e);
       ElMessage.error(e?.message || e?.data || '导出失败,请重试');
     }
@@ -235,7 +236,7 @@
       await deleteInventory(id);
       ElMessage.success('删除成功');
       getTableData();
-    } catch (e) {
+    } catch (e:any) {
       console.error('删除奖品库存失败:', e);
       ElMessage.error(e?.message || e?.data || '删除失败,请重试');
     }

+ 0 - 12
src/views/production-safety/safetyTrainingAndEducation/educationTrainingPlanManagement/educationTrainingPlanManagement.vue

@@ -75,18 +75,6 @@
             @update:pageSize="handleSizeChange"
             @update:pageNumber="handleCurrentChange"
           >
-            <template #status="scope">
-              <span>
-                {{
-                  scope.row.statusName ||
-                  (scope.row.status === true || scope.row.status === 'true'
-                    ? '启用'
-                    : scope.row.status === false || scope.row.status === 'false'
-                    ? '禁用'
-                    : '-')
-                }}
-              </span>
-            </template>
             <template #action="scope">
               <div class="action-container--div" style="justify-content: left">
                 <!-- 状态:1-未下发 2-进行中 3-已完成 4-已作废 -->

+ 26 - 21
src/views/production-safety/safetyTrainingAndEducation/educationTrainingPlanManagementDept/components/addTrainingInformation.vue

@@ -47,7 +47,7 @@
     startDate: '',
     endDate: '',
     courseIntroduction: '',
-    courseContent: [] as FileItem[],
+    courseContent: '', //[] as FileItem[],
     isSign: 0,
     courseImg: [] as FileItem[],
   });
@@ -73,17 +73,7 @@
         fileName: `${uuid}-${timestamp}-${random}`,
         file: data,
     });
-    const fileType = data.fileType;
-    const fileSize = data.fileSize;
-    const fileId = data.fileId;
-    const fileUrl = res.url;
-    return {
-        fileName,
-        fileType,
-        fileSize,
-        fileUrl,
-        fileId,
-    };
+    return res;
 };
 const openState = ref(false)
   // 打开抽屉时的事件
@@ -113,7 +103,7 @@ const openState = ref(false)
         if(res.courseContent){
             // handleFileExceed(JSON.parse(res.courseContent))
             // fileList.value =  JSON.parse(res.courseContent) || [];
-            form.courseContent = res.courseContent
+            // form.courseContent = res.courseContent
         }
       });
     } else if (props.state === 'add') {
@@ -129,7 +119,7 @@ const openState = ref(false)
           startDate: '',
           endDate: '',
           courseIntroduction: '',
-          courseContent: [] as FileItem[],
+          courseContent: '', // [] as FileItem[],
           isSign: 0,
           courseImg: [] as FileItem[],
         });
@@ -255,7 +245,7 @@ const openState = ref(false)
 
 
   // 课程内容文件上传
-  const handleFileChange = async (file, fileList) => {
+  const handleFileChange = async (file, fileLists) => {
     
 
     if (!allowedTypes.includes(file.raw.type)) {
@@ -267,7 +257,24 @@ const openState = ref(false)
       ElMessage.error('文件大小不能超过20MB');
       return;
     }
-    
+    if(file.raw){
+        try {
+            const res = await formatAttachment(file.raw);
+            
+            const targetFile = fileLists.find(f => f.uid === file.uid);
+            if (targetFile) {
+                targetFile.url = res.url; 
+                targetFile.contentType = res.contentType
+            }
+            fileList.value = fileLists; 
+            form.courseContent = JSON.stringify(fileList.value); 
+            ElMessage.success('上传成功');
+        } catch (error) {
+            ElMessage.error('上传失败,请重试');
+            // 上传失败时,可以从 fileLists 中移除该文件
+            fileList.value = fileLists.filter(f => f.uid !== file.uid);
+        }
+    }
     if(file.raw){
         let res = await formatAttachment(file.raw)
         console.log(res, '文件上传')
@@ -275,9 +282,9 @@ const openState = ref(false)
             ElMessage.success('上传成功')
         }
     }
-    // 直接替换为新文件
-    fileList.value = [file.raw]; 
-    form.courseContent = file; // 更新表单数据
+    // // 直接替换为新文件
+    // fileList.value = [file.raw]; 
+    // form.courseContent = file; // 更新表单数据
   };
 
   // 提交保存/编辑
@@ -428,8 +435,6 @@ const openState = ref(false)
             :on-change="handleFileChange"
             accept=".rar, .zip, .doc, .docx, .pdf, .mp4"
             :file-list="fileList"
-            :limit="1"
-            :on-exceed="handleFileExceed"
           >
             <el-button type="default" :disabled="isViewMode">
               <el-icon style="margin-right: 6px">