فهرست منبع

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

sunqijun 3 هفته پیش
والد
کامیت
2078c288ae
32فایلهای تغییر یافته به همراه858 افزوده شده و 168 حذف شده
  1. 10 0
      src/api/emergency-organization/teams.ts
  2. BIN
      src/assets/images/institute-safety/default-propaganda.jpeg
  3. 0 0
      src/assets/images/institute-safety/sfy.jpg
  4. BIN
      src/assets/images/institute-safety/workshop-list.png
  5. 0 0
      src/assets/images/production-safety/index.ts
  6. 1 1
      src/views/emergency/components/OrgChart.vue
  7. 1 1
      src/views/emergency/emergency-drill/configs/plan/form.ts
  8. 116 14
      src/views/emergency/organization/PageOrganization.vue
  9. 213 0
      src/views/emergency/organization/components/TeamDetailList.vue
  10. 16 1
      src/views/emergency/organization/team-management/store/userTeam.ts
  11. 4 3
      src/views/emergency/organization/team-management/type.ts
  12. 20 1
      src/views/emergency/overview/components/EmergencySupplies.vue
  13. 6 3
      src/views/institute-safety/components/CardEmergencyManage.vue
  14. 2 2
      src/views/institute-safety/components/CardMapAndAlert.vue
  15. 13 4
      src/views/institute-safety/modules/safety-company-home/CompanyHome.vue
  16. 30 0
      src/views/institute-safety/modules/safety-company-home/apis/index.ts
  17. 5 0
      src/views/institute-safety/modules/safety-company-home/components/ControlTab.vue
  18. 150 0
      src/views/institute-safety/modules/safety-company-home/components/WorkshopList.vue
  19. 0 0
      src/views/institute-safety/modules/safety-company-home/constants.ts
  20. 1 2
      src/views/institute-safety/modules/safety-company-home/hooks/use-violation-notice-company.ts
  21. 118 0
      src/views/institute-safety/modules/safety-propaganda/SafetyPropaganda.vue
  22. 0 105
      src/views/institute-safety/modules/safety-workshop-list/WorkshopList.vue
  23. 0 17
      src/views/institute-safety/modules/safety-workshop-list/apis/index.ts
  24. 117 14
      src/views/production-safety/safety-culture/safetyPublicityBoardManagement/components/safetyPublicityBoardManagementDetail.vue
  25. 10 0
      src/views/production-safety/safety-culture/safetyPublicityBoardManagement/configs/form.ts
  26. 1 0
      src/views/production-safety/safety-culture/safetyPublicityBoardManagement/configs/tables.ts
  27. 4 0
      src/views/security-confidentiality/confidentiality-regulation-notice/components/NoticeTable.vue
  28. 4 0
      src/views/security-confidentiality/confidentiality-regulation-notice/components/RegulationTable.vue
  29. 4 0
      src/views/security-confidentiality/security-regulation-notice/components/NoticeTable.vue
  30. 4 0
      src/views/security-confidentiality/security-regulation-notice/components/RegulationTable.vue
  31. 4 0
      src/views/traffic/regulation/components/NoticeTable.vue
  32. 4 0
      src/views/traffic/regulation/components/RegulationTable.vue

+ 10 - 0
src/api/emergency-organization/teams.ts

@@ -22,6 +22,16 @@ export function queryEmergencyTeamDetail(teamId: number) {
   });
 }
 
