Sfoglia il codice sorgente

Merge branch 'cc-dev' into 'dev'

完成灾害处置 需要重构代码

See merge request product-group-fe/sfy-safety-group/sfy-safety!83
陈昶 10 mesi fa
parent
commit
c6feacfae9

+ 12 - 1
src/types/disaster-control/index.ts

@@ -243,7 +243,18 @@ export interface ReportTaskListDetail {
   lossRecordList: LossRecordListDetail[]; // 损失记录列表
 }
 
-export interface DisasterLossDetailResponse {
+export interface OverviewLossRecordInfo {
+  needToReportDeptCount?: number; // 需上报单位数量
+  reportedDeptCount?: number; // 已上报单位数量
+  waitToReportDeptCount?: number; // 待上报单位数量
+  overdueReportedDeptCount?: number; // 超期未上报单位数量
+  lossRecordCount?: number; // 损失记录数量
+  fixedLossCount?: number; // 已整改损失数量
+  fixingLossCount?: number; //	整改中损失数量
+  waitToFixLossCount?: number; // 待整改损失数量
+}
+
+export interface DisasterLossDetailResponse extends OverviewLossRecordInfo {
   handleTaskName: string;
   reportTaskList: ReportTaskListDetail[]; // 上报任务列表
 }

+ 34 - 5
src/views/disaster/disaster-control/PageDisposalManagement.vue

@@ -64,7 +64,10 @@
                         'collapse-item__icon',
                         { 'collapse-item__icon--disabled': !isViewTask(item.tableData[0].disasterReportTaskInfoList) },
                       ]"
-                      @click.stop="isViewTask(item.tableData[0].disasterReportTaskInfoList) && handleViewTask(item.id)"
+                      @click.stop="
+                        isViewTask(item.tableData[0].disasterReportTaskInfoList) &&
+                          handleViewTask(item.id, item.taskName)
+                      "
                     />
                   </el-tooltip>
                 </template>
@@ -152,7 +155,11 @@
                             @confirm="handleDeleteReportTask(scope.row.id)"
                             v-if="disposalManagementPermissions && scope.row.status === ACTIVE_STATUS.NOT_EFFECTIVE"
                           />
-                          <ActionButton text="查看" v-if="scope.row.status === ACTIVE_STATUS.ACTIVE" />
+                          <ActionButton
+                            text="查看"
+                            v-if="scope.row.status === ACTIVE_STATUS.ACTIVE"
+                            @click="handleViewItem(item.id, scope.row.deptId, item.taskName)"
+                          />
                         </div>
                       </template>
                     </BasicTable>
@@ -385,17 +392,39 @@
   };
 
   const isBatchWithdraw = (disasterReportTaskInfoList: disasterReportTaskInfoListResponse[]) => {
-    return disasterReportTaskInfoList.some((item) => item.status === ACTIVE_STATUS.ACTIVE);
+    return (
+      disasterReportTaskInfoList.some(
+        (item) => item.taskStage === TASK_STAGE.TO_BE_REPORTED || item.taskStage === TASK_STAGE.OVERDUE,
+      ) && disasterReportTaskInfoList.some((item) => item.status === ACTIVE_STATUS.ACTIVE)
+    );
   };
 
   const isBatchDelete = (disasterReportTaskInfoList: disasterReportTaskInfoListResponse[]) => {
     return disasterReportTaskInfoList.every((item) => item.status === ACTIVE_STATUS.NOT_EFFECTIVE);
   };
 
