Browse Source

Merge branch 'feat/production-safety' of http://14.103.151.10:8888/product-group-fe/sfy-safety-group/sfy-safety into feat/production-safety

sunqijun 1 month ago
parent
commit
33703be7a3
13 changed files with 810 additions and 446 deletions
  1. 16 16
      src/router/routers/production-safety-router/productionSafetySystem.ts
  2. 2 2
      src/router/routers/production-safety-router/risk-identification-and-control.ts
  3. 141 0
      src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/TeamDetailDrawer.vue
  4. 2 2
      src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/addSafetySystem.vue
  5. 127 0
      src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/collapseItem.vue
  6. 195 0
      src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/orgChart.vue
  7. 285 352
      src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagement.vue
  8. 1 1
      src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/components/safetyOrganizationSystemManagementDetail.vue
  9. 3 2
      src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/configs/tables.ts
  10. 33 66
      src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/securityOrganizationalStructure.vue
  11. 0 0
      src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/securityOrganizationalStructureItem.vue
  12. 4 4
      src/views/production-safety/risk-identification-and-control/work-injury-apply-manage/listAdmin.vue
  13. 1 1
      src/views/production-safety/safetyTrainingAndEducation/employeeTrainingRecordCardManagement/employeeTrainingRecordCardManagement.vue

+ 16 - 16
src/router/routers/production-safety-router/productionSafetySystem.ts