+/**
+ * 查询所有队伍详细信息
+ */
+export function queryAllEmergencyTeamDetail() {
+  return http.request<TeamAndPersonInfoType[]>({
+    url: '/emergencySystem/queryAllEmergencyTeamDetail',
+    method: 'get',
+  });
+}
+
 export type SetTeamInfoType = {
   id: number;
   memberCount?: number;

BIN
src/assets/images/institute-safety/default-propaganda.jpeg


src/assets/images/sfy.jpg → src/assets/images/institute-safety/sfy.jpg


BIN
src/assets/images/institute-safety/workshop-list.png


+ 0 - 0
src/assets/images/production-safety/index.ts


+ 1 - 1
src/views/emergency/components/OrgChart.vue

@@ -102,7 +102,7 @@
         animation: true, // 启用布局动画
       },
       autoFit: {
-        type: 'center', // 自适应类型:'view' 或 'center'
+        type: 'view', // 自适应类型:'view' 或 'center'
         // options: {
         //   // 仅适用于 'view' 类型
         //   when: 'always', // 何时适配:'overflow'(仅当内容溢出时) 或 'always'(总是适配)

+ 1 - 1
src/views/emergency/emergency-drill/configs/plan/form.ts

@@ -201,7 +201,7 @@ export const DRILL_RECORD_FORM_CONFIG: FormConfig[] = [
       maxlength: 2000,
       showWordLimit: true,
       autosize: { minRows: 5 },
-      placeholder: '请描述演练问题分析,不超过2000字',
+      placeholder: '请描述演练问题分析,没有问题请填写“无”,不超过2000字',
     },
   },
   {

+ 116 - 14
src/views/emergency/organization/PageOrganization.vue

@@ -3,25 +3,47 @@
     <div class="safety-platform-container__header">
       <div class="breadcrumb-title"> 应急架构体系 </div>
     </div>
-    <div class="safety-platform-container__main">
-      <OrgChart :treeData="treeData" @node-click="handleNodeClick" v-if="treeData.id !== '-1'" />
-      <div v-else class="no-data">暂无队伍</div>
+    <div class="safety-platform-container__main" :class="{ 'zoom-mode': isChartZoomed }">
+      <div class="chart-container" ref="chartContainerRef" v-loading="loadingTeams">
+        <OrgChart
+          :treeData="treeData"
+          @node-click="handleNodeClick"
+          @canvas-click="handleCanvasClick"
+          v-if="treeData.id !== '-1'"
+        />
+        <div class="no-data" v-else>暂无队伍</div>
+        <div class="chart-actions">
+          <el-button v-if="!isChartFullscreen" size="small" @click="toggleChartZoom">
+            {{ isChartZoomed ? '恢复布局' : '放大模式' }}
+          </el-button>
+          <el-button size="small" @click="toggleChartFullscreen">
+            {{ isChartFullscreen ? '退出全屏' : '全屏查看' }}
+          </el-button>
+        </div>
+      </div>
+      <div class="detail-container" v-loading="loadingTeamsDetail">
+        <TeamDetailList :selected-team-id="selectedTeamId" class="team-detail" />
+      </div>
     </div>
     <div class="safety-platform-container__footer" v-if="showOperationBar">
       <el-button @click="router.push('team-management')"> 编辑 </el-button>
     </div>
   </div>
-  <TeamDetailDrawer ref="teamDetailDrawerRef" :selected-team-id="selectedTeamId" />
 </template>
 
 <script setup lang="ts">
-  import { ref, onMounted } from 'vue';
+  import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
   import { useRouter } from 'vue-router';
-  import OrgChart from '../components/OrgChart.vue';
-  import TeamDetailDrawer from './components/TeamDetailDrawer.vue';
+  import { storeToRefs } from 'pinia';
   import { useUserInfoHook } from '@/views/disaster/hooks';
   import useTeamStore from './team-management/store/userTeam';
   import { EMERGENCY_PERMISSIONS } from '@/views/emergency/constant';
+  import OrgChart from '../components/OrgChart.vue';
+  import TeamDetailList from './components/TeamDetailList.vue';
+
+  const { permissions } = useUserInfoHook();
+  const { loadingTeams, loadingTeamsDetail } = storeToRefs(useTeamStore());
+  const { getLeaderTeams } = useTeamStore();
 
   type OrganizationTreeType = {
     id: string;
@@ -51,20 +73,49 @@
   const router = useRouter();
 
   const showOperationBar = ref(false);
-
-  const { permissions } = useUserInfoHook();
-  const { getLeaderTeams } = useTeamStore();
-
-  const teamDetailDrawerRef = ref<InstanceType<typeof TeamDetailDrawer>>();
+  const chartContainerRef = ref<HTMLElement | null>(null);
+  const isChartFullscreen = ref(false);
+  const isChartZoomed = ref(false);
 
   const selectedTeamId = ref<number | null>(null);
 
   const handleNodeClick = (nodeData: any) => {
     selectedTeamId.value = Number(nodeData.id);
+  };
 
-    teamDetailDrawerRef.value?.drawerShow();
+  const handleCanvasClick = () => {
+    selectedTeamId.value = null;
   };
 
+  async function toggleChartFullscreen() {
+    const el = chartContainerRef.value;
+    if (!el) return;
+
+    if (document.fullscreenElement === el) {
+      await document.exitFullscreen();
+      await triggerChartResize();
+      return;
+    }
+
+    await el.requestFullscreen();
+    await triggerChartResize();
+  }
+
+  async function toggleChartZoom() {
+    isChartZoomed.value = !isChartZoomed.value;
+    await triggerChartResize();
+  }
+
+  function syncFullscreenState() {
+    isChartFullscreen.value = document.fullscreenElement === chartContainerRef.value;
+  }
+
+  async function triggerChartResize() {
+    await nextTick();
+    // G6 组件内部监听 window resize,这里主动触发一次确保尺寸立即更新
+    window.dispatchEvent(new Event('resize'));
+  }
+
   function convertData(leaderTeams): OrganizationTreeType {
     return {
       id: leaderTeams.teamId.toString(),
@@ -76,19 +127,70 @@
   }
 
   onMounted(async () => {
+    document.addEventListener('fullscreenchange', syncFullscreenState);
+
     showOperationBar.value = Boolean(
       permissions.find((item: { code: string }) => item.code === EMERGENCY_PERMISSIONS.ORGANIZATION_MANAGEMENT),
     );
 
     const res = await getLeaderTeams();
-
     treeData.value = convertData(res);
   });
+
+  onBeforeUnmount(() => {
+    document.removeEventListener('fullscreenchange', syncFullscreenState);
+  });
 </script>
 
 <style lang="scss" scoped>
   @use '@/styles/page-details-layout.scss' as *;
 
+  .chart-container {
+    position: relative;
+    width: 100%;
+    height: 40%;
+    box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
+    border-radius: 8px;
+  }
+
+  .chart-container:fullscreen {
+    height: 100%;
+    padding: 12px;
+    background: #ffffff;
+    border-radius: 0;
+  }
+
+  .chart-actions {
+    position: absolute;
+    display: flex;
+    gap: 8px;
+    right: 12px;
+    bottom: 12px;
+    z-index: 2;
+  }
+
+  .safety-platform-container__main.zoom-mode {
+    .chart-container {
+      height: 75%;
+    }
+
+    .detail-container {
+      height: 25%;
+    }
+  }
+
+  .detail-container {
+    width: 100%;
+    height: 60%;
+    padding-top: 20px;
+    overflow: auto;
+
+    .team-detail {
+      width: 60%;
+      margin: 0 auto;
+    }
+  }
+
   .no-data {
     width: 100%;
     height: 100%;

+ 213 - 0
src/views/emergency/organization/components/TeamDetailList.vue

@@ -0,0 +1,213 @@
+<template>
+  <div class="team-detail-list">
+    <template v-if="displayTeams.length">
+      <section v-for="team in displayTeams" :key="team.teamId" class="team-detail-list__section">
+        <header class="team-detail-list__header">
+          <h2 class="team-detail-list__title">{{ team.teamName }}</h2>
+          <span class="team-detail-list__count">共{{ team.memberCount ?? 0 }}人</span>
+        </header>
+
+        <div
+          v-for="row in roleRowsForTeam(team.personnelList)"
+          :key="`${team.teamId}-${row.positionLevel}`"
+          class="team-detail-list__role-row"
+        >
+          <span class="team-detail-list__role-pill">{{ row.title }}</span>
+          <div class="team-detail-list__names">
+            <el-tooltip v-for="person in row.members" :key="person.id" placement="top" effect="light" :show-after="200">
+              <template #content>
+                <div class="team-detail-list__tooltip">
+                  <div>部门:{{ person.department || '—' }}</div>
+                  <div>工号:{{ person.staffNo || '—' }}</div>
+                  <div>手机:{{ person.mobile || '—' }}</div>
+                </div>
+              </template>
+              <span class="team-detail-list__name">{{ person.realname }}</span>
+            </el-tooltip>
+          </div>
+        </div>
+
+        <div v-if="team.description?.trim()" class="team-detail-list__duty">
+          <h3 class="team-detail-list__duty-title">队伍职责</h3>
+          <div class="team-detail-list__duty-content">{{ team.description }}</div>
+        </div>
+      </section>
+    </template>
+    <div v-else class="team-detail-list__empty">暂无队伍详情</div>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { computed, ref, onMounted } from 'vue';
+  import useTeamStore from '../team-management/store/userTeam';
+  import type { TeamAndPersonInfoType, TeamPersonnelInfoType } from '../team-management/type';
+
+  const props = defineProps<{
+    selectedTeamId: number | null;
+  }>();
+
+  type RoleRow = {
+    positionLevel: number;
+    title: string;
+    members: TeamPersonnelInfoType[];
+  };
+
+  const teamStore = useTeamStore();
+  const teams = ref<TeamAndPersonInfoType[]>([]);
+  const displayTeams = computed(() => {
+    if (props.selectedTeamId === null) return teams.value;
+    return teams.value.filter((team) => team.teamId === props.selectedTeamId);
+  });
+
+  function roleRowsForTeam(personnelList: TeamPersonnelInfoType[] | undefined): RoleRow[] {
+    if (!personnelList?.length) return [];
+    const levelMap = new Map<number, RoleRow>();
+    for (const person of personnelList) {
+      const level = person.positionLevel;
+      if (!levelMap.has(level)) {
+        levelMap.set(level, {
+          positionLevel: level,
+          title: person.title || '成员',
+          members: [],
+        });
+      }
+      levelMap.get(level)!.members.push(person);
+    }
+    return [...levelMap.values()].sort((a, b) => a.positionLevel - b.positionLevel);
+  }
+
+  onMounted(async () => {
+    teams.value = await teamStore.getAllEmergencyTeamDetail();
+  });
+</script>
+
+<style scoped lang="scss">
+  $primary: #1777ff;
+  $text: #333333;
+  $text-muted: #666666;
+
+  .team-detail-list {
+    padding: 0 10px;
+  }
+
+  .team-detail-list__section {
+    padding: 18px 20px 20px;
+    background: #ffffff;
+    border: 1px solid #e8eef8;
+    border-left: 4px solid $primary;
+    border-radius: 10px;
+    box-shadow: 0 4px 14px rgba(23, 119, 255, 0.06);
+
+    & + & {
+      margin-top: 18px;
+    }
+  }
+
+  .team-detail-list__header {
+    display: flex;
+    align-items: baseline;
+    justify-content: space-between;
+    gap: 16px;
+    margin: -18px -20px 16px;
+    padding: 12px 20px;
+    background: linear-gradient(90deg, rgba(23, 119, 255, 0.08), rgba(23, 119, 255, 0.02));
+    border-bottom: 1px solid #edf2fb;
+    border-radius: 10px 10px 0 0;
+
+    .team-detail-list__title {
+      margin: 0;
+      font-size: 18px;
+      font-weight: 600;
+      color: $text;
+    }
+
+    .team-detail-list__count {
+      flex-shrink: 0;
+      font-size: 14px;
+      color: $primary;
+    }
+  }
+
+  .team-detail-list__role-row {
+    display: flex;
+    align-items: flex-start;
+    gap: 16px;
+    margin-bottom: 14px;
+  }
+
+  .team-detail-list__role-pill {
+    flex-shrink: 0;
+    min-width: 56px;
+    padding: 4px 14px;
+    font-size: 13px;
+    color: $primary;
+    text-align: center;
+    background: #ffffff;
+    border: 1px solid $primary;
+    border-radius: 999px;
+  }
+
+  .team-detail-list__names {
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+    gap: 12px 24px;
+    padding-top: 2px;
+    line-height: 1.5;
+  }
+
+  .team-detail-list__name {
+    cursor: default;
+    font-size: 14px;
+    color: $text-muted;
+    border-bottom: 1px dashed transparent;
+
+    &:hover {
+      color: $primary;
+      border-bottom-color: rgba($primary, 0.35);
+    }
+  }
+
+  .team-detail-list__tooltip {
+    padding: 2px 0;
+    font-size: 13px;
+    line-height: 1.6;
+    color: $text-muted;
+
+    div + div {
+      margin-top: 4px;
+    }
+  }
+
+  :deep(.el-tooltip__trigger) {
+    display: inline-block;
+  }
+
+  .team-detail-list__duty {
+    margin-top: 22px;
+    padding-top: 14px;
+    border-top: 1px dashed #dbe7fb;
+  }
+
+  .team-detail-list__duty-title {
+    margin: 0 0 10px;
+    font-size: 15px;
+    font-weight: 600;
+    color: $text;
+  }
+
+  .team-detail-list__duty-content {
+    margin: 0;
+    font-size: 14px;
+    line-height: 1.7;
+    color: $text-muted;
+    white-space: pre-wrap;
+  }
+
+  .team-detail-list__empty {
+    padding: 48px 0;
+    text-align: center;
+    font-size: 14px;
+    color: #999999;
+  }
+</style>

+ 16 - 1
src/views/emergency/organization/team-management/store/userTeam.ts

@@ -1,7 +1,11 @@
 import { ref } from 'vue';
 import { defineStore } from 'pinia';
 import { LeaderTeamType, TeamAndPersonInfoType } from '../type';
-import { queryLeaderTeam, queryEmergencyTeamDetail } from '@/api/emergency-organization/teams';
+import {
+  queryLeaderTeam,
+  queryEmergencyTeamDetail,
+  queryAllEmergencyTeamDetail,
+} from '@/api/emergency-organization/teams';
 import { PositionType, saveTeamPosition } from '@/api/emergency-organization/teams';
 import {
   SetTeamInfoType,
@@ -23,9 +27,18 @@ const useTeamStore = defineStore('useTeam', () => {
   const curTeam = ref<LeaderTeamType>();
   const teamAndPersonInfo = ref<TeamAndPersonInfoType>(); // 右侧的队伍信息和人员信息表格数据
 
+  const loadingTeamsDetail = ref(false);
   const loadingTeams = ref(false);
   const loadingTeamInfo = ref(false);
 
+  // 获取所有队伍详细信息
+  async function getAllEmergencyTeamDetail() {
+    loadingTeamsDetail.value = true;
+    const res = await queryAllEmergencyTeamDetail();
+    loadingTeamsDetail.value = false;
+    return res ?? [];
+  }
+
   async function getLeaderTeams() {
     loadingTeams.value = true;
 
@@ -152,8 +165,10 @@ const useTeamStore = defineStore('useTeam', () => {
     leaderTeamTree,
     curTeam,
     teamAndPersonInfo,
+    loadingTeamsDetail,
     loadingTeams,
     loadingTeamInfo,
+    getAllEmergencyTeamDetail,
     getLeaderTeams,
     createFirstLevelTeam,
     createTeam,

+ 4 - 3
src/views/emergency/organization/team-management/type.ts

@@ -18,14 +18,15 @@ export type TeamInfoType = {
 };
 
 export type TeamPersonnelInfoType = {
-  teamId: number;
+  id: number;
   userId: number;
   realname: string;
+  teamId: number;
   positionId: number; //	职位ID
-  positionLevel: number; //	职位等级
   jobTitle: string; //职务
-  title: string; //  岗位职责
   staffNo: string;
   department: string;
   mobile: string;
+  title: string; // 职位名称
+  positionLevel: number; //	职位等级
 };

+ 20 - 1
src/views/emergency/overview/components/EmergencySupplies.vue

@@ -87,11 +87,30 @@
 
     .supply-list {
       width: 100%;
-      height: calc(100% - 102px);
+      height: calc(100% - 100px);
       padding: 0 10px;
       display: grid;
       grid-template-columns: repeat(2, 1fr);
       grid-gap: 10px;
+      overflow-y: auto;
+
+      /* 自定义滚动条样式 */
+      &::-webkit-scrollbar {
+        width: 6px;
+      }
+
+      // &::-webkit-scrollbar-track {
+      //   background: #f1f1f1;
+      //   border-radius: 3px;
+      // }
+
+      &::-webkit-scrollbar-thumb {
+        border-radius: 3px;
+      }
+
+      // &::-webkit-scrollbar-thumb:hover {
+      //   background: #a8a8a8;
+      // }
 
       .supply-item {
         background: linear-gradient(90deg, #dbfaff 0%, #f5faff 100%);

+ 6 - 3
src/views/institute-safety/components/CardEmergencyManage.vue

@@ -103,7 +103,7 @@
         align: 'left',
         itemWidth: 6,
         itemHeight: 6,
-        itemGap: 10,
+        itemGap: 9,
         icon: 'circle',
         formatter: (name: string) => {
           const itemIndex = variousTypeSuppliesRatio.value.findIndex((item) => item.suppliesTypeName === name);
@@ -120,6 +120,8 @@
       series: [
         {
           type: 'pie',
+          left: '30',
+          top: '0',
           radius: ['60%', '90%'],
           center: ['20%', '50%'],
           avoidLabelOverlap: false,
@@ -259,7 +261,8 @@
   }
 
   .chart {
-    height: 100px;
-    margin: 34px 24px 24px 20px;
+    height: 130px;
+    margin-right: 20px;
+    // margin: 34px 24px 24px 20px;
   }
 </style>

+ 2 - 2
src/views/institute-safety/components/CardMapAndAlert.vue

@@ -1,13 +1,13 @@
 <template>
   <div class="map-alert">
     <CompanyHome />
-    <WorkshopList />
+    <SafetyPropaganda />
   </div>
 </template>
 
 <script setup lang="ts">
   import CompanyHome from '@/views/institute-safety/modules/safety-company-home/CompanyHome.vue';
-  import WorkshopList from '@/views/institute-safety/modules/safety-workshop-list/WorkshopList.vue';
+  import SafetyPropaganda from '@/views/institute-safety/modules/safety-propaganda/SafetyPropaganda.vue';
 </script>
 
 <style scoped>

+ 13 - 4
src/views/institute-safety/modules/safety-company-home/CompanyHome.vue

@@ -1,10 +1,15 @@
 <template>
   <div class="company-home" id="company-home">
     <RealtimeSurveillance v-if="curCamera?.code" />
-    <img v-else style="width: 100%" src="@/assets/images/sfy.jpg" alt="" />
+    <img v-else style="width: 100%" src="@/assets/images/institute-safety/sfy.jpg" alt="" />
     <CompanyRating v-if="!curCamera?.code" />
-    <ControlTab @open-surveillance-list="showSurveillanceList = true" @open-question-list="handleOpenQuestionList" />
+    <ControlTab
+      @open-surveillance-list="showSurveillanceList = true"
+      @open-workshop-list="showWorkshopList = true"
+      @open-question-list="handleOpenQuestionList"
+    />
     <SurveillanceList v-if="showSurveillanceList" @close="showSurveillanceList = false" />
+    <WorkshopList v-if="showWorkshopList" @close="showWorkshopList = false" />
 
     <QuestionList v-if="showQuestionList" @close="handleQuestionListClose" />
   </div>
@@ -13,8 +18,10 @@
 <script setup lang="ts">
   import CompanyRating from './components/CompanyRating.vue';
   import ControlTab from './components/ControlTab.vue';
-  import SurveillanceList from './components/SurveillanceList.vue';
   import RealtimeSurveillance from './components/RealtimeSurveillance.vue';
+  import SurveillanceList from './components/SurveillanceList.vue';
+  import WorkshopList from './components/WorkshopList.vue';
+
   import QuestionList from '../safety-question-list/QuestionList.vue';
 
   import useQuestionListStore from '@/views/institute-safety/modules/safety-company-home/stores/use-question-list';
@@ -23,9 +30,10 @@
   import useCameraStore from './stores/use-camera-store';
   import { nextTick, onUnmounted, ref } from 'vue';
   import { storeToRefs } from 'pinia';
-  import { WORKSHOP_INFOS } from '../safety-workshop-list/constants';
+  import { WORKSHOP_INFOS } from './constants';
 
   const showSurveillanceList = ref(false);
+  const showWorkshopList = ref(false);
 
   useViolationNoticeCompany();
 
@@ -51,6 +59,7 @@
       questionListStore.openList();
     });
   }
+
   function handleQuestionListClose() {
     questionListStore.closeList();
   }

+ 30 - 0
src/views/institute-safety/modules/safety-company-home/apis/index.ts

@@ -43,3 +43,33 @@ export function updateReadIssueId(issueId: number) {
     method: 'post',
   });
 }
+
+// 查询车间今日是否有异常状态
+export function getWorkshopTodayExceptionStatus(list: string[]) {
+  return http.request<
+    {
+      workshopCode: string;
+      exceptionStatus: boolean;
+    }[]
+  >({
+    url: '/issue/queryWorkshopTodayExceptionStatus',
+    method: 'post',
+    data: {
+      workshopCodeList: list,
+    },
+  });
+}
+
+export function getPaprogandaData() {
+  return http.request<
+    {
+      id: number;
+      imageUrls: string | null;
+      materialName: string;
+      createdAt: string;
+    }[]
+  >({
+    url: '/safetypublicitybulletinboard/field_external',
+    method: 'get',
+  });
+}

+ 5 - 0
src/views/institute-safety/modules/safety-company-home/components/ControlTab.vue

@@ -17,6 +17,10 @@
         <img src="@/assets/images/institute-safety/alert-white.png" alt="" />
         <div class="tab-text">今日异常告警</div>
       </div>
+      <div class="tab-button" @click="emit('open-workshop-list')">
+        <img src="@/assets/images/institute-safety/workshop-list.png" alt="" />
+        <div class="tab-text">监控区域列表</div>
+      </div>
     </div>
   </div>
 </template>
@@ -26,6 +30,7 @@
 
   const emit = defineEmits<{
     (e: 'open-surveillance-list'): void;
+    (e: 'open-workshop-list'): void;
     (e: 'open-question-list'): void;
   }>();
 

+ 150 - 0
src/views/institute-safety/modules/safety-company-home/components/WorkshopList.vue

@@ -0,0 +1,150 @@
+<template>
+  <div class="workshop-list">
+    <header class="list-header">
+      <div style="width: 16px"></div>
+      <span> 监控区域列表 </span>
+      <img class="close-btn" src="@/assets/images/institute-safety/close.png" alt="" @click="emits('close')" />
+    </header>
+    <main class="workshop-list-main">
+      <div class="workshop-item" v-for="item in staticWorkshopList" :key="item.id">
+        <span class="item-id">{{ item.id }}</span>
+
+        <el-tooltip placement="top" :content="item.name" :hide-after="0">
+          <span class="item-name"> {{ item.name }} </span>
+        </el-tooltip>
+        <img
+          class="item-icon"
+          v-if="item.status"
+          src="@/assets/images/institute-safety/alert.png"
+          alt=""
+          @click="handleOpenQuestionList(item.workshopCode)"
+        />
+      </div>
+    </main>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { nextTick, onMounted, ref } from 'vue';
+  import { ElTooltip } from 'element-plus';
+  import { getWorkshopTodayExceptionStatus } from '../apis';
+  import { WORKSHOP_INFOS } from '../constants';
+
+  import useQuestionListStore from '@/views/institute-safety/modules/safety-company-home/stores/use-question-list';
+
+  const emits = defineEmits<{
+    (e: 'close'): void;
+  }>();
+
+  const questionListStore = useQuestionListStore();
+
+  const staticWorkshopList = ref(WORKSHOP_INFOS);
+
+  function handleOpenQuestionList(code: string) {
+    questionListStore.closeList();
+    questionListStore.clearStore();
+    nextTick(() => {
+      questionListStore.setState({
+        type: 'workshop',
+        workshopCodes: [code],
+      });
+      questionListStore.openList();
+    });
+  }
+
+  onMounted(() => {
+    getWorkshopTodayExceptionStatus(staticWorkshopList.value.map((item) => item.workshopCode)).then((res) => {
+      staticWorkshopList.value.forEach((item) => {
+        item.status = res.find((x) => x.workshopCode === item.workshopCode)!.exceptionStatus;
+      });
+    });
+  });
+</script>
+
+<style scoped>
+  .workshop-list {
+    width: 280px;
+    height: 675px;
+
+    position: absolute;
+    top: 0px;
+    right: 0px;
+
+    background: rgba(0, 0, 0, 0.5);
+    border-radius: 12px 4px 4px 12px;
+    backdrop-filter: blur(10px);
+  }
+
+  .list-header {
+    margin: 12px 0;
+    padding: 0 16px;
+
+    font-weight: 500;
+    font-size: 14px;
+    color: #ffffff;
+
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+  .config-btn,
+  .close-btn {
+    cursor: pointer;
+  }
+  .workshop-list-main {
+    padding: 0 16px;
+    height: 623px;
+    overflow: auto;
+  }
+
+  .workshop-item {
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+    margin-top: 20px;
+  }
+  .item-id {
+    font-family: DIN, DIN;
+    font-weight: bold;
+    font-size: 13px;
+    color: #ffffff;
+    width: 20px;
+    height: 20px;
+    background: rgba(0, 0, 0, 0.4);
+    border-radius: 50%;
+    text-align: center;
+  }
+
+  .item-name {
+    margin-left: 8px;
+    max-width: 183px;
+    height: 28px;
+    line-height: 28px;
+    border-radius: 4px;
+
+    padding: 0 10px;
+
+    white-space: nowrap; /* 防止文本换行 */
+    overflow: hidden; /* 隐藏溢出的文本 */
+    text-overflow: ellipsis; /* 显示省略号 */
+
+    font-weight: 400;
+    font-size: 14px;
+    color: #ffffff;
+  }
+
+  .item-icon {
+    margin-right: 8px;
+    margin-left: auto;
+    cursor: pointer;
+    width: 20px;
+    height: 20px;
+  }
+
+  .camera-name-text {
+    max-width: 200px;
+    white-space: nowrap; /* 防止文本换行 */
+    overflow: hidden; /* 隐藏溢出的文本 */
+    text-overflow: ellipsis; /* 显示省略号 */
+  }
+</style>

src/views/institute-safety/modules/safety-workshop-list/constants.ts → src/views/institute-safety/modules/safety-company-home/constants.ts


+ 1 - 2
src/views/institute-safety/modules/safety-company-home/hooks/use-violation-notice-company.ts

@@ -1,12 +1,11 @@
 // 报警消息实时提醒
-
 import { getNewIssueList, updateReadIssueId } from '../apis';
 import useViolationNoticeStore, { getPlace, emitter } from '../stores/use-violation-notice-store';
 import { onUnmounted, onMounted, nextTick } from 'vue';
 import dayjs from 'dayjs';
 import { push } from 'notivue';
 import useQuestionListStore from '@/views/institute-safety/modules/safety-company-home/stores/use-question-list';
-import { WORKSHOP_INFOS } from '../../safety-workshop-list/constants';
+import { WORKSHOP_INFOS } from '../constants';
 
 const questionListStore = useQuestionListStore();
 const useViolationRealtimeCompany = () => {

+ 118 - 0
src/views/institute-safety/modules/safety-propaganda/SafetyPropaganda.vue

@@ -0,0 +1,118 @@
+<template>
+  <div class="safety-propaganda-container">
+    <div class="title">
+      <span class="line"></span>
+      <span class="text">安全宣传栏</span>
+    </div>
+    <div class="safety-propaganda">
+      <div
+        class="item"
+        v-for="item in data"
+        :key="item.id"
+        @click="
+          router.push({
+            name: 'safetyPublicityBoardManagementItem',
+            query: { id: item.id, operate: 'safety-publicity-board-view' },
+          })
+        "
+      >
+        <img v-if="item.imageUrls[0]?.url" class="propaganda-img" :src="item.imageUrls[0].url" alt="" />
+        <img v-else class="propaganda-img" src="@/assets/images/institute-safety/default-propaganda.jpeg" alt="" />
+        <div class="category-name">{{ item.materialName }}</div>
+        <div class="propaganda-time">{{ item.createdAt }}</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { ref, onMounted } from 'vue';
+  import { useRouter } from 'vue-router';
+  import { getPaprogandaData } from '../safety-company-home/apis';
+
+  const router = useRouter();
+  const data = ref();
+
+  onMounted(() => {
+    getPaprogandaData().then((res) => {
+      data.value = res || [];
+      data.value.forEach((item) => {
+        item.imageUrls = JSON.parse(item.imageUrls || '[]');
+      });
+    });
+  });
+</script>
+
+<style scoped>
+  .safety-propaganda-container {
+    font-family: PingFangSC, PingFang SC;
+
+    margin-top: 20px;
+  }
+
+  .safety-propaganda {
+    display: grid;
+    grid-template-columns: repeat(5, 1fr);
+    gap: 12px;
+  }
+  .item {
+    /* width: 228px; */
+    height: 224px;
+    background: #f0f2f6;
+    border-radius: 8px;
+    cursor: pointer;
+  }
+  .propaganda-img {
+    width: 100%;
+    height: 140px;
+    object-fit: cover;
+    border-radius: 8px 8px 0 0;
+  }
+  .category-name {
+    margin-left: 12px;
+    margin-top: 10px;
+    font-weight: 500;
+    font-size: 14px;
+    color: #333333;
+
+    /* 设置最大宽度(你可以随意改) */
+    max-width: 204px;
+    height: 40px;
+
+    /* 核心:多行文本溢出省略 */
+    display: -webkit-box;
+    -webkit-line-clamp: 2; /* 最多显示 2 行 */
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
+
+    /* 可选:文字换行 */
+    word-break: break-all;
+  }
+  .propaganda-time {
+    margin-left: 12px;
+    margin-top: 5px;
+    font-weight: 400;
+    font-size: 12px;
+    color: #999999;
+  }
+
+  .title {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    margin-bottom: 16px;
+  }
+  .line {
+    width: 3px;
+    height: 16px;
+    background: #1777ff;
+  }
+
+  .text {
+    font-weight: 500;
+    font-size: 16px;
+    color: #000000;
+    line-height: 22px;
+  }
+</style>

+ 0 - 105
src/views/institute-safety/modules/safety-workshop-list/WorkshopList.vue

@@ -1,105 +0,0 @@
-<template>
-  <div class="workshop-list">
-    <div class="workshop-list-item" v-for="item in staticWorkshopList" :key="item.id">
-      <div class="workshop-list-item-id">{{ item.id }}</div>
-      <el-tooltip placement="top" :content="item.name">
-        <div class="workshop-list-item-name">{{ item.name }}</div>
-      </el-tooltip>
-      <img
-        class="workshop-list-item-icon"
-        v-if="item.status"
-        src="@/assets/images/institute-safety/alert.png"
-        alt=""
-        @click="handleOpenQuestionList(item.workshopCode)"
-      />
-    </div>
-  </div>
-</template>
-
-<script setup lang="ts">
-  import { nextTick, onMounted, ref } from 'vue';
-  import { ElTooltip } from 'element-plus';
-  import { getWorkshopTodayExceptionStatus } from './apis';
-  import { WORKSHOP_INFOS } from './constants';
-
-  import useQuestionListStore from '@/views/institute-safety/modules/safety-company-home/stores/use-question-list';
-  // import { storeToRefs } from 'pinia';
-
-  const questionListStore = useQuestionListStore();
-  // const { showQuestionList } = storeToRefs(questionListStore);
-
-  const staticWorkshopList = ref(WORKSHOP_INFOS);
-
-  function handleOpenQuestionList(code: string) {
-    questionListStore.closeList();
-    questionListStore.clearStore();
-    nextTick(() => {
-      questionListStore.setState({
-        type: 'workshop',
-        workshopCodes: [code],
-      });
-      questionListStore.openList();
-    });
-  }
-
-  onMounted(() => {
-    getWorkshopTodayExceptionStatus(staticWorkshopList.value.map((item) => item.workshopCode)).then((res) => {
-      staticWorkshopList.value.forEach((item) => {
-        item.status = res.find((x) => x.workshopCode === item.workshopCode)!.exceptionStatus;
-      });
-    });
-  });
-</script>
-
-<style scoped>
-  .workshop-list {
-    margin-top: 8px;
-    display: grid;
-    grid-template-columns: repeat(auto-fill, 200px);
-  }
-  .workshop-list-item {
-    display: flex;
-    flex-direction: row;
-    align-items: center;
-    justify-content: flex-start;
-    width: 200px;
-    height: 40px;
-    border: 1px solid #e8e8e8;
-  }
-  .workshop-list-item:nth-child(n + 12) {
-    border: 1px solid rgba(232, 232, 232, 0.6);
-  }
-  .workshop-list-item:nth-child(n + 30) {
-    border: 1px solid rgba(232, 232, 232, 0.3);
-  }
-
-  .workshop-list-item-id {
-    margin: 0 10px;
-    width: 20px;
-    height: 20px;
-    border-radius: 50%;
-    background: #e8e8e8;
-    font-size: 13px;
-    color: #666666;
-    font-weight: bold;
-    font-family: DINAlternate;
-    text-align: center;
-    line-height: 20px;
-  }
-
-  .workshop-list-item-name {
-    width: 126px;
-    font-weight: 400;
-    font-size: 14px;
-    color: #666666;
-    white-space: nowrap;
-    overflow: hidden;
-    text-overflow: ellipsis;
-  }
-  .workshop-list-item-icon {
-    cursor: pointer;
-    margin: 0 8px 0 10px;
-    width: 20px;
-    height: 20px;
-  }
-</style>

+ 0 - 17
src/views/institute-safety/modules/safety-workshop-list/apis/index.ts

@@ -1,17 +0,0 @@
-import { http } from '@/utils/http/axios';
-
-// 查询车间今日是否有异常状态
-export function getWorkshopTodayExceptionStatus(list: string[]) {
-  return http.request<
-    {
-      workshopCode: string;
-      exceptionStatus: boolean;
-    }[]
-  >({
-    url: '/issue/queryWorkshopTodayExceptionStatus',
-    method: 'post',
-    data: {
-      workshopCodeList: list,
-    },
-  });
-}

+ 117 - 14
src/views/production-safety/safety-culture/safetyPublicityBoardManagement/components/safetyPublicityBoardManagementDetail.vue

@@ -30,20 +30,11 @@
                 <el-button link type="primary" @click="previewOnline(file.fileUrl, file.fileType)"
                   >预览</el-button
                 >
-                <!-- <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
-                  >下载</el-button
-                > -->
+                <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
+                  >下载</el-button>
               </div>
             </div>
           </div>
-        <!-- <UploadFiles
-          label="上传文件"
-          :maxCount="1"
-          :file-list="ruleFormData.attachmentUrl"
-          :disabled="isViewMode"
-          :allow-all-file-types="true"
-          @upload-success="handleUploadSuccess"
-        /> -->
       </template>
       <template #content>
         <div class="editor-container">
@@ -58,6 +49,31 @@
           />
         </div>
       </template>
+      <template #imageUrls>
+        <el-upload
+            class="image-uploader"
+            ref="courseImgRef"
+            action="#"
+            :file-list="imageList"
+            :disabled="isViewMode"
+            :auto-upload="false"
+            accept="image/*"
+            :on-change="handleImageUploadChange"
+            :on-remove="handlePictureCardDelete"
+            :on-preview="handlePictureCardPreview"
+            :before-upload="validateImage"
+            list-type="picture-card">
+                <el-icon>
+                    <Plus />
+                </el-icon>
+            <template #tip>
+              <div class="el-upload__tip"> 支持格式:.jpg .png .jpeg,单个文件不能超过300k</div>
+            </template>
+          </el-upload>
+          <el-dialog v-model="dialogVisible">
+            <img w-full :src="dialogImageUrl" alt="Preview Image" style="width: 100%;" />
+          </el-dialog>
+      </template>
     </BasicForm>
     <PreviewOnline ref="previewOnlineRef" />
   </main>
@@ -73,6 +89,7 @@
   import { computed, onMounted, ref, shallowRef, onBeforeUnmount } from 'vue';
   import { useRoute, useRouter } from 'vue-router';
   import { ElMessage } from 'element-plus';
+  import {Plus} from "@element-plus/icons-vue";
   import BasicForm from '@/components/BasicForm.vue';
   import UploadFiles from '@/components/UploadFiles/UploadFiles.vue';
   import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
@@ -87,7 +104,9 @@
   import type { FileItem } from '@/components/UploadFiles/types';
   import { formatAttachmentList } from '@/components/UploadFiles/utils';
   import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
-
+  import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
+  import { downloadFile } from '@/views/disaster/utils';
+  
   const router = useRouter();
   const route = useRoute();
 
@@ -124,7 +143,7 @@
   });
 
   const basicFormRef = ref<InstanceType<typeof BasicForm>>();
-
+  const imageList = ref<FileItem[]>([]);
   // 富文本编辑器
   const editorRef = shallowRef();
   const editorConfig = computed(() => ({
@@ -146,7 +165,6 @@
   const handleUploadSuccess = (files: FileItem[]) => {
     ruleFormData.attachmentUrl = files;
   };
-
   const parseAttachmentUrls = (attachmentUrl?: string): string[] => {
     if (!attachmentUrl || !attachmentUrl.trim()) {
       return [];
@@ -171,6 +189,88 @@
       .filter((url) => url);
   };
 
+   // 上传文件
+ const formatAttachment = async (data: any) => {
+    if (!data) return data;
+    const uuid = Math.random().toString(36).substring(2, 9);
+    const timestamp = Date.now().toString();
+    const random = Math.random().toString(36).substring(2, 4);
+    const fileName = data.name;
+    const res = await uploadFileApi({
+        bizType: UPLOAD_BIZ_TYPE.ATTACHMENT,
+        fileName: `${uuid}-${timestamp}-${random}`,
+        file: data,
+    });
+    return res;
+};
+  //  上传图片
+  const handleImageUploadChange = async (file: any, fileLists: any) => {
+    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
+            }
+            imageList.value = fileLists; 
+            ruleFormData.imageUrls = JSON.stringify(fileLists);
+            ElMessage.success('上传成功');
+        } catch (error) {
+            ElMessage.error('上传失败,请重试');
+            // 上传失败时,可以从 fileLists 中移除该文件
+            imageList.value = fileLists.filter(f => f.uid !== file.uid);
+        }
+    }
+  };
+  // 删除图片
+  const handlePictureCardDelete = (file, fileLists)=>{
+    imageList.value = fileLists.filter(f => f.uid !== file.uid);
+    ruleFormData.imageUrls = JSON.stringify(imageList.value);
+  }
+// 图片预览
+  const dialogVisible = ref(false);
+  const dialogImageUrl = ref('');
+  const handlePictureCardPreview = (file: any) => {
+    dialogImageUrl.value = file.url;
+    dialogVisible.value = true;
+  };
+
+// 图片格式校验
+  const validateImage = (file) => {
+    const validMIME = [
+      'image/jpeg',
+      'image/png',
+      'image/gif',
+      'image/bmp',
+      'image/webp',
+      'image/svg+xml',
+      'image/tiff',
+      'image/heic',
+      'image/heif',
+      'image/avif',
+    ];
+
+    if (!validMIME.includes(file.type)) {
+      ElMessage.error('仅支持图片文件(JPEG/PNG/GIF/BMP/WEBP/SVG/TIFF/HEIC/AVIF等)');
+      return false;
+    }
+
+    if (!validMIME.includes(file.type)) {
+      ElMessage.error('仅支持JPG/PNG格式图片');
+      return false; // 阻止上传
+    }
+
+    // 可选:添加文件大小限制
+    const maxSize = 1 * 1024 * 1024; // 4MB
+    if (file.size > maxSize) {
+      ElMessage.error('图片大小不能超过1MB');
+      return false;
+    }
+
+    return true; // 验证通过
+  };
   // 将逗号分隔的URL字符串转换为FileItem数组
   const convertFileUrlToFileItems = (fileUrl: string): FileItem[] => {
     if (!fileUrl || !fileUrl.trim()) {
@@ -222,6 +322,8 @@
         ruleFormData.description = res.description || '';
         ruleFormData.attachmentUrl = JSON.parse(res.attachmentUrl || res.fileUrl || '');
         ruleFormData.status = res.status ?? 1;
+        ruleFormData.imageUrls = JSON.parse(res.imageUrls || '');
+        imageList.value = JSON.parse(res.imageUrls || '') || [];
       }
       cloneRuleFormData();
     } catch (e) {
@@ -252,6 +354,7 @@
         categoryName: ruleFormData.categoryName,
         description: ruleFormData.description,
         attachmentUrl: JSON.stringify(uploadedFileList),
+        imageUrls: ruleFormData.imageUrls
       };
       if (isCreateMode.value) {
         await saveSafetyPublicityBoardPage(basePayload);

+ 10 - 0
src/views/production-safety/safety-culture/safetyPublicityBoardManagement/configs/form.ts

@@ -37,6 +37,15 @@ export const ACADEMY_FILE_FORM_CONFIG: FormConfig[] = [
       style:'width:45%',
     },
   },
+  // 状态为什么要去掉,肯定是当成bug修复去掉了,不要质疑
+  {
+    prop: 'imageUrls',
+    label: '图片上传:',
+    slot: 'imageUrls',
+    componentProps: {
+      style:'width:45%',
+    },
+  },
 ];
 
 export const ACADEMY_FILE_FORM_DATA = {
@@ -46,6 +55,7 @@ export const ACADEMY_FILE_FORM_DATA = {
   fileFormat: '',
   status: 1,
   attachmentUrl: [] as FileItem[],
+  imageUrls:'',
 };
 
 export const ACADEMY_FILE_FORM_RULES = {

+ 1 - 0
src/views/production-safety/safety-culture/safetyPublicityBoardManagement/configs/tables.ts

@@ -33,6 +33,7 @@ export const INVENTORY_TABLE_COLUMNS: TableColumnProps[] = [
     prop: 'categoryName',
     align: 'left',
     minWidth: '120px',
+    showOverflowTooltip: true,
   },
   // {
   //   label: '资料描述',

+ 4 - 0
src/views/security-confidentiality/confidentiality-regulation-notice/components/NoticeTable.vue

@@ -84,6 +84,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 1,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />
@@ -102,6 +104,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 0,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />

+ 4 - 0
src/views/security-confidentiality/confidentiality-regulation-notice/components/RegulationTable.vue

@@ -78,6 +78,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 1,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />
@@ -95,6 +97,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 0,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />

+ 4 - 0
src/views/security-confidentiality/security-regulation-notice/components/NoticeTable.vue

@@ -84,6 +84,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 1,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />
@@ -102,6 +104,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 0,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />

+ 4 - 0
src/views/security-confidentiality/security-regulation-notice/components/RegulationTable.vue

@@ -78,6 +78,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 1,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />
@@ -95,6 +97,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 0,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />

+ 4 - 0
src/views/traffic/regulation/components/NoticeTable.vue

@@ -83,6 +83,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 1,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />
@@ -101,6 +103,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 0,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />

+ 4 - 0
src/views/traffic/regulation/components/RegulationTable.vue

@@ -77,6 +77,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 1,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />
@@ -94,6 +96,8 @@
                 attachment: scope.row.attachment,
                 isPush: scope.row.isPush,
                 effectState: 0,
+                remark: scope.row.remark,
+                userGroupList: scope.row.userGroupList,
               })
             "
           />