-  const handleViewTask = (id: number) => {
-    console.log('查看任务ID' + id);
+  const handleViewTask = (id: number, taskName: string) => {
+    router.push({
+      name: Task_RouterName,
+      query: {
+        id,
+        taskName,
+      },
+    });
   };
 
+  const handleViewItem = (id: number, deptId: number, taskName: string) => {
+    router.push({
+      name: Table_RouterName,
+      params: {
+        id,
+      },
+      query: {
+        deptId,
+        taskName,
+      },
+    });
+  };
   const handleBatchRelease = async (id: number) => {
     const confirmed = await openMessageBox('', '确定发布吗?', 'warning');
     if (!confirmed) return;

+ 15 - 0
src/views/disaster/disaster-control/PageDisposalManagementItem.vue

@@ -4,6 +4,7 @@
       <img :src="BackIcon" alt="back" class="back-icon" @click="router.back()" />
       <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
     </header>
+    <TaskInfoSection :task-name="taskName" @export-loss-detail="exportLossDetail" v-if="!operate" />
     <main class="disaster-precaution-container__main">
       <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
     </main>
@@ -20,6 +21,8 @@
   import { ref, computed, defineAsyncComponent } from 'vue';
   import { ElMessage } from 'element-plus';
   import UploadLoading from '@/components/UploadLoading.vue';
+  import TaskInfoSection from './src/components/TaskInfoSection.vue';
+  import { exportLossRecord } from '@/views/disaster/disaster-control/src/util';
   import type { DisposalManagementCreateQuery, DisasterReportEditQuery } from '@/types/disaster-control';
   import { createDisasterReportTask, editDisasterReportTask } from '@/api/disaster-control';
   import BackIcon from 'assets/svg/back.svg';
@@ -28,6 +31,7 @@
   const route = useRoute();
   const operate = route.query.operate;
   const id = Number(route.params.id);
+  const taskName = String(route.query.taskName);
   const reportTaskId = Number(route.query.reportTaskId);
   const headerTitle = computed(() => {
     const fixedTitle = '灾害处置任务';
@@ -77,6 +81,17 @@
       formLoading.value = false;
     }
   };
+  const exportLossDetail = async () => {
+    const { id: lossRecordId, name: lossRecordName } = dynamicComponentRef.value?.getLossRecordListInfo();
+    await exportLossRecord(
+      {
+        handleTaskId: id,
+        reportRecordId: lossRecordId,
+      },
+      lossRecordName,
+    );
+    ElMessage.success(`导出${lossRecordName}损失明细成功`);
+  };
 </script>
 
 <style lang="scss" scoped>

+ 26 - 3
src/views/disaster/disaster-control/PageDisposalManagementTaskItem.vue

@@ -4,8 +4,19 @@
       <img :src="BackIcon" alt="back" class="back-icon" @click="router.back()" />
       <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
     </header>
+    <TaskInfoSection
+      :task-name="taskName"
+      :overview-loss-record-info="overviewInfo"
+      @export-loss-detail="exportLossDetail"
+      v-if="!operate"
+    />
     <main class="disaster-precaution-container__main">
-      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+      <component
+        :is="dynamicComponent"
+        :id="id"
+        ref="dynamicComponentRef"
+        @overviewLossRecordInfo="getOverviewLossRecordInfo"
+      />
     </main>
     <footer class="disaster-precaution-container__footer" v-if="operate">
       <el-button @click="router.back()">取消</el-button>
@@ -20,13 +31,18 @@
   import { ref, computed, defineAsyncComponent } from 'vue';
   import { ElMessage } from 'element-plus';
   import UploadLoading from '@/components/UploadLoading.vue';
+  import { exportLossRecord } from '@/views/disaster/disaster-control/src/util';
+  import TaskInfoSection from '@/views/disaster/disaster-control/src/components/TaskInfoSection.vue';
+  import { OverviewLossRecordInfo } from '@/types/disaster-control';
   import { createDisasterHandleTask } from '@/api/disaster-control';
   import BackIcon from 'assets/svg/back.svg';
 
   const router = useRouter();
   const route = useRoute();
   const operate = route.query.operate;
-  const id = route.query.id;
+  const id = Number(route.query.id);
+  const taskName = String(route.query.taskName);
+  const overviewInfo = ref<OverviewLossRecordInfo>();
   const headerTitle = computed(() => {
     const fixedTitle = '灾害处置任务';
     if (operate === 'create') {
@@ -38,7 +54,7 @@
     if (operate === 'create') {
       return defineAsyncComponent(() => import('./src/components/CreateDisposalManagementTaskItem.vue'));
     } else {
-      return defineAsyncComponent(() => import('./src/components/ViewDisposalControlItem.vue'));
+      return defineAsyncComponent(() => import('./src/components/ViewDisposalControlTaskItem.vue'));
     }
   });
   const dynamicComponentRef = ref();
@@ -57,6 +73,13 @@
       formLoading.value = false;
     }
   };
+  const getOverviewLossRecordInfo = (overviewLossRecordInfo: OverviewLossRecordInfo) => {
+    overviewInfo.value = overviewLossRecordInfo;
+  };
+  const exportLossDetail = async () => {
+    await exportLossRecord({ handleTaskId: id }, taskName);
+    ElMessage.success(`导出${taskName}损失明细成功`);
+  };
 </script>
 
 <style lang="scss" scoped>

+ 1 - 1
src/views/disaster/disaster-control/PageDisposalRectification.vue

@@ -318,7 +318,7 @@
   ) => {
     const rectificationIds = detailList
       .filter((item) => item.fixStatus === FIX_STATUS.TO_BE_RECTIFIED)
-      .map((item) => item.id);
+      .map((item) => ({ id: item.id, fixTaskId: item.fixTaskId }));
     sessionStorage.setItem('rectificationIds', JSON.stringify(rectificationIds));
     router.push({
       name: defaultRouterName,

+ 22 - 9
src/views/disaster/disaster-control/PageDisposalRectificationItem.vue

@@ -53,6 +53,11 @@
     DISPOSAL_RECTIFICATION_FORM_RULES,
   } from './src/config';
 
+  interface RectificationIds {
+    id: number;
+    fixTaskId: number;
+  }
+
   const basicFormRef = ref<InstanceType<typeof BasicForm>>();
   const uploadImagesRef = ref<InstanceType<typeof UploadImages>>();
   const uploadFilesRef = ref<InstanceType<typeof UploadFiles>>();
@@ -64,7 +69,9 @@
   const route = useRoute();
   const id = ref<number>(Number(route.params.id));
   const handleTaskId = Number(route.query.handleTaskId);
-  const fixTaskId = Number(route.query.fixTaskId);
+  const fixTaskId = computed(() => {
+    return Number(route.query.fixTaskId);
+  });
   const formLoading = ref(false);
   const { ruleFormConfig, ruleFormData, formRules, cloneRuleFormData, beforeRouteLeave } =
     useFormConfigHook<DisposalRectificationFormData>(
@@ -72,9 +79,10 @@
       DISPOSAL_RECTIFICATION_FORM_DATA,
       DISPOSAL_RECTIFICATION_FORM_RULES,
     );
-  const rectificationIds = ref<number[]>([]);
+  const rectificationIds = ref<RectificationIds[]>([]);
   const isShowNextSubmit = computed(() => {
-    return rectificationIds.value.length > 1 && rectificationIds.value.includes(id.value);
+    const reportTaskIds = rectificationIds.value.map((item) => item.id);
+    return rectificationIds.value.length > 1 && reportTaskIds.includes(id.value);
   });
   const handleUploadImageSuccess = (files: File[]) => {
     ruleFormData.uploadImages = files;
@@ -116,7 +124,7 @@
     ruleFormData.fixImages = imagesListString;
     ruleFormData.fixMaterials = fileListString;
     await createDisposalRectification({
-      fixTaskId,
+      fixTaskId: fixTaskId.value,
       ...ruleFormData,
     });
     ElMessage.success('提交成功');
@@ -139,26 +147,31 @@
     if (!basicFormRef.value) return;
     const validateResult = await basicFormRef.value.validateForm();
     if (!validateResult) return;
+    formLoading.value = true;
     try {
       await submitDisposalRectification();
     } finally {
       formLoading.value = false;
     }
+    const reportTaskIds = rectificationIds.value.map((item) => item.id);
     // 查找当前id在数组中的索引
-    const currentIndex = rectificationIds.value.indexOf(id.value);
+    const currentIndex = reportTaskIds.indexOf(id.value);
 
     if (currentIndex !== -1) {
       // 从数组中移除当前id
       rectificationIds.value.splice(currentIndex, 1);
 
-      // 确定下一个要处理的id
+      // 确定下一个要处理的id和fixTaskId
       let nextId;
+      let nextFixTaskId;
       if (currentIndex < rectificationIds.value.length) {
         // 如果不是最后一个元素,取当前索引位置的元素(移除当前id后,下一个id会自动前移)
-        nextId = rectificationIds.value[currentIndex];
+        nextId = rectificationIds.value[currentIndex].id;
+        nextFixTaskId = rectificationIds.value[currentIndex].fixTaskId;
       } else {
         // 如果是最后一个元素,取第一个元素
-        nextId = rectificationIds.value[0];
+        nextId = rectificationIds.value[0].id;
+        nextFixTaskId = rectificationIds.value[0].fixTaskId;
       }
 
       // 保存更新后的数组到sessionStorage
@@ -170,7 +183,7 @@
         },
         query: {
           handleTaskId,
-          fixTaskId,
+          fixTaskId: nextFixTaskId,
         },
       });
     }