@@ -226,30 +226,30 @@ const productionSafetySystemRoutes: RouteComponent[] = [{
       },
     },
     {
-      id: 90030,
+      id: 90027,
       parentId: 9002,
-      name: 'securityOrganizationalStructure',
-      path: 'security-organizational-structure',
-      component: '/production-safety/productionSafetySystem/securityOrganizationalStructure/securityOrganizationalStructure',
+      name: 'SafetyOrganizationSystemManagement',
+      path: 'safety-organization-system-management',
+      component: '/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagement',
       meta: {
-        title: '安全组织体系架构',
+        title: '安全组织体系管理(架构)',
         icon: 'OverviewIcon',
-        activeMenu: '/work-safety/productionSafetySystem/securityOrganizationalStructure',
+        activeMenu: '/work-safety/production-safety-system/safety-organization-system-management',
         isRoot: false,
         hidden: false,
         noCache: false,
       },
     },
     {
-      id: 90027,
+      id: 90030,
       parentId: 9002,
-      name: 'SafetyOrganizationSystemManagement',
-      path: 'safety-organization-system-management',
-      component: '/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagement',
+      name: 'securityOrganizationalStructure',
+      path: 'security-organizational-structure',
+      component: '/production-safety/productionSafetySystem/securityOrganizationalStructure/securityOrganizationalStructure',
       meta: {
-        title: '安全组织体系管理',
+        title: '安全组织体系管理(组织员工)',
         icon: 'OverviewIcon',
-        activeMenu: '/work-safety/productionSafetySystem/safetyOrganizationSystemManagement',
+        activeMenu: '/work-safety/production-safety-system/safety-organization-system-management',
         isRoot: false,
         hidden: false,
         noCache: false,
@@ -258,12 +258,12 @@ const productionSafetySystemRoutes: RouteComponent[] = [{
     {
         id: 90029,
         parentId: 9002,
-        name: 'SafetyOrganizationSystemManagementItem',
-        path: 'safety-organization-system-management-item',
-        component: '/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagementItem',
+        name: 'SecurityOrganizationalStructureItem',
+        path: 'security-organizational-structure-item',
+        component: '/production-safety/productionSafetySystem/securityOrganizationalStructure/securityOrganizationalStructureItem',
         meta: {
             title: '安全组织体系管理详情',
-            activeMenu: '/work-safety/productionSafetySystem/safetyOrganizationSystemManagement',
+            activeMenu: '/work-safety/production-safety-system/safety-organization-system-management',
             icon: 'OverviewIcon',
             isRoot: false,
             hidden: false,

+ 2 - 2
src/router/routers/production-safety-router/risk-identification-and-control.ts

@@ -633,7 +633,7 @@ const riskIdentificationAndControlRoutes: RouteComponent[] = [{
       path: 'labor-products-purchase-apply-manage-admin',
       component: '/production-safety/risk-identification-and-control/labor-products-purchase-apply-manage-admin/listAdmin',
       meta: {
-        title: '劳防用品采购申请(管理员)',
+        title: '劳防用品采购申请审核列表(管理员)',
         icon: 'OverviewIcon',
         isRoot: false,
         hidden: false,
@@ -647,7 +647,7 @@ const riskIdentificationAndControlRoutes: RouteComponent[] = [{
       path: 'labor-products-purchase-apply-manage-admin-item',
       component: '/production-safety/risk-identification-and-control/labor-products-purchase-apply-manage-admin/Item',
       meta: {
-        title: '劳防用品采购申请详情(管理员)',
+        title: '劳防用品采购申请审核详情(管理员)',
         activeMenu: '/work-safety/risk-identification-and-control/labor-products-purchase-apply-manage-admin',
         icon: 'OverviewIcon',
         isRoot: false,

+ 141 - 0
src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/TeamDetailDrawer.vue

@@ -0,0 +1,141 @@
+<template>
+  <el-drawer v-model="showDrawer" direction="rtl" @close="clearData">
+    <div class="team-detail__info">
+      <div class="team-detail__info__team-name">{{ teamAndPersonInfo?.teamName }}</div>
+      <div class="team-detail__info__member-count">
+        共 <span>{{ teamAndPersonInfo?.memberCount || 0 }}</span> 人
+      </div>
+    </div>
+
+    <div class="team-detail__level" v-for="level in levelAndPersonList" :key="level.positionLevel">
+      <div class="team-detail__level__title">
+        {{ level.title }}
+      </div>
+      <div class="team-detail__level__content">
+        <div v-for="(person, index) in level.personList" :key="index">{{ person }}</div>
+      </div>
+    </div>
+
+    <div class="team-detail__description">
+      <div class="team-detail__description__title"> 队伍职责 </div>
+      <div class="team-detail__description__content"> {{ teamAndPersonInfo?.description }} </div>
+    </div>
+  </el-drawer>
+</template>
+
+<script setup lang="ts">
+  import { ref, watch } from 'vue';
+  import { queryEmergencyTeamDetail } from '@/api/emergency-organization/teams';
+  import { TeamAndPersonInfoType } from '../team-management/type';
+
+  const props = defineProps<{ selectedTeamId: number | null }>();
+
+  type LevelAndPersonType = {
+    positionLevel: number;
+    title: string;
+    personList: string[];
+  };
+
+  const showDrawer = ref(false);
+  const teamAndPersonInfo = ref<TeamAndPersonInfoType>();
+  const levelAndPersonList = ref<LevelAndPersonType[]>([]);
+
+  function drawerShow() {
+    showDrawer.value = true;
+  }
+
+  function clearData() {
+    teamAndPersonInfo.value = undefined;
+    levelAndPersonList.value = [];
+  }
+
+  // 按照职位等级排序队伍人员
+  function setLevelAndPerson() {
+    const levelMap: { [key: number]: LevelAndPersonType } = {};
+
+    teamAndPersonInfo.value?.personnelList.map((person) => {
+      if (!(person.positionLevel in levelMap)) {
+        levelMap[person.positionLevel] = { positionLevel: person.positionLevel, title: person.title, personList: [] };
+      }
+
+      levelMap[person.positionLevel].personList.push(person.realname);
+    });
+
+    for (let level in levelMap) {
+      levelAndPersonList.value.push(levelMap[level]);
+    }
+  }
+
+  watch(
+    () => showDrawer.value,
+    async () => {
+      if (showDrawer.value) {
+        teamAndPersonInfo.value = await queryEmergencyTeamDetail(props.selectedTeamId!);
+        setLevelAndPerson();
+      }
+    },
+  );
+
+  defineExpose({
+    drawerShow,
+  });
+</script>
+
+<style scoped lang="scss">
+  .team-detail__info {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20px;
+
+    &__team-name {
+      font-size: 20px;
+      font-weight: bold;
+    }
+    &__member-count {
+      span {
+        color: #1777ff;
+      }
+    }
+  }
+
+  .team-detail__level {
+    display: flex;
+    align-items: center;
+    margin-bottom: 10px;
+    padding: 10px 0;
+    border-left: 3px solid #1777ff;
+    background-color: #e5effe;
+
+    &__title {
+      flex: 1;
+      height: inherit;
+      padding: 0 10px;
+      color: #1777ff;
+      text-align: center;
+      white-space: nowrap;
+    }
+
+    &__content {
+      flex: 10;
+      display: flex;
+      flex-wrap: wrap;
+      padding: 0 15px;
+      gap: 15px;
+      border-left: 1px solid #c5c3c3;
+    }
+  }
+
+  .team-detail__description {
+    margin-top: 20px;
+    &__title {
+      margin-bottom: 10px;
+      font-size: 20px;
+      font-weight: bold;
+    }
+    &__content {
+      color: #aaaaaa;
+      white-space: pre-wrap;
+    }
+  }
+</style>

+ 2 - 2
src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/addSafetySystem.vue

@@ -2,8 +2,8 @@
  * @Author: liuJie
  * @Date: 2026-02-05 10:20:24
  * @LastEditors: liuJie
- * @LastEditTime: 2026-02-05 20:25:10
- * @Describe: 添加组织
+ * @LastEditTime: 2026-03-29 16:20:32
+ * @Describe: 添加、编辑组织
 -->
 <script lang="ts" setup>
   import { ref, watch } from 'vue';

+ 127 - 0
src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/collapseItem.vue

@@ -0,0 +1,127 @@
+<template>
+  <div v-if="level <= 10">
+    <el-collapse-item :name="String(data.orgId)">
+      <!-- 标题 -->
+      <template #title>
+        <div class="node">
+            <div @click.stop="handleClick" class="cursor-pointer">
+            {{ data?.orgName }}
+            </div>
+            <el-popconfirm hide-icon  popper-class="node-popconfirm">
+                <template #reference>
+                    <el-button size="small" class="handle" :icon="MoreFilled" @click.stop />
+                </template>
+                <template #actions="{ confirm, cancel }">
+                    <ul>
+                        <li><el-button type="primary" link :icon="Plus" @click.stop="bindingEvents('create', 'children', data)">新增</el-button></li>
+                        <li><el-button type="primary" link :icon="Edit" @click.stop="bindingEvents('edit', 'children', data)">编辑</el-button></li>
+                        <li><el-button type="primary" link :icon="Delete" @click.stop="bindingEvents('delate', 'children', data)">删除</el-button></li>
+                    </ul>
+                </template>
+            </el-popconfirm>
+        </div>
+      </template>
+
+      <!-- 子级递归 -->
+      <div
+        v-if="data.children && data.children.length && level < 10"
+        class="ml-4">
+        <el-collapse accordion>
+          <CollapseItem
+            v-for="child in data.children"
+            :key="child.id"
+            :data="child"
+            :level="level + 1"
+            @click-node="handleClickItem"
+            @create-node="(type, item) => emit('create-node', type, item)"
+            @edit-node="(type, item) => emit('edit-node', type, item)"
+            @delete-node="(type, item) => emit('delete-node', type, item)"
+          />
+        </el-collapse>
+      </div>
+      <div v-else>
+        <el-empty description="未添加子组织" :image-size="40" />
+      </div>
+    </el-collapse-item>
+  </div>
+</template>
+
+<script setup>
+  import { defineProps, defineEmits, defineOptions } from 'vue'
+  import {
+  Delete,
+  Edit,
+  Plus,
+  MoreFilled
+} from '@element-plus/icons-vue'
+// 必须给组件命名,才能递归
+defineOptions({
+  name: 'CollapseItem'
+})
+
+// 定义 props
+const props = defineProps({
+  data: {
+    type: Object,
+    required: true
+  },
+  level: {
+    type: Number,
+    default: 1
+  }
+})
+
+// 定义事件
+const emit = defineEmits(['click-node', 'create-node', 'edit-node', 'delete-node'])
+// 新增、编辑、删除事件
+const bindingEvents = (state, type, item)=>{
+    switch(state){
+        case 'create':
+            emit('create-node',type, item)
+            break;
+        case 'edit':
+            emit('edit-node',type, item)
+            break;
+        case 'delate':
+            emit('delete-node',type, item)
+            break;
+        default:
+            emit('create-node',type, item)
+    }
+}
+// 点击当前项
+const handleClick = () => {
+  emit('click-node', props.data)
+}
+
+// 接收子组件点击
+const handleClickItem = (item) => {
+  emit('click-node', item)
+}
+</script>
+
+<style scoped>
+.ml-4 {
+  margin-left: 16px;
+}
+.cursor-pointer {
+  cursor: pointer;
+}
+.node {
+  display:flex;
+  justify-content: space-between;
+  align-items: center;
+  width: 100%;
+}
+.handle {
+    margin-right: 8px;
+}
+li{
+    list-style: none;
+    width:100%;
+    text-align: center;
+    padding:4px 0;
+    margin: 4px 0;
+    cursor: pointer;
+}
+</style>

+ 195 - 0
src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/components/orgChart.vue

@@ -0,0 +1,195 @@
+<template>
+  <div class="org-chart-container" ref="container"></div>
+</template>
+
+<script setup lang="ts">
+  import { ref, onMounted, onBeforeUnmount, watch, nextTick } from 'vue';
+  import { Graph, treeToGraphData, NodeEvent, CanvasEvent } from '@antv/g6';
+  // import { Graph, treeToGraphData, register, ExtensionCategory, NodeEvent, Polyline, CanvasEvent } from '@antv/g6';
+
+  /**
+   * @description: 为了确保图的正确渲染和交互,建议按照 G6 标准数据结构组织数据。
+   * 每个元素(节点、边、组合)应包含一个 data 字段,用于存放业务数据和自定义属性。
+   */
+
+  // 定义 props 接口
+  interface TreeData {
+    id: string;
+    data: { name: string };
+    children?: TreeData[];
+  }
+
+  const props = defineProps<{
+    treeData: TreeData;
+  }>();
+
+  const emits = defineEmits<{
+    (event: 'node-click', nodeData: any): void;
+    (event: 'canvas-click'): void;
+  }>();
+
+  let data = treeToGraphData(props.treeData); // 通过 treeToGraphData 方法,将树形结构数据转换为 G6 的标准数据结构
+  const container = ref<HTMLDivElement | null>(null); // 图表容器引用
+  let graph: any = null;
+  let pending = false; // 防止并发 initGraph
+
+  // 初始化图表
+  const initGraph = async () => {
+    if (pending || !container.value) return;
+    pending = true;
+
+    // 销毁旧实例
+    if (graph) {
+      graph.off();
+      graph.destroy();
+      graph = null;
+    }
+
+    // 等待下一帧,确保销毁完成
+    await nextTick();
+
+    // 创建新的 G6 实例
+    graph = new Graph({
+      container: container.value,
+      padding: [20, 20, 20, 20], // 图表内边距
+      data,
+      node: {
+        type: 'rect', // 使用内置的矩形节点类型
+        style: {
+          labelText: (d: any) => d.data.name, // 节点文本
+          labelFill: '#333', // 文本颜色
+          labelFontSize: 14, // 文本大小
+          size: [250, 50],
+          lineWidth: 1, // 边框宽度
+          // lineDash: [5, 5], // 虚线边框
+          stroke: '#1777FF', // 边框色
+          fill: '#E7F1FF', // 填充色
+          radius: 8,
+          labelPlacement: 'center',
+          ports: [{ placement: 'top' }, { placement: 'bottom' }],
+        },
+        // 节点状态样式
+        state: {
+          selected: {
+            fill: '#1777FF',
+            stroke: '#1777FF',
+            lineWidth: 1,
+            labelFill: '#fff', // 选中状态下文本颜色
+            labelFontSize: 16, // 选中状态下文本大小
+          },
+        },
+      },
+      edge: {
+        type: 'ant-line', // 边类型
+        style: {
+          stroke: '#1777FF', // 边的颜色
+          lineWidth: 1, // 边的宽度
+          lineDash: [10, 10],
+          endArrow: true, // 是否有箭头
+          router: {
+            type: 'orth',
+          },
+        },
+      },
+      layout: {
+        type: 'dagre',
+        nodesep: 100,
+        ranksep: 120,
+        preventOverlap: true, // 防止节点重叠
+        nodeStrength: -50, // 节点之间的斥力
+        edgeStrength: 0.5, // 边的弹性系数
+        iterations: 200, // 迭代次数
+        animation: true, // 启用布局动画
+      },
+      autoFit: {
+        type: 'center', // 自适应类型:'view' 或 'center'
+        // options: {
+        //   // 仅适用于 'view' 类型
+        //   when: 'always', // 何时适配:'overflow'(仅当内容溢出时) 或 'always'(总是适配)
+        //   direction: 'both', // 适配方向:'x'、'y' 或 'both'
+        // },
+        // animation: {
+        //   // 自适应动画效果
+        //   duration: 1000, // 动画持续时间(毫秒)
+        //   easing: 'ease-in-out', // 动画缓动函数
+        // },
+      },
+      autoResize: true, // 自动调整大小
+      behaviors: [
+        'drag-canvas',
+        {
+          type: 'zoom-canvas',
+          sensitivity: 0.5, // 配置灵敏度
+          key: 'zoom-behavior', // 为交互指定key,便于后续更新
+        },
+        'focus-element',
+        {
+          type: 'click-select',
+          state: 'selected',
+          unselectedState: 'inactive',
+          multiple: true,
+          trigger: ['shift'],
+        },
+      ],
+    });
+
+    // 渲染
+    graph.render();
+
+    // 监听节点点击事件
+    graph.on(NodeEvent.CLICK, (evt) => {
+      const { target } = evt;
+      const nodeData = graph.getNodeData(target.id); // 获取节点数据
+      emits('node-click', nodeData);
+    });
+
+    graph.on(CanvasEvent.CLICK, () => {
+      graph?.fitCenter();
+      emits('canvas-click');
+    });
+
+    window.addEventListener('resize', handleResize);
+
+    pending = false;
+  };
+
+  // 处理窗口大小变化
+  const handleResize = () => {
+    if (graph && container.value) {
+      graph.resize(container.value.offsetWidth, container.value.offsetHeight);
+      graph.fitCenter();
+    }
+  };
+
+  // 监听 treeData 变化
+  watch(
+    () => props.treeData,
+    () => {
+      data = treeToGraphData(props.treeData);
+      initGraph();
+    },
+    { deep: true },
+  );
+
+  // 生命周期钩子
+  onMounted(() => {
+    data = treeToGraphData(props.treeData);
+    initGraph();
+  });
+
+  onBeforeUnmount(() => {
+    window.removeEventListener('resize', handleResize);
+    if (graph) {
+      graph.off(); // 移除所有事件监听
+      graph.destroy();
+      graph = null;
+    }
+  });
+</script>
+
+<style lang="scss" scoped>
+  .org-chart-container {
+    width: 100%;
+    height: 100%;
+  }
+</style>

+ 285 - 352
src/views/production-safety/productionSafetySystem/safetyOrganizationSystemManagement/safetyOrganizationSystemManagement.vue

@@ -8,63 +8,25 @@
         <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>
-                  <div class="handler">
-                    <el-button :icon="Plus" size="small" type="default" dashed @click.stop="handleCreateSafetySystem('children', item)"
-                      ></el-button
-                    >
-                    <el-button size="small" type="primary" link @click.stop="handleEditSafetySystem('parent', item, '')"
-                      >编辑</el-button
-                    >
-                    <el-button  size="small" type="danger" link @click.stop="handleDelSafetySystem('parent', item)"
-                      >删除</el-button
-                    >
-                  </div>
-                </div>
-              </template>
-              <div class="collapse-item-content">
-                <div v-if="item.children.length > 0">
-                  <ul>
-                    <li class="flex" v-for="children in item.children" :key="children.orgId">
-                      <span @click="querySafetyTeamData('children', children)">
-                        {{ children.orgName }}
-                      </span>
-                      <div class="handler">
-                        <el-button
-                          link
-                          size="small"
-                          type="primary"
-                          @click.stop="handleEditSafetySystem('children', children, item.orgId)"
-                          >编辑</el-button
-                        >
-                        <el-button
-                          link
-                          size="small"
-                          type="danger"
-                          @click.stop="handleDelSafetySystem('children', children)"
-                          >删除</el-button
-                        >
-                      </div>
-                    </li>
-                  </ul>
-                </div>
-                <div v-else>
-                  <el-empty description="未添加子组织" :image-size="40" />
-                </div>
-              </div>
-            </el-collapse-item>
-          </el-collapse>
+            <!-- 组织树 -->
+            <el-collapse v-model="activeName" accordion v-if="fetchSafetyOrganizationList.length > 0">
+                <CollapseItem
+                    v-for="item in fetchSafetyOrganizationList"
+                    :key="item.id"
+                    :data="item"
+                    :level="level"
+                    @click-node="querySafetyTeamData"
+                    @create-node="handleCreateSafetySystem"
+                    @edit-node="handleEditSafetySystem"
+                    @delete-node="handleDelSafetySystem"
+                />
+            </el-collapse>
+           
           <div v-else>
             <el-empty description="未添加组织" />
           </div>
         </div>
+        <!-- 添加、编辑组织弹窗 -->
         <AddSafetySystem
           v-model:visible="addSafetySystemVisible"
           :data="addSafetyOrganizationSystemFormData"
@@ -72,83 +34,15 @@
         />
       </div>
       <div class="search-table-container table-content">
-        <div style="margin-bottom:20px">
-            <el-button type="primary" :icon="Plus"  @click="handleCreate"> 添加 </el-button>
-            <el-button plain  @click="handleImport">导入</el-button>
-            <!-- <el-button plain  @click="handlerEdit">架构</el-button> -->
-        </div>
-        <header>
-          <div class="act-search">
-            <section class="select-box">
-              <div class="select-box--item">
-                <span>搜索工号/姓名:</span>
-                <el-input
-                  v-model="tableQuery.queryParam.keyword"
-                  placeholder="搜索工号/姓名"
-                  class="act-search-input"
-                />
-              </div>
-              <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-select>
-              </div>
-              <div class="select-box--item">
-                <span>日期范围:</span>
-                <el-date-picker
-                  v-model="dateRange"
-                  @change="onchangeDateRange"
-                  type="daterange"
-                  range-separator="至"
-                  start-placeholder="开始日期"
-                  end-placeholder="结束日期"
-                  value-format="YYYY-MM-DD"
-                  format="YYYY-MM-DD"
-                />
-              </div>
-            </section>
-            <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">
-          <BasicTable
-            ref="basicTableRef"
-            :tableData="tableData"
-            :tableConfig="tableConfig"
-            @update:pageSize="handleSizeChange"
-            @update:pageNumber="handleCurrentChange"
-          >
-            <template #status="scope">
-              <span>
-                {{ scope.row.status === 1 ? '启用' : scope.row.status === 2 ? '禁用' : '-' }}
-              </span>
-            </template>
-            <template #action="scope">
-              <div class="action-container--div" style="justify-content: left">
-                <ActionButton text="编辑" @click="handleEdit(scope.row.id)" />
-                <ActionButton
-                  text="删除"
-                  :popconfirm="{
-                    title: '确定要删除?',
-                  }"
-                  @confirm="handleDelete(scope.row.id)"
-                />
-                <ActionButton text="查看" @click="handleView(scope.row.id)" />
-              </div>
-            </template>
-          </BasicTable>
+        <!-- 架构图 -->
+        <OrgChart :treeData="treeData" @node-click="handleNodeClick" />
+        <TeamDetailDrawer ref="teamDetailDrawerRef" :selected-team-id="selectedTeamId" />
+        <div class="text-right mb-4">
+            <el-button type="primary" @click="toStaff"> 编辑 </el-button>
         </div>
-        <!-- <OrgChart :treeData="treeData" @node-click="handleNodeClick" /> -->
       </div>
     </main>
-    <BatchImport
+    <!-- <BatchImport
       v-if="batchImportVisible"
       :visible="batchImportVisible"
       :import-api-url="importApiUrl"
@@ -157,16 +51,15 @@
       :show-template="true"
       @close="batchImportVisible = false"
       @update="handleUpdate"
-    />
+    /> -->
   </div>
 </template>
 
 <script setup lang="ts">
-  import { onMounted, reactive, ref } from 'vue';
+  import { onMounted, reactive, ref, defineComponent } from 'vue';
   import { ElMessage, ElMessageBox } from 'element-plus';
   import BasicTable from '@/components/BasicTable.vue';
   import useTableConfig from '@/hooks/useTableConfigHook';
-  import ActionButton from '@/components/ActionButton.vue';
   import { TABLE_OPTIONS, TABLE_COLUMNS } from './configs/tables';
   import { useRouter } from 'vue-router';
   import type { QueryPageRequest } from '@/types/basic-query';
@@ -179,22 +72,24 @@
     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 { downloadByData } from '@/utils/file/download';
+//   import BatchImport from '@/components/batch-import/BatchImport.vue';
+//   import { useGlobSetting } from '@/hooks/setting';
+//   import urlJoin from 'url-join';
   import AddSafetySystem from './components/addSafetySystem.vue';
   import {
   Delete,
   Edit,
   Plus,
 } from '@element-plus/icons-vue'
-  import OrgChart from '@/views/emergency/components/OrgChart.vue';
+  import OrgChart from './components/orgChart.vue';
+  import CollapseItem from './components/collapseItem.vue'
+  import TeamDetailDrawer from './components/TeamDetailDrawer.vue';
 const position = ref('left')
 
   const router = useRouter();
   // 表格
-  const basicTableRef = ref<InstanceType<typeof BasicTable>>();
+//   const basicTableRef = ref<InstanceType<typeof BasicTable>>();
 
   const { tableConfig, pagination } = useTableConfig(TABLE_COLUMNS, TABLE_OPTIONS);
 
@@ -203,6 +98,8 @@ const position = ref('left')
   const fetchSafetyOrganizationList = ref<any[]>([]);
 
   const activeName = ref('');
+
+  const level = ref(1)
   // 日期范围(用于日期选择器)
   const dateRange = ref<[string, string] | string>('');
 
@@ -226,58 +123,48 @@ const position = ref('left')
 
   const treeData = ref<OrganizationTreeType>({
     id: 'root',
-    data: { name: '应急领导小组' },
-    children: [
-      {
-        id: 'group1',
-        data: { name: '应急指挥小组' },
-      },
-      {
-        id: 'group2',
-        data: { name: '应急响应小组' },
-      },
-      {
-        id: 'group3',
-        data: { name: '应急支援小组' },
-      },
-    ],
+    data: { name: '请添加组织' },
+    children: [],
   });
-
-  const handlerEdit = ()=>{
-    router.push({name: 'securityOrganizationalStructure'})
-  }
-  const handleSizeChange = (value: number) => {
-    pagination.pageSize = value;
-    tableQuery.pageSize = value;
-    getTableData();
-  };
-
-  const handleCurrentChange = (value: number) => {
-    pagination.pageNumber = value;
-    tableQuery.pageNumber = value;
-    getTableData();
-  };
+  
+//   const handlerEdit = ()=>{
+//     router.push({name: 'securityOrganizationalStructure'})
+//   }
+//   const handleSizeChange = (value: number) => {
+//     pagination.pageSize = value;
+//     tableQuery.pageSize = value;
+//     getTableData();
+//   };
+
+//   const handleCurrentChange = (value: number) => {
+//     pagination.pageNumber = value;
+//     tableQuery.pageNumber = value;
+//     getTableData();
+//   };
+
+  const teamDetailDrawerRef = ref<InstanceType<typeof TeamDetailDrawer>>();
+  const selectedTeamId = ref<number | null>(null);
   const handleNodeClick = (nodeData: any) => {
-    // selectedTeamId.value = Number(nodeData.id);
+    selectedTeamId.value = Number(nodeData.id);
 
-    // teamDetailDrawerRef.value?.drawerShow();
+    teamDetailDrawerRef.value?.drawerShow();
   };
-  async function getTableData() {
-    tableConfig.loading = true;
-    try {
-      const res = await fetchTableList(tableQuery);
-      if (res) {
-        tableData.value = res.records
-        pagination.total = res.totalRow;
-      }
-    } catch (e) {
-      console.error('获取列表失败:', e);
-      tableData.value = [];
-      pagination.total = 0;
-    } finally {
-      tableConfig.loading = false;
-    }
-  }
+//   async function getTableData() {
+//     tableConfig.loading = true;
+//     try {
+//       const res = await fetchTableList(tableQuery);
+//       if (res) {
+//         tableData.value = res.records
+//         pagination.total = res.totalRow;
+//       }
+//     } catch (e) {
+//       console.error('获取列表失败:', e);
+//       tableData.value = [];
+//       pagination.total = 0;
+//     } finally {
+//       tableConfig.loading = false;
+//     }
+//   }
 
   interface addSafetyOrganizationSystemFormDataType {
     type: String;
@@ -295,99 +182,88 @@ const position = ref('left')
     action: '',
     parentid: '',
   });
-  // 一级新增
-  const addTeam = (type) => {
-    addSafetyOrganizationSystemFormData.value = {
-      type,
-      action: 'add',
+
+/**
+ * 递归给树形结构添加 id 、data 、children 字段
+ * @param {Array} tree 原始树形数组
+ * @returns 格式化后的标准树结构
+ */
+const formatTreeData = (tree)=> {
+  if (!tree || !Array.isArray(tree)) return [];
+
+  return tree.map(item => {
+    // 给每一层节点都加上 id 和 data
+    const formattedItem = {
+      children: item.children || [],
+      id: `org-${item.orgId}`, 
+      data: {
+        name: item.orgName
+      }
     };
-    addSafetySystemVisible.value = true;
-  };
 
-// id: 'root',
-//     data: { name: '应急领导小组' },
-//     children: [
-//       {
-//         id: 'group1',
-//         data: { name: '应急指挥小组' },
-//       },
-//       {
-//         id: 'group2',
-//         data: { name: '应急响应小组' },
-//       },
-//       {
-//         id: 'group3',
-//         data: { name: '应急支援小组' },
-//       },
-//     ],
+    // 递归处理子节点
+    if (formattedItem.children && formattedItem.children.length > 0) {
+      formattedItem.children = formatTreeData(formattedItem.children);
+    }
+
+    return formattedItem;
+  });
+}
+  function convertData(leaderTeams): OrganizationTreeType {
+    return {
+      id: `org-${leaderTeams.orgId}`, 
+      data: {
+        name: leaderTeams.orgName
+      },
+      children: leaderTeams.children?.map((child) => convertData(child)),
+    };
+  }
   // 获取组织列表
   const fetchSafetyOrganizationTeamList = async () => {
     try {
       const res = await getSafetySystemList();
       fetchSafetyOrganizationList.value = res;
-    //   treeData.value = res.map(li=>({id:li.orgId,data:{name: li.orgName}}))
+      // 默认选择第一个组织
+      if(res[0].orgId){
+        treeNodePreview(res[0])
+        activeName.value = res[0].orgId
+        tableQuery.queryParam.classifyName = res[0].orgId
+      }
+
     } catch (error) {
       ElMessage.error('获取组织列表失败');
     }
   };
-  // 定义组织数据类型
-  interface SafetySystemFormData {
-    value: string; // 输入的组织名称
-    action: 'add' | 'edit'; // 操作类型:新增或编辑
-    orgId?: string | number; // 组织ID(编辑时必传)
-    parentid?: string | number; // 父组织ID(新增子组织时必传)
-    type?: 'children' | 'parent'; // 组织类型(子组织或根组织)
+  // 给架构图赋值
+  const treeNodePreview = (data)=>{
+    let TreeNode = convertData(data)
+    treeData.value = TreeNode
   }
 
-  // 保存弹窗回调
-  const confirmAddSafetySystemCallback = async (formData: SafetySystemFormData) => {
-    try {
-      if (!formData.value?.trim()) {
-        ElMessage.warning('请输入有效的组织名称!');
-        return;
-      }
-      const requestData = {
-        orgName: formData.value.trim(),
-        id: formData.action === 'edit' ? formData.orgId : undefined,
-        parentid: formData.action === 'add' ? formData.parentid : undefined,
-      };
-      // console.log(formData, 'formData')
-      if (formData.action === 'add') {
-        if (formData.type === 'children' && formData.orgId) {
-          requestData.parentid = formData.orgId;
-        }
-        await addSafetySystem(requestData);
-        ElMessage.success('新增组织成功!');
-      } else {
-        // 如果是子类,补充父级ID
-        if (formData.type === 'children' && formData.parentid) {
-          requestData.parentid = formData.parentid;
-        }
-        await updateSafetySystem(requestData);
-        ElMessage.success('编辑组织成功!');
-      }
-      // 刷新列表
-      fetchSafetyOrganizationTeamList();
-    } catch (error) {
-      console.error('操作失败:', error);
-      ElMessage.error(formData.action === 'add' ? '新增组织失败!' : '编辑组织失败!');
-    }
+  // 一级新增
+  const addTeam = (type) => {
+    addSafetyOrganizationSystemFormData.value = {
+      type,
+      action: 'add',
+    };
+    addSafetySystemVisible.value = true;
   };
-  // 级新增
+  // 子级新增
   const handleCreateSafetySystem = async (type, value) => {
+    // console.log('新增参数--',type, value)
     addSafetyOrganizationSystemFormData.value = {
-      type,
+      type:'children',
       action: 'add',
       orgName: value.orgName,
       orgId: value.orgId,
     };
     addSafetySystemVisible.value = true;
     // 打开某一个
-    activeName.value = value.orgId;
+    // activeName.value = value.orgId;
   };
   // 编辑
   const handleEditSafetySystem = (type, value, parentid) => {
-    // console.log(value)
+    // console.log('编辑参数--', type, value, parentid)
     addSafetySystemVisible.value = true;
     addSafetyOrganizationSystemFormData.value = {
       type,
@@ -397,130 +273,183 @@ const position = ref('left')
       parentid,
     };
   };
+
   // 删除
   const handleDelSafetySystem = async (type, value) => {
     // console.log('删除', type, value)
     ElMessageBox.confirm('确认删除该组织吗?', '警告', { type: 'warning' }).then(async () => {
       try {
+        if(value.children.length > 0){
+            ElMessage.error('当前一级组织存在子级数据,无法删除,请先删除子级组织')
+            return 
+        }
         await deleteSafetySystem(value.orgId);
-
         ElMessage.success('删除成功');
-        // 刷新列表
+        // 刷新组织列表
         fetchSafetyOrganizationTeamList();
-        handleReset();
       } catch (error) {
         ElMessage.error(error || '删除失败');
       }
     });
   };
   // 查询
-  const querySafetyTeamData = (type, value) => {
-    console.log(type, '查询', value);
+  const querySafetyTeamData = (value) => {
+    // console.log('查询', value);
     tableQuery.queryParam.classifyName = value.orgId;
-    getTableData();
-  };
-  // 时间查询
-  const onchangeDateRange = () => {
-    if (dateRange.value && Array.isArray(dateRange.value) && dateRange.value.length === 2) {
-      tableQuery.queryParam.startTime = dateRange.value[0] || '';
-      tableQuery.queryParam.endTime = dateRange.value[1] || '';
-    } else {
-      tableQuery.queryParam.startTime = '';
-      tableQuery.queryParam.endTime = '';
-    }
-    getTableData();
-  };
-  const handleSearch = () => {
-    pagination.pageNumber = 1;
-    tableQuery.pageNumber = 1;
-    getTableData();
-  };
-
-  const handleReset = () => {
-    pagination.pageNumber = 1;
-    tableQuery.queryParam = {
-      classifyName: '',
-      keyword: '',
-      status: '', // 重置为默认启用状态
-      startTime: '',
-      endTime: '',
-    };
-    dateRange.value = '';
-    handleSearch();
-  };
-
-  // 批量导入
-  const batchImportVisible = ref(false);
-  const { urlPrefix } = useGlobSetting();
-  const importApiUrl = ref(urlJoin(urlPrefix, '/safetyorguser/importSafetyOrgUser'));
-  const templateUrl = ref('./skyeye-file-upload/sfysecurity/TEMPLATE/安全组织体系管理导入模版.xlsx');
-
-  const handleImport = () => {
-    batchImportVisible.value = true;
+    treeNodePreview(value)
   };
 
-  const handleUpdate = () => {
-    batchImportVisible.value = false;
-    getTableData();
-  };
-
-  const handleDownload = async () => {
+    // 定义组织数据类型
+  interface SafetySystemFormData {
+    value: string; // 输入的组织名称
+    action: 'add' | 'edit'; // 操作类型:新增或编辑
+    orgId?: string | number; // 组织ID(编辑时必传)
+    parentid?: string | number; // 父组织ID(新增子组织时必传)
+    type?: 'children' | 'parent'; // 组织类型(子组织或根组织)
+  }
+   // 保存弹窗回调
+  const confirmAddSafetySystemCallback = async (formData: SafetySystemFormData) => {
     try {
-      const response = await exportSafetyOrganizationSystemManagement(tableQuery.queryParam);
-      if (response) {
-        const fileName = `安全组织体系管理_${new Date().toISOString().split('T')[0]}.xlsx`;
-        downloadByData(response, fileName);
-        ElMessage.success('导出成功');
+      if (!formData.value?.trim()) {
+        ElMessage.warning('请输入有效的组织名称!');
+        return;
+      }
+      // 新增时,传orgName(组织名称)、parentid(父组织ID)
+      // 编辑时,传当前ID和orgName
+      const requestData = {
+        orgName: formData.value.trim(),
+        id: formData.action === 'edit' ? formData.orgId : undefined,
+        // 第一级不需要传parentid
+        parentid: formData.action === 'add' ? formData.parentid : undefined,
+      };
+      console.log(formData, '参数--formData')
+      if (formData.action === 'add') {
+        if (formData.type === 'children' && formData.orgId) {
+          requestData.parentid = formData.orgId;
+        }
+        await addSafetySystem(requestData);
+        ElMessage.success('新增组织成功!');
+      } else {
+        // 如果是子类,补充父级ID
+        if (formData.type === 'children' && formData.parentid) {
+          requestData.parentid = formData.parentid;
+        }
+        await updateSafetySystem(requestData);
+        ElMessage.success('编辑组织成功!');
       }
-    } catch (e) {
-      console.error('导出安全组织体系管理失败:', e);
-      ElMessage.error('导出失败,请重试');
+      // 刷新列表
+      fetchSafetyOrganizationTeamList();
+    } catch (error) {
+      console.error('操作失败:', error);
+      ElMessage.error(formData.action === 'add' ? '新增组织失败!' : '编辑组织失败!');
     }
   };
 
-  const handleCreate = () => {
-    router.push({
-      name: 'SafetyOrganizationSystemManagementItem',
-      query: {
-        operate: 'employee-create',
-      },
-    });
-  };
-
-  const handleEdit = (id: number) => {
-    router.push({
-      name: 'SafetyOrganizationSystemManagementItem',
-      query: {
-        id,
-        operate: 'employee-edit',
-      },
-    });
-  };
-
-  const handleDelete = async (id: number) => {
-    try {
-      await delEmployee(id);
-      ElMessage.success('删除成功');
-      getTableData();
-    } catch (e) {
-      console.error('删除员工失败:', e);
-      ElMessage.error('删除失败,请重试');
-    }
-  };
+  const toStaff = ()=>{
+    router.push({name: 'securityOrganizationalStructure', query: {id: tableQuery.queryParam.classifyName}})
+  }
+  // 时间查询
+//   const onchangeDateRange = () => {
+//     if (dateRange.value && Array.isArray(dateRange.value) && dateRange.value.length === 2) {
+//       tableQuery.queryParam.startTime = dateRange.value[0] || '';
+//       tableQuery.queryParam.endTime = dateRange.value[1] || '';
+//     } else {
+//       tableQuery.queryParam.startTime = '';
+//       tableQuery.queryParam.endTime = '';
+//     }
+//     getTableData();
+//   };
+//   const handleSearch = () => {
+//     pagination.pageNumber = 1;
+//     tableQuery.pageNumber = 1;
+//     getTableData();
+//   };
+
+//   const handleReset = () => {
+//     pagination.pageNumber = 1;
+//     tableQuery.queryParam = {
+//       classifyName: '',
+//       keyword: '',
+//       status: '', // 重置为默认启用状态
+//       startTime: '',
+//       endTime: '',
+//     };
+//     dateRange.value = '';
+//     handleSearch();
+//   };
 
-  const handleView = (id: number) => {
-    router.push({
-      name: 'SafetyOrganizationSystemManagementItem',
-      query: {
-        id,
-        operate: 'employee-view',
-      },
-    });
-  };
+  // 批量导入
+//   const batchImportVisible = ref(false);
+//   const { urlPrefix } = useGlobSetting();
+//   const importApiUrl = ref(urlJoin(urlPrefix, '/safetyorguser/importSafetyOrgUser'));
+//   const templateUrl = ref('./skyeye-file-upload/sfysecurity/TEMPLATE/安全组织体系管理导入模版.xlsx');
+
+//   const handleImport = () => {
+//     batchImportVisible.value = true;
+//   };
+
+//   const handleUpdate = () => {
+//     batchImportVisible.value = false;
+//     getTableData();
+//   };
+
+//   const handleDownload = async () => {
+//     try {
+//       const response = await exportSafetyOrganizationSystemManagement(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('导出失败,请重试');
+//     }
+//   };
+
+//   const handleCreate = () => {
+//     router.push({
+//       name: 'SafetyOrganizationSystemManagementItem',
+//       query: {
+//         operate: 'employee-create',
+//       },
+//     });
+//   };
+
+//   const handleEdit = (id: number) => {
+//     router.push({
+//       name: 'SafetyOrganizationSystemManagementItem',
+//       query: {
+//         id,
+//         operate: 'employee-edit',
+//       },
+//     });
+//   };
+
+//   const handleDelete = async (id: number) => {
+//     try {
+//       await delEmployee(id);
+//       ElMessage.success('删除成功');
+//       getTableData();
+//     } catch (e) {
+//       console.error('删除员工失败:', e);
+//       ElMessage.error('删除失败,请重试');
+//     }
+//   };
+
+//   const handleView = (id: number) => {
+//     router.push({
+//       name: 'SafetyOrganizationSystemManagementItem',
+//       query: {
+//         id,
+//         operate: 'employee-view',
+//       },
+//     });
+//   };
 
   onMounted(() => {
     fetchSafetyOrganizationTeamList();
-    getTableData();
+    // getTableData();
   });
 </script>
 
@@ -529,8 +458,12 @@ const position = ref('left')
   @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 {
-  }
+ .text-right{
+    text-align: right;
+ }
+ .mb-4{
+    margin-bottom: 12px;
+ }
   .nav {
     flex: 0 0 300px;
     margin-right: 15px;

+ 1 - 1
src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/components/safetyOrganizationSystemManagementDetail.vue

@@ -34,7 +34,7 @@
           v-model="form.jobResp"
           type="textarea"
           :rows="4"
-          :maxlength="300"
+          :maxlength="200"
           placeholder="请填写岗位职责"
           :disabled="isViewMode"
         />

+ 3 - 2
src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/configs/tables.ts

@@ -2,7 +2,7 @@
  * @Author: liuJie
  * @Date: 2026-01-27 16:29:28
  * @LastEditors: liuJie
- * @LastEditTime: 2026-03-07 20:34:07
+ * @LastEditTime: 2026-03-29 21:52:01
  * @Describe: file describe
  */
 import type { TableColumnProps } from '@/types/basic-table';
@@ -38,7 +38,7 @@ export const TABLE_COLUMNS: TableColumnProps[] = [
     prop: 'status',
     slot: 'status',
     align: 'left',
-    minWidth: '120px',
+    minWidth: '90px',
   },
 
   {
@@ -52,6 +52,7 @@ export const TABLE_COLUMNS: TableColumnProps[] = [
     prop: 'jobResp',
     align: 'left',
     minWidth: '150px',
+    showOverflowTooltip: true,
   },
   {
     label: '添加时间',

+ 33 - 66
src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/securityOrganizationalStructure.vue

@@ -8,63 +8,25 @@
         <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>
-                  <div class="handler">
-                    <el-button :icon="Plus" size="small" type="default" dashed @click.stop="handleCreateSafetySystem('children', item)"
-                      ></el-button
-                    >
-                    <el-button size="small" type="primary" link @click.stop="handleEditSafetySystem('parent', item, '')"
-                      >编辑</el-button
-                    >
-                    <el-button  size="small" type="danger" link @click.stop="handleDelSafetySystem('parent', item)"
-                      >删除</el-button
-                    >
-                  </div>
-                </div>
-              </template>
-              <div class="collapse-item-content">
-                <div v-if="item.children.length > 0">
-                  <ul>
-                    <li class="flex" v-for="children in item.children" :key="children.orgId">
-                      <span @click="querySafetyTeamData('children', children)">
-                        {{ children.orgName }}
-                      </span>
-                      <div class="handler">
-                        <el-button
-                          link
-                          size="small"
-                          type="primary"
-                          @click.stop="handleEditSafetySystem('children', children, item.orgId)"
-                          >编辑</el-button
-                        >
-                        <el-button
-                          link
-                          size="small"
-                          type="danger"
-                          @click.stop="handleDelSafetySystem('children', children)"
-                          >删除</el-button
-                        >
-                      </div>
-                    </li>
-                  </ul>
-                </div>
-                <div v-else>
-                  <el-empty description="未添加子组织" :image-size="40" />
-                </div>
-              </div>
-            </el-collapse-item>
-          </el-collapse>
+            <!-- 组织树 -->
+            <el-collapse v-model="activeName" accordion v-if="fetchSafetyOrganizationList.length > 0">
+                <CollapseItem
+                    v-for="item in fetchSafetyOrganizationList"
+                    :key="item.id"
+                    :data="item"
+                    :level="level"
+                    @click-node="querySafetyTeamData"
+                    @create-node="handleCreateSafetySystem"
+                    @edit-node="handleEditSafetySystem"
+                    @delete-node="handleDelSafetySystem"
+                />
+            </el-collapse>
+           
           <div v-else>
             <el-empty description="未添加组织" />
           </div>
         </div>
+        <!-- 添加、编辑组织弹窗 -->
         <AddSafetySystem
           v-model:visible="addSafetySystemVisible"
           :data="addSafetyOrganizationSystemFormData"
@@ -166,7 +128,7 @@
   import useTableConfig from '@/hooks/useTableConfigHook';
   import ActionButton from '@/components/ActionButton.vue';
   import { TABLE_OPTIONS, TABLE_COLUMNS } from './configs/tables';
-  import { useRouter } from 'vue-router';
+  import { useRouter, useRoute } from 'vue-router';
   import type { QueryPageRequest } from '@/types/basic-query';
   import {
     getSafetySystemList,
@@ -187,9 +149,9 @@
   Edit,
   Plus,
 } from '@element-plus/icons-vue'
-
+import CollapseItem from '../safetyOrganizationSystemManagement/components/collapseItem.vue'
 const position = ref('left')
-
+  const route = useRoute();
   const router = useRouter();
   // 表格
   const basicTableRef = ref<InstanceType<typeof BasicTable>>();
@@ -203,7 +165,7 @@ const position = ref('left')
   const activeName = ref('');
   // 日期范围(用于日期选择器)
   const dateRange = ref<[string, string] | string>('');
-
+  const level = ref(1)
   const tableQuery = reactive<QueryPageRequest<any>>({
     pageNumber: pagination.pageNumber,
     pageSize: pagination.pageSize,
@@ -324,14 +286,14 @@ const position = ref('left')
   // 二级新增
   const handleCreateSafetySystem = async (type, value) => {
     addSafetyOrganizationSystemFormData.value = {
-      type,
+      type:'children',
       action: 'add',
       orgName: value.orgName,
       orgId: value.orgId,
     };
     addSafetySystemVisible.value = true;
     // 打开某一个
-    activeName.value = value.orgId;
+    // activeName.value = value.orgId;
   };
   // 编辑
   const handleEditSafetySystem = (type, value, parentid) => {
@@ -350,8 +312,11 @@ const position = ref('left')
     // console.log('删除', type, value)
     ElMessageBox.confirm('确认删除该组织吗?', '警告', { type: 'warning' }).then(async () => {
       try {
+        if(value.children.length > 0){
+            ElMessage.error('当前一级组织存在子级数据,无法删除,请先删除子级组织')
+            return 
+        }
         await deleteSafetySystem(value.orgId);
-
         ElMessage.success('删除成功');
         // 刷新列表
         fetchSafetyOrganizationTeamList();
@@ -362,8 +327,8 @@ const position = ref('left')
     });
   };
   // 查询
-  const querySafetyTeamData = (type, value) => {
-    console.log(type, '查询', value);
+  const querySafetyTeamData = (value) => {
+    // console.log('查询', value);
     tableQuery.queryParam.classifyName = value.orgId;
     getTableData();
   };
@@ -428,7 +393,7 @@ const position = ref('left')
 
   const handleCreate = () => {
     router.push({
-      name: 'SafetyOrganizationSystemManagementItem',
+      name: 'SecurityOrganizationalStructureItem',
       query: {
         operate: 'employee-create',
       },
@@ -437,7 +402,7 @@ const position = ref('left')
 
   const handleEdit = (id: number) => {
     router.push({
-      name: 'SafetyOrganizationSystemManagementItem',
+      name: 'SecurityOrganizationalStructureItem',
       query: {
         id,
         operate: 'employee-edit',
@@ -458,16 +423,18 @@ const position = ref('left')
 
   const handleView = (id: number) => {
     router.push({
-      name: 'SafetyOrganizationSystemManagementItem',
+      name: 'SecurityOrganizationalStructureItem',
       query: {
         id,
         operate: 'employee-view',
       },
     });
   };
-
   onMounted(() => {
     fetchSafetyOrganizationTeamList();
+    // 默认读取上个选中架构组织的员工数据
+    const orgId = route.query.id as string;
+    tableQuery.queryParam.classifyName = orgId || undefined
     getTableData();
   });
 </script>

src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/securityOrganizationalStructureItme.vue → src/views/production-safety/productionSafetySystem/securityOrganizationalStructure/securityOrganizationalStructureItem.vue


+ 4 - 4
src/views/production-safety/risk-identification-and-control/work-injury-apply-manage/listAdmin.vue

@@ -316,7 +316,7 @@
 
   const handleCreate = () => {
     router.push({
-      name: 'workInjuryApplyManageItem',
+      name: 'workInjuryApplyManageAdminItem',
       query: {
         operate: 'inventory-create',
       },
@@ -325,7 +325,7 @@
 
   const handleEdit = (id: number,row: any) => {
     router.push({
-      name: 'workInjuryApplyManageItem',
+      name: 'workInjuryApplyManageAdminItem',
       query: {
         id,
         rejectReason:row.rejectReason ?? '',
@@ -340,7 +340,7 @@
 
   const handleAudit = (id: number,row: any) => {
     router.push({
-      name: 'workInjuryApplyManageItem',
+      name: 'workInjuryApplyManageAdminItem',
       query: {
         id,
         approvalTemplateId:row.templateId ?? '',
@@ -363,7 +363,7 @@
 
   const handleView = (id: number) => {
     router.push({
-      name: 'workInjuryApplyManageItem',
+      name: 'workInjuryApplyManageAdminItem',
       query: {
         id,
         operate: 'inventory-view',

+ 1 - 1
src/views/production-safety/safetyTrainingAndEducation/employeeTrainingRecordCardManagement/employeeTrainingRecordCardManagement.vue

@@ -46,7 +46,7 @@
             <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 plain  @click="handleDownload">
                 导出
             </el-button>
             </section>