Просмотр исходного кода

完成灾害处置静态表单页面

chauncey 11 месяцев назад
Родитель
Сommit
3beb32b44a

+ 72 - 5
mock/disaster-control/table.ts

@@ -63,7 +63,7 @@ const disposalManagementItemList = [
         id: 1,
         realname: 'XXX',
         username: '321540',
-      }
+      },
     ],
   },
   {
@@ -73,8 +73,7 @@ const disposalManagementItemList = [
     dueCompleteTime: '2025-05-23 10:00',
     status: 1,
     taskStage: 2,
-    reportPrincipals: [
-    ],
+    reportPrincipals: [],
   },
   {
     handleTaskId: 1,
@@ -118,11 +117,63 @@ const disposalManagementItemList = [
     dueCompleteTime: '2025-05-23 10:00',
     status: 2,
     taskStage: 2,
-    reportPrincipals: [
-    ],
+    reportPrincipals: [],
   },
 ];
 
+const lossReportReportTaskList = {
+  records: [
+    {
+      id: 1,
+      taskName: '台风“贝碧嘉”灾害损失上报1',
+      deptName: '广东省应急管理厅',
+      dueCompleteTime: '2025-05-23 10:00',
+      taskStage: 1,
+    },
+    {
+      id: 2,
+      taskName: '台风“贝碧嘉”灾害损失上报2',
+      deptName: '湖北省应急管理厅',
+      dueCompleteTime: '2025-05-23 10:00',
+      taskStage: 2,
+    },
+    {
+      id: 3,
+      taskName: '台风“贝碧嘉”灾害损失上报3',
+      deptName: '海南省应急管理厅',
+      dueCompleteTime: '2025-05-23 10:00',
+      taskStage: 3,
+    },
+  ],
+  totalRow: 3,
+};
+
+const lossRecordItemList = [
+  {
+    affectedArea: '广东省应急管理厅',
+    affectedItems: '树木8棵',
+    reportTime: '2025-05-23 10:00',
+    department: '广东省应急管理厅',
+    priority: 1,
+    progress: 1,
+  },
+  {
+    affectedArea: '湖北省应急管理厅',
+    affectedItems: '房屋10间',
+    reportTime: '2025-05-23 10:00',
+    department: '湖北省应急管理厅',
+    priority: 2,
+    progress: 2,
+  },
+  {
+    affectedArea: '海南省应急管理厅',
+    affectedItems: '道路100米',
+    reportTime: '2025-05-23 10:00',
+    department: '海南省应急管理厅',
+    priority: 3,
+    progress: 3,
+  },
+];
 export default [
   {
     url: '/safety_mock_api/disasterHandle/queryDisasterHandleTaskPage',
@@ -140,4 +191,20 @@ export default [
       return resultSuccess(disposalManagementItemList);
     },
   },
+  {
+    url: '/safety_mock_api/disasterHandle/queryDisasterReportTask2',
+    timeout: 500,
+    method: 'post',
+    response: () => {
+      return resultSuccess(lossReportReportTaskList);
+    },
+  },
+  {
+    url: '/safety_mock_api/disasterHandle/queryDisasterHandleTaskPage2',
+    timeout: 500,
+    method: 'post',
+    response: () => {
+      return resultSuccess(lossRecordItemList);
+    },
+  },
 ];

+ 28 - 1
src/api/disaster-control/index.ts

@@ -4,13 +4,16 @@ import type {
   DisposalManagementListQuery,
   DisposalManagementListItemQuery,
   DisposalManagementTableResponse,
+  LossReportReportTaskQuery,
+  LossRecordItemQuery,
+  LossRecordTableResponse,
 } from '@/types/disaster-control';
 import type { QueryPageResponse, QueryPageRequest } from '@/types/disaster';
 /**
  * 获取台风灾害管理表格数据
  */
 export const getDisasterControlCollapseData = (query: QueryPageRequest<DisposalManagementListQuery>) => {
-  return http.request<QueryPageResponse<DisposalManagementListResponse>>({
+  return http.request<QueryPageResponse<DisposalManagementListResponse<DisposalManagementTableResponse>>>({
     url: '/disasterHandle/queryDisasterHandleTaskPage',
     method: 'post',
     data: query,
@@ -24,3 +27,27 @@ export const getDisasterControlTableData = (query: DisposalManagementListItemQue
     data: query,
   });
 };
+
+export const getLossReportReportTaskData = (query: QueryPageRequest<LossReportReportTaskQuery>) => {
+  return http.request<QueryPageResponse<DisposalManagementTableResponse>>({
+    url: '/disasterHandle/queryDisasterReportTask2',
+    method: 'post',
+    data: query,
+  });
+};
+
+export const getLossRecordCollapseData = (query: QueryPageRequest<DisposalManagementListQuery>) => {
+  return http.request<QueryPageResponse<DisposalManagementListResponse<LossRecordTableResponse>>>({
+    url: '/disasterHandle/queryDisasterHandleTaskPage',
+    method: 'post',
+    data: query,
+  });
+};
+
+export const getLossRecordTableData = (query: LossRecordItemQuery) => {
+  return http.request<LossRecordTableResponse[]>({
+    url: '/disasterHandle/queryDisasterHandleTaskPage2',
+    method: 'post',
+    data: query,
+  });
+};

+ 2 - 1
src/components/BasicTable.vue

@@ -27,7 +27,7 @@
       v-if="props.tableConfig.pagination && props.tableData.length > 0"
       :current-page="props.tableConfig.pagination.pageNumber"
       :page-size="props.tableConfig.pagination.pageSize"
-      :page-sizes="PAGE_SIZE_CONFIG"
+      :page-sizes="props.pageSizeConfig || PAGE_SIZE_CONFIG"
       layout="prev, pager, next, jumper, sizes, total"
       background
       :total="props.tableConfig.pagination.total"
@@ -46,6 +46,7 @@
   const props = defineProps<{
     tableConfig: BasicTableProps;
     tableData: any[];
+    pageSizeConfig?: number[];
   }>();
   const emits = defineEmits<{
     (e: 'update:pageSize', value: number): void;

+ 23 - 4
src/types/disaster-control/index.ts

@@ -3,16 +3,26 @@ export interface DisposalManagementListQuery {
   reporterId?: number;
 }
 
-export interface DisposalManagementListItemQuery extends DisposalManagementListQuery {
+export interface LossReportReportTaskQuery {
+  taskStage?: string;
+}
+
+export interface DisposalManagementListItemQuery extends DisposalManagementListQuery, LossReportReportTaskQuery {
   handleTaskIds: number[];
   reportDeptIds?: number[];
   status?: string;
-  taskStage?: string;
 }
-export interface DisposalManagementListResponse {
+
+export interface LossRecordItemQuery  {
+    handleTaskIds: number[];
+  department?: string;
+  progress?: string;
+}
+
+export interface DisposalManagementListResponse<T> {
   id: number;
   taskName: string;
-  tableData: DisposalManagementTableResponse[];
+  tableData: T[];
 }
 
 export interface DisposalManagementTableResponse {
@@ -23,3 +33,12 @@ export interface DisposalManagementTableResponse {
   taskStage: string;
   reportPrincipals: UserInfo[];
 }
+
+export interface LossRecordTableResponse {
+  affectedArea: string;
+  affectedItems: string;
+  reportTime: string;
+  department: string;
+  priority: number;
+  progress: number;
+}

+ 15 - 15
src/views/disaster/components/User.vue

@@ -54,7 +54,7 @@
 <script lang="ts" setup>
   import { nextTick, ref, watch } from 'vue';
   import empty from 'assets/images/empty@1X.png';
-  import { queryAvailableUserList } from '@/api/push-object';
+  // import { queryAvailableUserList } from '@/api/push-object';
   import type { TreeNodeData } from '@/views/disaster/types';
   import type { UserInfo } from '@/types/push-object';
   import type { ElTree } from 'element-plus';
@@ -83,20 +83,20 @@
   ]);
   const selectType = ref(searchOptions.value[0].value);
   const getUserList = async () => {
-    loading.value = true;
-    const res = await queryAvailableUserList();
-    searchResult.value = res.map((user) => {
-      return {
-        id: user.id,
-        name: `${user.username}-${user.realname}`,
-        children: [],
-      };
-    });
-    nodeData.value[0].children = searchResult.value;
-    const selectedIds = selectedPersonList.value.map((item) => item.id);
-    await nextTick();
-    treeRef.value?.setCheckedKeys(selectedIds);
-    loading.value = false;
+    // loading.value = true;
+    // const res = await queryAvailableUserList();
+    // searchResult.value = res.map((user) => {
+    //   return {
+    //     id: user.id,
+    //     name: `${user.username}-${user.realname}`,
+    //     children: [],
+    //   };
+    // });
+    // nodeData.value[0].children = searchResult.value;
+    // const selectedIds = selectedPersonList.value.map((item) => item.id);
+    // await nextTick();
+    // treeRef.value?.setCheckedKeys(selectedIds);
+    // loading.value = false;
   };
   const handleSearch = () => {
     getUserList();

+ 1 - 0
src/views/disaster/constant/index.ts

@@ -76,4 +76,5 @@ export const DISASTER_PERMISSIONS = {
   WARNING_INFO: 'disaster_business_module:warn_info',
   DEFENSE_NOTICE: 'disaster_business_module:defense_notice',
   TASK_MANAGEMENT: 'disaster_business_module:prevent_inspect',
+  DISPOSAL_MANAGEMENT: 'disaster_business_module:disaster_handle',
 };

+ 65 - 38
src/views/disaster/disaster-control/PageDisposalManagement.vue

@@ -6,8 +6,13 @@
     <main class="disaster-precaution-container__main">
       <div class="disaster-precaution">
         <header class="disaster-precaution__header">
-          <el-button type="primary" class="disaster-precaution__header--button" :icon="Plus">
-            创建灾害损失记录
+          <el-button
+            type="primary"
+            class="disaster-precaution__header--button"
+            :icon="Plus"
+            v-if="disposalManagementPermissions"
+          >
+            创建灾害处置任务
           </el-button>
           <Search
             :searchConfig="DISPOSAL_MANAGEMENT_SEARCH_CONFIG"
@@ -15,13 +20,23 @@
             @update:searchData="handleSearch"
           >
             <template #reportDeptIds>
-              <el-select v-model="searchData.reportDeptIds" multiple placeholder="请选择上报单位" filterable class="custom-select">
+              <el-select
+                v-model="searchData.reportDeptIds"
+                multiple
+                placeholder="请选择上报单位"
+                filterable
+                class="custom-select"
+              >
                 <el-option v-for="item in firstLevelDepts" :key="item.id" :label="item.deptName" :value="item.id" />
               </el-select>
             </template>
           </Search>
         </header>
-        <div class="collapse-container" v-loading="collapseLoading">
+        <div
+          class="collapse-container"
+          v-loading="collapseLoading"
+          :class="disposalManagementPermissions ? 'collapse-container--permission' : 'collapse-container--default'"
+        >
           <div class="empty-container" v-if="collapseList.length === 0">
             <img :src="Empty" />
             <span>暂无数据</span>
@@ -32,6 +47,7 @@
               :key="item.id"
               :name="item.taskName"
               :defaultOpen="item.id === 1"
+              :disposalManagementPermissions="disposalManagementPermissions"
             >
               <template #main-table>
                 <BasicTable :tableData="item.tableData" :tableConfig="tableConfig">
@@ -45,7 +61,7 @@
                     </div>
                   </template>
                   <template #taskStage="scope">
-                    <span>{{ formatTaskStage(scope.row.taskStage) }}</span>
+                    <span>{{ getTaskStage(scope.row.taskStage) }}</span>
                   </template>
                   <template #reportPrincipals="scope">
                     <p v-for="user in scope.row.reportPrincipals" :key="user.id">
@@ -53,22 +69,28 @@
                     </p>
                   </template>
                   <template #action="scope">
-                    <ActionButton text="编辑" v-if="scope.row.status === ACTIVE_STATUS.NOT_EFFECTIVE" />
+                    <ActionButton
+                      text="编辑"
+                      v-if="scope.row.status === ACTIVE_STATUS.NOT_EFFECTIVE && disposalManagementPermissions"
+                    />
                     <ActionButton
                       text="发布"
                       :popconfirm="{
                         title: '确定发布吗?',
                       }"
-                      v-if="scope.row.status === ACTIVE_STATUS.NOT_EFFECTIVE"
+                      v-if="scope.row.status === ACTIVE_STATUS.NOT_EFFECTIVE && disposalManagementPermissions"
                     />
                     <ActionButton
                       text="撤回"
                       :popconfirm="{
                         title: '确定撤回吗?',
                       }"
-                      v-if="scope.row.taskStage === TASK_STAGE.TO_BE_REPORTED"
+                      v-if="scope.row.taskStage === TASK_STAGE.TO_BE_REPORTED && disposalManagementPermissions"
+                    />
+                    <ActionButton
+                      text="删除"
+                      v-if="scope.row.status === ACTIVE_STATUS.NOT_EFFECTIVE && disposalManagementPermissions"
                     />
-                    <ActionButton text="删除" v-if="scope.row.status === ACTIVE_STATUS.NOT_EFFECTIVE" />
                     <ActionButton text="查看" v-if="scope.row.status === ACTIVE_STATUS.ACTIVE" />
                   </template>
                 </BasicTable>
@@ -98,20 +120,32 @@
   import Search from '@/views/disaster/components/Search.vue';
   import CollapseItem from './src/components/CollapseItem.vue';
   import BasicTable from '@/components/BasicTable.vue';
-  import { DISPOSAL_MANAGEMENT_SEARCH_CONFIG } from './src/config';
   import { getAllDepartments } from '@/api/auth/dept';
   import { onMounted, reactive, ref } from 'vue';
   import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
   import type { DeptTree } from '@/types/dept/type';
-  import { TASK_STAGE_OPTIONS, TASK_STAGE } from './src/constant';
+  import { TASK_STAGE } from './src/constant';
   import { getDisasterControlCollapseData, getDisasterControlTableData } from '@/api/disaster-control';
   import { DEFAULT_PAGE_SIZE, DISASTER_CONTROL_PAGE_SIZE_CONFIG } from './src/constant';
-  import type { DisposalManagementListResponse } from '@/types/disaster-control';
+  import type { DisposalManagementListResponse, DisposalManagementTableResponse } from '@/types/disaster-control';
   import useTableConfig from '@/hooks/useTableConfigHook';
-  import { DISPOSAL_MANAGEMENT_TABLE_COLUMNS, TABLE_OPTIONS } from './src/config';
-  import { ACTIVE_STATUS, ACTIVE_STATUS_COLOR, ACTIVE_STATUS_MAP } from '@/views/disaster/constant';
+  import {
+    DISPOSAL_MANAGEMENT_SEARCH_CONFIG,
+    DISPOSAL_MANAGEMENT_TABLE_COLUMNS,
+    DISPOSAL_MANAGEMENT_TABLE_OPTIONS,
+  } from './src/config';
+  import { getTaskStage } from './src/util';
+  import {
+    ACTIVE_STATUS,
+    ACTIVE_STATUS_COLOR,
+    ACTIVE_STATUS_MAP,
+    DISASTER_PERMISSIONS,
+  } from '@/views/disaster/constant';
   import ActionButton from '@/components/ActionButton.vue';
   import Empty from 'assets/images/empty@1X.png';
+  import { useUserInfoHook } from '@/views/disaster/hooks/userInfo';
+
+  const { permissions } = useUserInfoHook();
 
   const firstLevelDepts = ref<DeptTree[]>([]);
   const searchData = reactive({
@@ -125,13 +159,10 @@
   const total = ref(0);
 
   const collapseLoading = ref(false);
-  const collapseList = ref<DisposalManagementListResponse[]>([]);
+  const collapseList = ref<DisposalManagementListResponse<DisposalManagementTableResponse>[]>([]);
+  const disposalManagementPermissions = ref(false);
 
-  const { tableConfig } = useTableConfig(DISPOSAL_MANAGEMENT_TABLE_COLUMNS, TABLE_OPTIONS, false);
-
-  const formatTaskStage = (taskStage: number) => {
-    return TASK_STAGE_OPTIONS.find((item) => item.value === taskStage)?.label;
-  };
+  const { tableConfig } = useTableConfig(DISPOSAL_MANAGEMENT_TABLE_COLUMNS, DISPOSAL_MANAGEMENT_TABLE_OPTIONS, false);
 
   const handleSizeChange = (size: number) => {
     pageSize.value = size;
@@ -178,12 +209,18 @@
     const result = await getAllDepartments();
     await getDisposalData();
     await getDisposalTableData();
+    disposalManagementPermissions.value = Boolean(
+      permissions.find((item: { code: string }) => item.code === DISASTER_PERMISSIONS.DISPOSAL_MANAGEMENT),
+    );
     firstLevelDepts.value = formatDeptTree(result);
   });
 </script>
 
 <style scoped lang="scss">
   @use '../style/disaster.scss' as *;
+  @use './src/style/collapse.scss' as *;
+  $collapse-container-height-default: calc(68vh - 13cpx);
+  $collapse-container-height-permission: calc(63vh - 15cpx);
   .custom-select {
     width: 200cpx;
     :deep(.el-select__selection) {
@@ -193,23 +230,13 @@
     }
   }
   .collapse-container {
-    display: flex;
-    flex-direction: column;
-    gap: 10cpx;
-    width: 100%;
-    height: calc(63vh - 15cpx);
-    max-height: calc(63vh - 15cpx);
-    overflow-y: auto;
-  }
-  .empty-container {
-    width: 100%;
-    height: 100%;
-    @include flex-center;
-    flex-direction: column;
-    gap: 10cpx;
-  }
-  .pagination-container {
-    display: flex;
-    justify-content: flex-end;
+    &--permission {
+      height: $collapse-container-height-permission;
+      max-height: $collapse-container-height-permission;
+    }
+    &--default {
+      height: $collapse-container-height-default;
+      max-height: $collapse-container-height-default;
+    }
   }
 </style>

+ 35 - 8
src/views/disaster/disaster-control/PageLossReport.vue

@@ -1,13 +1,40 @@
 <template>
-    <div>
-        this is loss report
-    </div>
+  <div class="disaster-precaution-container">
+    <header class="disaster-precaution-container__header">
+      <span class="disaster-precaution-container__title">灾害损失上报</span>
+      <el-tabs v-model="activeName">
+        <el-tab-pane v-for="item in LOSS_REPORT_TABS" :key="item.value" :label="item.label" :name="item.value" />
+      </el-tabs>
+    </header>
+    <main class="disaster-precaution-container__main">
+      <component :is="dynamicComponent" />
+    </main>
+  </div>
 </template>
 
-<script lang="ts" setup>
-
+<script setup lang="ts">
+  import { LOSS_REPORT_TABS } from './src/constant';
+  import { computed, ref, defineAsyncComponent } from 'vue';
+  const activeName = ref(LOSS_REPORT_TABS[0].value);
+  const dynamicComponent = computed(() => {
+    switch (activeName.value) {
+      case LOSS_REPORT_TABS[0].value:
+        return defineAsyncComponent(() => import('./src/components/ReportTask.vue'));
+      case LOSS_REPORT_TABS[1].value:
+        return defineAsyncComponent(() => import('./src/components/LossRecord.vue'));
+    }
+  });
 </script>
 
-<style lang="scss" scoped>
-
-</style>
+<style scoped lang="scss">
+  @use '../style/disaster.scss' as *;
+  .disaster-precaution-container__header {
+    padding-bottom: 0 !important;
+  }
+  :deep(.el-tabs__header) {
+    margin: 0;
+  }
+  :deep(.el-tabs__item) {
+    font-size: 14cpx;
+  }
+</style>

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

@@ -8,7 +8,7 @@
         <span>{{ name }}</span>
         <img :src="ViewDocument" alt="查看" class="collapse-item__icon" @click.stop="handleViewDocument" />
       </div>
-      <div class="collapse-item__header--right">
+      <div class="collapse-item__header--right" v-if="disposalManagementPermissions">
         <el-button type="primary">发布</el-button>
         <el-button type="primary">撤回</el-button>
         <el-button type="primary">删除</el-button>
@@ -24,7 +24,7 @@
   import { ref, onMounted } from 'vue';
   import { ArrowUp, ArrowDown } from '@element-plus/icons-vue';
   import ViewDocument from '../svg/view-document.svg';
-  const props = defineProps<{ name: string; defaultOpen?: boolean }>();
+  const props = defineProps<{ name: string; defaultOpen?: boolean; disposalManagementPermissions?: boolean }>();
   const isOpen = ref(false);
   const toggle = () => {
     isOpen.value = !isOpen.value;

+ 121 - 0
src/views/disaster/disaster-control/src/components/LossRecord.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="disaster-precaution">
+    <header class="disaster-precaution__header">
+      <el-button type="primary" class="disaster-precaution__header--button" :icon="Plus"> 创建灾害损失记录 </el-button>
+      <Search
+        :searchConfig="LOSS_RECORD_LOSS_RECORD_SEARCH_CONFIG"
+        :searchData="searchData"
+        @update:searchData="handleSearch"
+      >
+      </Search>
+    </header>
+    <div class="collapse-container" v-loading="collapseLoading">
+      <div class="empty-container" v-if="collapseList.length === 0">
+        <img :src="Empty" />
+        <span>暂无数据</span>
+      </div>
+      <template v-else>
+        <CollapseItem v-for="item in collapseList" :key="item.id" :name="item.taskName" :defaultOpen="item.id === 1">
+          <template #main-table>
+            <BasicTable :tableData="item.tableData" :tableConfig="tableConfig" />
+          </template>
+        </CollapseItem>
+      </template>
+    </div>
+    <div class="pagination-container" v-if="collapseList.length > 0">
+      <el-pagination
+        :current-page="currentPage"
+        :page-size="pageSize"
+        :page-sizes="DISASTER_CONTROL_PAGE_SIZE_CONFIG"
+        layout="prev, pager, next, jumper, sizes, total"
+        background
+        :total="total"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+      />
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { ref, reactive, onMounted } from 'vue';
+  import { Plus } from '@element-plus/icons-vue';
+  import Search from '@/views/disaster/components/Search.vue';
+  import BasicTable from '@/components/BasicTable.vue';
+  import CollapseItem from './CollapseItem.vue';
+  import { DEFAULT_PAGE_SIZE, DISASTER_CONTROL_PAGE_SIZE_CONFIG } from '../constant';
+  import type { DisposalManagementListResponse, LossRecordTableResponse } from '@/types/disaster-control';
+  import {
+    LOSS_RECORD_LOSS_RECORD_SEARCH_CONFIG,
+    LOSS_RECORD_TABLE_COLUMNS,
+    DISPOSAL_MANAGEMENT_TABLE_OPTIONS,
+  } from '../config';
+  import Empty from 'assets/images/empty@1X.png';
+  import { getLossRecordCollapseData, getLossRecordTableData } from '@/api/disaster-control';
+  import useTableConfig from '@/hooks/useTableConfigHook';
+
+  const currentPage = ref(1);
+  const pageSize = ref(DEFAULT_PAGE_SIZE);
+  const total = ref(0);
+  const collapseLoading = ref(false);
+  const { tableConfig } = useTableConfig(LOSS_RECORD_TABLE_COLUMNS, DISPOSAL_MANAGEMENT_TABLE_OPTIONS, false);
+  const searchData = reactive({
+    department: '',
+    progress: '',
+  });
+  const handleSearch = () => {
+    console.log(searchData);
+  };
+
+  const taskIds = ref<number[]>([]);
+  const collapseList = ref<DisposalManagementListResponse<LossRecordTableResponse>[]>([]);
+  const getDisposalData = async () => {
+    collapseLoading.value = true;
+    const res = await getLossRecordCollapseData({
+      pageNumber: currentPage.value,
+      pageSize: pageSize.value,
+      queryParam: {},
+    });
+    collapseList.value = res.records;
+    collapseList.value.forEach((item) => {
+      item.tableData = [];
+    });
+    taskIds.value = res.records.map((item) => item.id);
+    total.value = res.totalRow;
+    collapseLoading.value = false;
+  };
+
+  const getDisposalTableData = async () => {
+    tableConfig.loading = true;
+    const res = await getLossRecordTableData({
+      handleTaskIds: taskIds.value,
+      ...searchData,
+    });
+    collapseList.value.forEach((item) => {
+      item.tableData = res;
+    });
+    tableConfig.loading = false;
+  };
+  const handleSizeChange = (size: number) => {
+    pageSize.value = size;
+  };
+
+  const handleCurrentChange = (page: number) => {
+    currentPage.value = page;
+  };
+
+  onMounted(async () => {
+    await getDisposalData();
+    await getDisposalTableData();
+  });
+</script>
+
+<style lang="scss" scoped>
+  @use '@/views/disaster/style/disaster.scss' as *;
+  @use '../style/collapse.scss' as *;
+  $collapse-container-height: calc(60vh - 20cpx);
+  .collapse-container {
+    height: $collapse-container-height;
+    max-height: $collapse-container-height;
+  }
+</style>

+ 69 - 0
src/views/disaster/disaster-control/src/components/ReportTask.vue

@@ -0,0 +1,69 @@
+<template>
+  <div class="disaster-precaution">
+    <header class="disaster-precaution__header">
+      <Search
+        :searchConfig="LOSS_REPORT_REPORT_TASK_SEARCH_CONFIG"
+        :searchData="searchData"
+        @update:searchData="handleSearch"
+      >
+      </Search>
+    </header>
+    <BasicTable :tableConfig="tableConfig" :tableData="tableData" :pageSizeConfig="DISASTER_CONTROL_PAGE_SIZE_CONFIG">
+      <template #taskStage="scope">
+        <span>{{ getTaskStage(scope.row.taskStage) }}</span>
+      </template>
+    </BasicTable>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { ref, reactive, onMounted } from 'vue';
+  import Search from '@/views/disaster/components/Search.vue';
+  import BasicTable from '@/components/BasicTable.vue';
+  import {
+    LOSS_REPORT_REPORT_TASK_SEARCH_CONFIG,
+    LOSS_REPORT_REPORT_TASK_TABLE_OPTIONS,
+    LOSS_REPORT_REPORT_TASK_TABLE_COLUMNS,
+  } from '../config';
+  import useTableConfig from '@/hooks/useTableConfigHook';
+  import { DEFAULT_PAGE_SIZE, DISASTER_CONTROL_PAGE_SIZE_CONFIG } from '../constant';
+  import { getLossReportReportTaskData } from '@/api/disaster-control';
+  import type { LossReportReportTaskQuery, DisposalManagementTableResponse } from '@/types/disaster-control';
+  import type { QueryPageRequest } from '@/types/disaster';
+  import { getTaskStage } from '../util';
+
+  const searchData = reactive({
+    taskStage: '',
+  });
+  const tableData = ref<DisposalManagementTableResponse[]>([]);
+  const { tableConfig, pagination } = useTableConfig(
+    LOSS_REPORT_REPORT_TASK_TABLE_COLUMNS,
+    LOSS_REPORT_REPORT_TASK_TABLE_OPTIONS,
+  );
+  pagination.pageSize = DEFAULT_PAGE_SIZE;
+  let ReportTaskListQuery: QueryPageRequest<LossReportReportTaskQuery> = {
+    pageNumber: pagination.pageNumber,
+    pageSize: pagination.pageSize,
+    queryParam: {},
+  };
+  const getTableData = async () => {
+    tableConfig.loading = true;
+    const res = await getLossReportReportTaskData(ReportTaskListQuery);
+    tableData.value = res.records;
+    pagination.total = res.totalRow;
+    tableConfig.loading = false;
+  };
+  const handleSearch = () => {
+    if (searchData.taskStage !== '') {
+      ReportTaskListQuery.queryParam.taskStage = searchData.taskStage;
+    }
+    getTableData();
+  };
+  onMounted(() => {
+    getTableData();
+  });
+</script>
+
+<style lang="scss" scoped>
+  @use '@/views/disaster/style/disaster.scss' as *;
+</style>

+ 22 - 3
src/views/disaster/disaster-control/src/config/index.ts

@@ -1,4 +1,23 @@
-import { DISPOSAL_MANAGEMENT_SEARCH_CONFIG } from './search';
-import { DISPOSAL_MANAGEMENT_TABLE_COLUMNS, TABLE_OPTIONS } from './table';
+import {
+  DISPOSAL_MANAGEMENT_SEARCH_CONFIG,
+  LOSS_REPORT_REPORT_TASK_SEARCH_CONFIG,
+  LOSS_RECORD_LOSS_RECORD_SEARCH_CONFIG,
+} from './search';
+import {
+  DISPOSAL_MANAGEMENT_TABLE_COLUMNS,
+  LOSS_REPORT_REPORT_TASK_TABLE_COLUMNS,
+  DISPOSAL_MANAGEMENT_TABLE_OPTIONS,
+  LOSS_REPORT_REPORT_TASK_TABLE_OPTIONS,
+  LOSS_RECORD_TABLE_COLUMNS,
+} from './table';
 
-export { DISPOSAL_MANAGEMENT_SEARCH_CONFIG, DISPOSAL_MANAGEMENT_TABLE_COLUMNS, TABLE_OPTIONS };
+export {
+  DISPOSAL_MANAGEMENT_SEARCH_CONFIG,
+  LOSS_REPORT_REPORT_TASK_SEARCH_CONFIG,
+  LOSS_RECORD_LOSS_RECORD_SEARCH_CONFIG,
+  DISPOSAL_MANAGEMENT_TABLE_COLUMNS,
+  LOSS_REPORT_REPORT_TASK_TABLE_COLUMNS,
+  DISPOSAL_MANAGEMENT_TABLE_OPTIONS,
+  LOSS_REPORT_REPORT_TASK_TABLE_OPTIONS,
+  LOSS_RECORD_TABLE_COLUMNS,
+};

+ 37 - 4
src/views/disaster/disaster-control/src/config/search.ts

@@ -5,6 +5,20 @@ import type { SearchConfig } from '@/views/disaster/types';
 import { ACTIVE_STATUS_OPTIONS } from '@/views/disaster/constant';
 import { TASK_STAGE_OPTIONS } from '../constant';
 
+// 通用搜索配置
+const BASIC_SEARCH_CONFIG = {
+  TASK_STAGE: {
+    label: '任务阶段',
+    prop: 'taskStage',
+    component: 'ElSelect',
+    selectOptions: TASK_STAGE_OPTIONS,
+    componentProps: {
+      placeholder: '请选择任务阶段',
+    },
+  },
+};
+
+// 灾害处理搜索配置
 export const DISPOSAL_MANAGEMENT_SEARCH_CONFIG: SearchConfig[] = [
   {
     label: '上报单位',
@@ -20,13 +34,32 @@ export const DISPOSAL_MANAGEMENT_SEARCH_CONFIG: SearchConfig[] = [
       placeholder: '请选择生效状态',
     },
   },
+  BASIC_SEARCH_CONFIG.TASK_STAGE,
+];
+
+// 损失上报-上报任务搜索配置
+export const LOSS_REPORT_REPORT_TASK_SEARCH_CONFIG: SearchConfig[] = [
+  BASIC_SEARCH_CONFIG.TASK_STAGE,
+];
+
+// 损失记录-损失记录搜索配置
+export const LOSS_RECORD_LOSS_RECORD_SEARCH_CONFIG: SearchConfig[] = [
+  {
+    label: '整改部门',
+    prop: 'department',
+    component: 'ElSelect',
+    selectOptions: [],
+    componentProps: {
+      placeholder: '请选择整改部门',
+    },
+  },
   {
-    label: '任务阶段',
-    prop: 'taskStage',
+    label: '整改进度',
+    prop: 'progress',
     component: 'ElSelect',
-    selectOptions: TASK_STAGE_OPTIONS,
+    selectOptions: [],
     componentProps: {
-      placeholder: '请选择任务阶段',
+      placeholder: '请选择整改进度',
     },
   },
 ];

+ 85 - 21
src/views/disaster/disaster-control/src/config/table.ts

@@ -3,15 +3,50 @@
  */
 import type { TableColumnProps } from '@/types/basic-table';
 // 基础表格样式配置
-export const TABLE_OPTIONS = {
+const TABLE_OPTIONS = {
   emptyText: '暂无数据',
   loading: true,
   stripe: true,
+};
+
+// 处置管理表格配置
+export const DISPOSAL_MANAGEMENT_TABLE_OPTIONS = {
+  ...TABLE_OPTIONS,
   height: '40vh',
 };
 
+// 损失上报-上报任务表格配置
+export const LOSS_REPORT_REPORT_TASK_TABLE_OPTIONS = {
+  ...TABLE_OPTIONS,
+  height: 'calc(65vh - 20px)',
+};
+
 // 基础表格列配置项
 const BASIC_TABLE_COLUMNS = {
+  INDEX: {
+    type: 'index',
+    label: '序号',
+    prop: 'index',
+    align: 'center',
+    width: '80cpx',
+  },
+  DEPT_NAME: {
+    label: '上报部门',
+    prop: 'deptName',
+    align: 'center',
+  },
+  DUE_COMPLETE_TIME: {
+    label: '应完成上报时间',
+    prop: 'dueCompleteTime',
+    align: 'center',
+    width: '200cpx',
+  },
+  TASK_STAGE: {
+    label: '任务阶段',
+    prop: 'taskStage',
+    align: 'center',
+    slot: 'taskStage',
+  },
   ACTION: {
     prop: 'action',
     label: '操作',
@@ -24,43 +59,72 @@ const BASIC_TABLE_COLUMNS = {
 
 // 处置管理表格列配置
 export const DISPOSAL_MANAGEMENT_TABLE_COLUMNS: TableColumnProps[] = [
+  BASIC_TABLE_COLUMNS.INDEX,
+  BASIC_TABLE_COLUMNS.DEPT_NAME,
+  BASIC_TABLE_COLUMNS.DUE_COMPLETE_TIME,
   {
-    type: 'index',
-    label: '序号',
-    prop: 'index',
+    label: '任务状态',
+    prop: 'status',
     align: 'center',
-    width: '80cpx',
+    slot: 'status',
+    width: '120cpx',
   },
+  BASIC_TABLE_COLUMNS.TASK_STAGE,
   {
-    label: '上报部门',
-    prop: 'deptName',
+    label: '上报责任人',
+    prop: 'reportPrincipals',
     align: 'center',
+    slot: 'reportPrincipals',
+    width: '200cpx',
   },
+  BASIC_TABLE_COLUMNS.ACTION,
+];
+
+// 损失上报-上报任务表格列配置
+export const LOSS_REPORT_REPORT_TASK_TABLE_COLUMNS: TableColumnProps[] = [
+  BASIC_TABLE_COLUMNS.INDEX,
   {
-    label: '应完成上报时间',
-    prop: 'dueCompleteTime',
+    label: '任务名称',
+    prop: 'taskName',
     align: 'center',
-    width: '200cpx',
   },
+  BASIC_TABLE_COLUMNS.DEPT_NAME,
+  BASIC_TABLE_COLUMNS.DUE_COMPLETE_TIME,
+  BASIC_TABLE_COLUMNS.TASK_STAGE,
+  BASIC_TABLE_COLUMNS.ACTION,
+];
+
+export const LOSS_RECORD_TABLE_COLUMNS: TableColumnProps[] = [
+  BASIC_TABLE_COLUMNS.INDEX,
   {
-    label: '任务状态',
-    prop: 'status',
+    label: '受灾地点',
+    prop: 'affectedArea',
     align: 'center',
-    slot: 'status',
-    width: '120cpx',
   },
   {
-    label: '任务阶段',
-    prop: 'taskStage',
+    label: '受灾物品',
+    prop: 'affectedItems',
     align: 'center',
-    slot: 'taskStage',
   },
   {
-    label: '上报责任人',
-    prop: 'reportPrincipals',
+    label: '上报时间',
+    prop: 'reportTime',
+    align: 'center',
+  },
+  {
+    label: '整改部门',
+    prop: 'department',
+    align: 'center',
+  },
+  {
+    label: '优先级',
+    prop: 'priority',
+    align: 'center',
+  },
+  {
+    label: '整改进度',
+    prop: 'progress',
     align: 'center',
-    slot: 'reportPrincipals',
-    width: '200cpx',
   },
   BASIC_TABLE_COLUMNS.ACTION,
 ];

+ 11 - 0
src/views/disaster/disaster-control/src/constant.ts

@@ -26,3 +26,14 @@ export const TASK_STAGE_OPTIONS = [
 
 export const DEFAULT_PAGE_SIZE = 10;
 export const DISASTER_CONTROL_PAGE_SIZE_CONFIG = [DEFAULT_PAGE_SIZE, ...PAGE_SIZE_CONFIG];
+
+export const LOSS_REPORT_TABS = [
+  {
+    label: '上报任务',
+    value: 'reportTask',
+  },
+  {
+    label: '损失记录',
+    value: 'lossRecord',
+  },
+]; 

+ 19 - 0
src/views/disaster/disaster-control/src/style/collapse.scss

@@ -0,0 +1,19 @@
+@use '@/styles/variables.scss' as *;
+.collapse-container {
+  display: flex;
+  flex-direction: column;
+  gap: 10cpx;
+  width: 100%;
+  overflow-y: auto;
+}
+.empty-container {
+  width: 100%;
+  height: 100%;
+  @include flex-center;
+  flex-direction: column;
+  gap: 10cpx;
+}
+.pagination-container {
+  display: flex;
+  justify-content: flex-end;
+}

+ 6 - 0
src/views/disaster/disaster-control/src/util.ts

@@ -0,0 +1,6 @@
+import { TASK_STAGE_OPTIONS } from './constant';
+
+// 获取任务阶段
+export const getTaskStage = (taskStage: number) => {
+  return TASK_STAGE_OPTIONS.find((item) => item.value === taskStage)?.label;
+};