+ 2 - 2
src/views/disaster/disaster-control/PageViewDisposalRectification.vue

@@ -10,7 +10,7 @@
         <CollapseItem
           v-for="reportTask in disasterLossDetailList?.reportTaskList"
           :key="reportTask.reportDeptId"
-          :name="reportTask.reportDeptName"
+          :name="`上报单位:${reportTask.reportDeptName}`"
           :isActive="activeId === reportTask.reportDeptId"
           @toggle="handleCollapseToggle(reportTask.reportDeptId)"
         >
@@ -22,7 +22,7 @@
           </template>
           <template #right-header>
             <span class="collapse-item__header--right">
-              {{ activeId === reportTask.reportTaskId ? '收起' : '立即查看' }}
+              {{ activeId === reportTask.reportDeptId ? '收起' : '展开' }}
             </span>
           </template>
           <template #main-table>

+ 121 - 1
src/views/disaster/disaster-control/src/components/TaskInfoSection.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="disaster-precaution-container__header">
+  <div class="task-info-container">
     <section class="task-info">
       <span class="disaster-precaution-container__title">{{ taskName }}</span>
       <el-button type="primary" @click="emit('exportLossDetail')">
@@ -9,13 +9,65 @@
         导出损失明细
       </el-button>
     </section>
+    <section class="overview-info" v-if="overviewLossRecordInfo">
+      <div class="overview-info__item">
+        <header class="overview-info__item-header">
+          <div class="overview-info__item-title">
+            <img :src="ReportIcon" />
+            <span>需上报单位数量</span>
+          </div>
+          <span>{{ overviewLossRecordInfo.needToReportDeptCount }}</span>
+        </header>
+        <main class="overview-info__item-main">
+          <div class="overview-info__item-main-item">
+            <span class="overview-info-title">已上报</span>
+            <span class="overview-info-value value--primary">{{ overviewLossRecordInfo.reportedDeptCount }}</span>
+          </div>
+          <div class="overview-info__item-main-item">
+            <span class="overview-info-title">待上报</span>
+            <span class="overview-info-value value--doing">{{ overviewLossRecordInfo.waitToReportDeptCount }}</span>
+          </div>
+          <div class="overview-info__item-main-item">
+            <span class="overview-info-title">超期未上报</span>
+            <span class="overview-info-value value--done">{{ overviewLossRecordInfo.overdueReportedDeptCount }}</span>
+          </div>
+        </main>
+      </div>
+      <div class="overview-info__item">
+        <header class="overview-info__item-header">
+          <div class="overview-info__item-title">
+            <img :src="LossIcon" />
+            <span>总灾害损失记录数量</span>
+          </div>
+          <span>{{ overviewLossRecordInfo.lossRecordCount }}</span>
+        </header>
+        <main class="overview-info__item-main">
+          <div class="overview-info__item-main-item">
+            <span class="overview-info-title">已整改</span>
+            <span class="overview-info-value value--primary">{{ overviewLossRecordInfo.fixedLossCount }}</span>
+          </div>
+          <div class="overview-info__item-main-item">
+            <span class="overview-info-title">整改中</span>
+            <span class="overview-info-value value--doing">{{ overviewLossRecordInfo.fixingLossCount }}</span>
+          </div>
+          <div class="overview-info__item-main-item">
+            <span class="overview-info-title">待整改</span>
+            <span class="overview-info-value value--done">{{ overviewLossRecordInfo.waitToFixLossCount }}</span>
+          </div>
+        </main>
+      </div>
+    </section>
   </div>
 </template>
 
 <script lang="ts" setup>
+  import { OverviewLossRecordInfo } from '@/types/disaster-control';
   import ExportIcon from 'assets/svg/export.svg';
+  import ReportIcon from '../svg/report.svg';
+  import LossIcon from '../svg/loss.svg';
   defineProps<{
     taskName?: string;
+    overviewLossRecordInfo?: OverviewLossRecordInfo;
   }>();
   const emit = defineEmits<{
     (e: 'exportLossDetail'): void;
@@ -24,9 +76,77 @@
 
 <style lang="scss" scoped>
   @use '@/views/disaster/style/disaster.scss' as *;
+  .task-info-container {
+    display: flex;
+    flex-direction: column;
+    gap: 16px;
+    justify-content: space-between;
+    padding: 16px 22px;
+    background-color: $white-color;
+    border-radius: 4px;
+  }
   .task-info {
     @include flex-center;
     justify-content: space-between;
     width: 100%;
   }
+  .overview-info {
+    display: flex;
+    gap: 80px;
+  }
+  .overview-info__item {
+    width: 283px;
+    height: 116px;
+    border-radius: 8px;
+    background-color: #f2f8ff;
+    &-header {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      width: 100%;
+      height: 36px;
+      padding: 8px 20px 8px 10px;
+      background-color: #409eff;
+      border-radius: 8px;
+      line-height: 36px;
+      font-size: 14px;
+      color: rgba(255, 255, 255, 0.85);
+    }
+    &-main {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      width: 100%;
+      height: calc(100% - 36px);
+      padding: 0 20px;
+      &-item {
+        display: flex;
+        flex-direction: column;
+      }
+    }
+    &-title {
+      display: flex;
+      align-items: center;
+      gap: 10px;
+    }
+  }
+  $doing-color: #ffaa00;
+  $done-color: #ff4d4f;
+  .value--primary {
+    color: $primary-color;
+  }
+  .value--doing {
+    color: $doing-color;
+  }
+  .value--done {
+    color: $done-color;
+  }
+  .overview-info-title {
+    font-size: 14px;
+    color: rgba(102, 102, 102, 0.85);
+  }
+  .overview-info-value {
+    font-size: 20px;
+    font-weight: 600;
+  }
 </style>

+ 117 - 3
src/views/disaster/disaster-control/src/components/ViewDisposalControlItem.vue

@@ -1,7 +1,121 @@
 <template>
-  <div> this is view disposal control item page </div>
+  <div class="info-container">
+    <CollapseItem
+      v-for="reportTask in disasterLossDetailList?.reportTaskList"
+      :key="reportTask.reportDeptId"
+      :name="`上报单位:${reportTask.reportDeptName}`"
+      :isActive="activeId === reportTask.reportDeptId"
+      @toggle="handleCollapseToggle(reportTask.reportDeptId)"
+    >
+      <template #view-operation>
+        <div class="rectification-info">
+          <span class="num">{{ reportTask.lossRecordCount }}</span>
+          <span>条,整改完成{{ reportTask.fixFinishCount }}条</span>
+        </div>
+      </template>
+      <template #right-header>
+        <span class="collapse-item__header--right">
+          {{ activeId === reportTask.reportDeptId ? '收起' : '展开' }}
+        </span>
+      </template>
+      <template #main-table>
+        <div class="rectification-table">
+          <section class="damaged-list-container">
+            <DamagedList
+              :damagedList="reportTask.lossRecordList"
+              :active-id="activeTaskId || reportTask.lossRecordList[0].fixTaskId"
+              @update:activeId="handleActiveTask"
+            />
+          </section>
+          <section class="disaster-info-container">
+            <DisasterInfo :LossReportItemFormData="lossRecordListInfo" rectification v-if="lossRecordListInfo" />
+            <Rectification
+              v-if="lossRecordListInfo?.fixRecordList"
+              :rectification-list="lossRecordListInfo?.fixRecordList"
+              :rectification-dept-name="lossRecordListInfo?.responsibleDeptName"
+              :rectification-responsible-user-list="rectificationResponsibleUserList"
+              :rectification-priority="lossRecordListInfo?.priority"
+            />
+          </section>
+        </div>
+      </template>
+    </CollapseItem>
+  </div>
 </template>
 
-<script lang="ts" setup></script>
+<script setup lang="ts">
+  import { useRoute } from 'vue-router';
+  import { onMounted, ref } from 'vue';
+  import CollapseItem from './CollapseItem.vue';
+  import DamagedList from './DamagedList.vue';
+  import DisasterInfo from './DisasterInfo.vue';
+  import Rectification from './Rectification.vue';
+  import { useDisasterControlHook } from '../hook';
+  import type { PersonGroupItem } from '@/types/person-group/type';
+  import type { ReportTaskListDetail, LossRecordListDetail, OverviewLossRecordInfo } from '@/types/disaster-control';
+  import { queryUserInfoByIds } from '@/api/system/person-group';
 
-<style lang="scss" scoped></style>
+  const route = useRoute();
+  const handleTaskId = Number(route.params.id);
+  const { getDisasterLossDetailList, disasterLossDetailList } = useDisasterControlHook();
+  const activeId = ref<number | null>(null);
+  const activeTaskId = ref<number | null>(null);
+  const deptId = Number(route.query.deptId);
+  const handleCollapseToggle = (itemId: number) => {
+    if (activeId.value === itemId) {
+      activeId.value = null;
+    } else {
+      activeId.value = itemId;
+      reportTaskListInfo.value = reportTaskList.value.find((item) => item.reportDeptId === activeId.value);
+      if (!reportTaskListInfo.value) return;
+      lossRecordList.value = reportTaskListInfo.value?.lossRecordList;
+      activeTaskId.value = lossRecordList.value[0].fixTaskId;
+      lossRecordListInfo.value = lossRecordList.value.find((item) => item.fixTaskId === activeTaskId.value);
+      getFixUserList(lossRecordListInfo.value?.fixPrincipals);
+    }
+  };
+  const handleActiveTask = (fixTaskId: number) => {
+    activeTaskId.value = fixTaskId;
+    if (!lossRecordList.value.length) return;
+    lossRecordListInfo.value = lossRecordList.value.find((item) => item.fixTaskId === activeTaskId.value);
+    getFixUserList(lossRecordListInfo.value?.fixPrincipals);
+  };
+  const reportTaskList = ref<ReportTaskListDetail[]>([]);
+  const lossRecordList = ref<LossRecordListDetail[]>([]);
+  const reportTaskListInfo = ref<ReportTaskListDetail>();
+  const lossRecordListInfo = ref<LossRecordListDetail>();
+  const rectificationResponsibleUserList = ref<PersonGroupItem[]>([]);
+  const getFixUserList = async (userIds: string | undefined) => {
+    if (!userIds) return;
+    const ids = JSON.parse(userIds);
+    const res = await queryUserInfoByIds(ids);
+    rectificationResponsibleUserList.value = res;
+  };
+  const getLossRecordListInfo = () => {
+    if (!lossRecordListInfo.value) return;
+    return {
+      id: lossRecordListInfo.value.id,
+      name: lossRecordListInfo.value.affectedItems,
+    };
+  };
+  onMounted(async () => {
+    await getDisasterLossDetailList({ handleTaskId });
+    if (!disasterLossDetailList.value?.reportTaskList.length) return;
+    reportTaskList.value = disasterLossDetailList.value?.reportTaskList;
+    activeId.value = deptId ? Number(deptId) : reportTaskList.value[0].reportDeptId;
+    reportTaskListInfo.value = reportTaskList.value.find((item) => item.reportDeptId === activeId.value);
+    if (!reportTaskListInfo.value) return;
+    lossRecordList.value = reportTaskListInfo.value?.lossRecordList;
+    activeTaskId.value = lossRecordList.value[0].fixTaskId;
+    lossRecordListInfo.value = lossRecordList.value.find((item) => item.fixTaskId === activeTaskId.value);
+    getFixUserList(lossRecordListInfo.value?.fixPrincipals);
+  });
+  defineExpose({
+    getLossRecordListInfo,
+  });
+</script>
+
+<style lang="scss" scoped>
+  @use '@/views/disaster/style/info-container.scss' as *;
+  @use '../style/common.scss' as *;
+</style>

+ 120 - 0
src/views/disaster/disaster-control/src/components/ViewDisposalControlTaskItem.vue

@@ -0,0 +1,120 @@
+<template>
+  <div class="info-container">
+    <CollapseItem
+      v-for="reportTask in disasterLossDetailList?.reportTaskList"
+      :key="reportTask.reportDeptId"
+      :name="`上报单位:${reportTask.reportDeptName}`"
+      :isActive="activeId === reportTask.reportDeptId"
+      @toggle="handleCollapseToggle(reportTask.reportDeptId)"
+    >
+      <template #view-operation>
+        <div class="rectification-info">
+          <span class="num">{{ reportTask.lossRecordCount }}</span>
+          <span>条,整改完成{{ reportTask.fixFinishCount }}条</span>
+        </div>
+      </template>
+      <template #right-header>
+        <span class="collapse-item__header--right">
+          {{ activeId === reportTask.reportDeptId ? '收起' : '展开' }}
+        </span>
+      </template>
+      <template #main-table>
+        <div class="rectification-table">
+          <section class="damaged-list-container">
+            <DamagedList
+              :damagedList="reportTask.lossRecordList"
+              :active-id="activeTaskId || reportTask.lossRecordList[0].fixTaskId"
+              @update:activeId="handleActiveTask"
+            />
+          </section>
+          <section class="disaster-info-container">
+            <DisasterInfo :LossReportItemFormData="lossRecordListInfo" rectification v-if="lossRecordListInfo" />
+            <Rectification
+              v-if="lossRecordListInfo?.fixRecordList"
+              :rectification-list="lossRecordListInfo?.fixRecordList"
+              :rectification-dept-name="lossRecordListInfo?.responsibleDeptName"
+              :rectification-responsible-user-list="rectificationResponsibleUserList"
+              :rectification-priority="lossRecordListInfo?.priority"
+            />
+          </section>
+        </div>
+      </template>
+    </CollapseItem>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { useRoute } from 'vue-router';
+  import { onMounted, ref } from 'vue';
+  import CollapseItem from './CollapseItem.vue';
+  import DamagedList from './DamagedList.vue';
+  import DisasterInfo from './DisasterInfo.vue';
+  import Rectification from './Rectification.vue';
+  import { useDisasterControlHook } from '../hook';
+  import type { PersonGroupItem } from '@/types/person-group/type';
+  import type { ReportTaskListDetail, LossRecordListDetail, OverviewLossRecordInfo } from '@/types/disaster-control';
+  import { queryUserInfoByIds } from '@/api/system/person-group';
+
+  const route = useRoute();
+  const handleTaskId = Number(route.query.id);
+  const { getDisasterLossDetailList, disasterLossDetailList } = useDisasterControlHook();
+  const activeId = ref<number | null>(null);
+  const activeTaskId = ref<number | null>(null);
+  const handleCollapseToggle = (itemId: number) => {
+    if (activeId.value === itemId) {
+      activeId.value = null;
+    } else {
+      activeId.value = itemId;
+    }
+  };
+  const handleActiveTask = (fixTaskId: number) => {
+    activeTaskId.value = fixTaskId;
+    if (!lossRecordList.value.length) return;
+    lossRecordListInfo.value = lossRecordList.value.find((item) => item.fixTaskId === activeTaskId.value);
+    getFixUserList(lossRecordListInfo.value?.fixPrincipals);
+  };
+  const reportTaskList = ref<ReportTaskListDetail[]>([]);
+  const lossRecordList = ref<LossRecordListDetail[]>([]);
+  const reportTaskListInfo = ref<ReportTaskListDetail>();
+  const lossRecordListInfo = ref<LossRecordListDetail>();
+  const rectificationResponsibleUserList = ref<PersonGroupItem[]>([]);
+  const getFixUserList = async (userIds: string | undefined) => {
+    if (!userIds) return;
+    const ids = JSON.parse(userIds);
+    const res = await queryUserInfoByIds(ids);
+    rectificationResponsibleUserList.value = res;
+  };
+  const overviewLossRecordInfo = () => {
+    return {
+      needToReportDeptCount: disasterLossDetailList.value?.needToReportDeptCount,
+      reportedDeptCount: disasterLossDetailList.value?.reportedDeptCount,
+      waitToReportDeptCount: disasterLossDetailList.value?.waitToReportDeptCount,
+      overdueReportedDeptCount: disasterLossDetailList.value?.overdueReportedDeptCount,
+      lossRecordCount: disasterLossDetailList.value?.lossRecordCount,
+      fixedLossCount: disasterLossDetailList.value?.fixedLossCount,
+      fixingLossCount: disasterLossDetailList.value?.fixingLossCount,
+      waitToFixLossCount: disasterLossDetailList.value?.waitToFixLossCount,
+    };
+  };
+  const emit = defineEmits<{
+    (e: 'overviewLossRecordInfo', info: OverviewLossRecordInfo): void;
+  }>();
+  onMounted(async () => {
+    await getDisasterLossDetailList({ handleTaskId });
+    if (!disasterLossDetailList.value?.reportTaskList.length) return;
+    emit('overviewLossRecordInfo', overviewLossRecordInfo());
+    reportTaskList.value = disasterLossDetailList.value?.reportTaskList;
+    activeId.value = reportTaskList.value[0].reportDeptId;
+    reportTaskListInfo.value = reportTaskList.value.find((item) => item.reportDeptId === activeId.value);
+    if (!reportTaskListInfo.value) return;
+    lossRecordList.value = reportTaskListInfo.value?.lossRecordList;
+    activeTaskId.value = lossRecordList.value[0].fixTaskId;
+    lossRecordListInfo.value = lossRecordList.value.find((item) => item.fixTaskId === activeTaskId.value);
+    getFixUserList(lossRecordListInfo.value?.fixPrincipals);
+  });
+</script>
+
+<style lang="scss" scoped>
+  @use '@/views/disaster/style/info-container.scss' as *;
+  @use '../style/common.scss' as *;
+</style>

+ 2 - 2
src/views/disaster/disaster-control/src/components/ViewLossReportItem.vue

@@ -3,7 +3,7 @@
     <CollapseItem
       v-for="reportTask in disasterLossDetailList?.reportTaskList"
       :key="reportTask.reportDeptId"
-      :name="reportTask.reportDeptName"
+      :name="`上报单位:${reportTask.reportDeptName}`"
       :isActive="activeId === reportTask.reportDeptId"
       @toggle="handleCollapseToggle(reportTask.reportDeptId)"
     >
@@ -15,7 +15,7 @@
       </template>
       <template #right-header>
         <span class="collapse-item__header--right">
-          {{ activeId === reportTask.reportTaskId ? '收起' : '立即查看' }}
+          {{ activeId === reportTask.reportDeptId ? '收起' : '展开' }}
         </span>
       </template>
       <template #main-table>

File diff suppressed because it is too large
+ 13 - 0
src/views/disaster/disaster-control/src/svg/loss.svg


File diff suppressed because it is too large
+ 13 - 0
src/views/disaster/disaster-control/src/svg/report.svg


+ 3 - 3
src/views/disaster/disaster-precaution/src/constants/template-detail.ts

@@ -9,17 +9,17 @@ import { INSPECT_TYPE } from './task-execution';
 export const TASK_TEMPLATE_LIST = [
   {
     id: INSPECT_TYPE.Previous,
-    name: '台讯前期安全检查模',
+    name: '台讯前期安全检查模',
     img: Previous
   },
   {
     id: INSPECT_TYPE.Midterm,
-    name: '台讯中期安全检查任务模',
+    name: '台讯中期安全检查任务模',
     img: Midterm
   },
   {
     id: INSPECT_TYPE.Later,
-    name: '台讯后期安全检查模',
+    name: '台讯后期安全检查模',
     img: Later
   },
 ];