Przeglądaj źródła

Merge branch 'cc-dev' into 'dev'

修复提测bug 完成灾害处置静态页面

See merge request product-group-fe/sfy-safety-group/sfy-safety!23
陈昶 11 miesięcy temu
rodzic
commit
f79284ce76
37 zmienionych plików z 1403 dodań i 359 usunięć
  1. 160 65
      mock/disaster-control/table.ts
  2. 2 2
      src/api/disaster-control/index.ts
  3. 2 1
      src/components/BasicTable.vue
  4. 3 3
      src/main.scss
  5. 40 154
      src/router/full-routes.ts
  6. 31 8
      src/types/disaster-control/index.ts
  7. 39 9
      src/views/disaster/WorkRecord.md
  8. 15 15
      src/views/disaster/components/User.vue
  9. 1 0
      src/views/disaster/constant/index.ts
  10. 202 47
      src/views/disaster/disaster-control/PageDisposalManagement.vue
  11. 55 0
      src/views/disaster/disaster-control/PageDisposalManagementItem.vue
  12. 50 0
      src/views/disaster/disaster-control/PageDisposalManagementTaskItem.vue
  13. 35 8
      src/views/disaster/disaster-control/PageLossReport.vue
  14. 5 14
      src/views/disaster/disaster-control/src/components/CollapseItem.vue
  15. 96 0
      src/views/disaster/disaster-control/src/components/CreateDisposalManagementItem.vue
  16. 93 0
      src/views/disaster/disaster-control/src/components/CreateDisposalManagementTaskItem.vue
  17. 7 0
      src/views/disaster/disaster-control/src/components/EditDisposalManagementItem.vue
  18. 121 0
      src/views/disaster/disaster-control/src/components/LossRecord.vue
  19. 69 0
      src/views/disaster/disaster-control/src/components/ReportTask.vue
  20. 7 0
      src/views/disaster/disaster-control/src/components/ViewDisposalManagementItem.vue
  21. 7 0
      src/views/disaster/disaster-control/src/components/ViewDisposalManagementTaskItem.vue
  22. 127 0
      src/views/disaster/disaster-control/src/config/form.ts
  23. 34 3
      src/views/disaster/disaster-control/src/config/index.ts
  24. 37 4
      src/views/disaster/disaster-control/src/config/search.ts
  25. 85 21
      src/views/disaster/disaster-control/src/config/table.ts
  26. 31 3
      src/views/disaster/disaster-control/src/constant.ts
  27. 19 0
      src/views/disaster/disaster-control/src/style/collapse.scss
  28. 5 0
      src/views/disaster/disaster-control/src/style/common.scss
  29. 3 0
      src/views/disaster/disaster-control/src/style/item-common.scss
  30. 6 0
      src/views/disaster/disaster-control/src/util.ts
  31. 1 1
      src/views/disaster/disaster-precaution/src/config/form.ts
  32. 2 0
      src/views/disaster/disaster-warning/PageDefenseNotice.vue
  33. 2 0
      src/views/disaster/disaster-warning/PageWarningInfo.vue
  34. 2 0
      src/views/disaster/disaster-warning/src/config/form.ts
  35. 6 0
      src/views/disaster/overview/PageOverview.vue
  36. 3 0
      src/views/disaster/overview/src/components/NotionList.vue
  37. 0 1
      src/views/disaster/style/disaster.scss

+ 160 - 65
mock/disaster-control/table.ts

@@ -33,96 +33,191 @@ const disposalManagementList = {
 const disposalManagementItemList = [
   {
     handleTaskId: 1,
-    id: 1,
-    deptName: '广东省应急管理厅',
-    dueCompleteTime: '2025-05-23 10:00',
-    status: 1,
-    taskStage: 1,
-    reportPrincipals: [
+    disasterReportTaskInfoList: [
       {
         id: 1,
-        realname: '张三',
-        username: '321540',
+        deptName: '广东省应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 1,
+        taskStage: 1,
+        reportPrincipalInfoList: [
+          {
+            id: 1,
+            realname: '张三',
+            username: '321540',
+          },
+          {
+            id: 2,
+            realname: '李四',
+            username: '321541',
+          },
+        ],
       },
       {
         id: 2,
-        realname: '李四',
-        username: '321541',
+        deptName: '湖北省应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 2,
+        taskStage: 1,
+        reportPrincipalInfoList: [
+          {
+            id: 1,
+            realname: 'XXX',
+            username: '321540',
+          },
+        ],
       },
-    ],
-  },
-  {
-    handleTaskId: 1,
-    id: 2,
-    deptName: '湖北省应急管理厅',
-    dueCompleteTime: '2025-05-23 10:00',
-    status: 2,
-    taskStage: 1,
-    reportPrincipals: [
       {
-        id: 1,
-        realname: 'XXX',
-        username: '321540',
-      }
-    ],
-  },
-  {
-    handleTaskId: 1,
-    id: 3,
-    deptName: '海南省应急管理厅',
-    dueCompleteTime: '2025-05-23 10:00',
-    status: 1,
-    taskStage: 2,
-    reportPrincipals: [
+        id: 3,
+        deptName: '海南省应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 1,
+        taskStage: 2,
+        reportPrincipalInfoList: [],
+      },
+      {
+        id: 4,
+        deptName: '湖南省应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 2,
+        taskStage: 3,
+        reportPrincipalInfoList: [
+          {
+            id: 2,
+            realname: '李四',
+            username: '321541',
+          },
+        ],
+      },
+      {
+        id: 5,
+        deptName: '黑龙江省应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 1,
+        taskStage: 3,
+        reportPrincipalInfoList: [
+          {
+            id: 1,
+            realname: '张三',
+            username: '321540',
+          },
+          {
+            id: 2,
+            realname: '李四',
+            username: '321541',
+          },
+        ],
+      },
+      {
+        id: 6,
+        deptName: '北京市应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 2,
+        taskStage: 2,
+        reportPrincipalInfoList: [],
+      },
     ],
   },
   {
-    handleTaskId: 1,
-    id: 4,
-    deptName: '湖南省应急管理厅',
-    dueCompleteTime: '2025-05-23 10:00',
-    status: 2,
-    taskStage: 3,
-    reportPrincipals: [
+    handleTaskId: 2,
+    disasterReportTaskInfoList: [
       {
-        id: 2,
-        realname: '李四',
-        username: '321541',
+        id: 7,
+        deptName: '天津市应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 1,
+        taskStage: 4,
+        reportPrincipalInfoList: [
+          {
+            id: 1,
+            realname: '张三',
+            username: '321540',
+          },
+        ],
+      },
+      {
+        id: 8,
+        deptName: '黑龙江省应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 2,
+        taskStage: 5,
+        reportPrincipalInfoList: [
+          {
+            id: 1,
+            realname: 'XXX',
+            username: '321540',
+          },
+        ],
       },
     ],
   },
   {
-    handleTaskId: 1,
-    id: 5,
-    deptName: '黑龙江省应急管理厅',
-    dueCompleteTime: '2025-05-23 10:00',
-    status: 1,
-    taskStage: 3,
-    reportPrincipals: [
+    handleTaskId: 3,
+    disasterReportTaskInfoList: [
       {
-        id: 1,
-        realname: '张三',
-        username: '321540',
+        id: 9,
+        deptName: '内蒙古应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 1,
+        taskStage: 5,
+        reportPrincipalInfoList: [
+          {
+            id: 1,
+            realname: 'XXX',
+            username: '321540',
+          },
+          {
+            id: 2,
+            realname: 'XXX2',
+            username: '321541',
+          },
+          {
+            id: 3,
+            realname: 'XXX3',
+            username: '321542',
+          },
+        ],
       },
       {
-        id: 2,
-        realname: '李四',
-        username: '321541',
+        id: 10,
+        deptName: '河北省应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 2,
+        taskStage: 5,
+        reportPrincipalInfoList: [],
+      },
+      {
+        id: 11,
+        deptName: '湖南省应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 2,
+        taskStage: 4,
+        reportPrincipalInfoList: [],
       },
     ],
   },
   {
-    handleTaskId: 1,
-    id: 6,
-    deptName: '北京市应急管理厅',
-    dueCompleteTime: '2025-05-23 10:00',
-    status: 2,
-    taskStage: 2,
-    reportPrincipals: [
+    handleTaskId: 4,
+    disasterReportTaskInfoList: [],
+  },
+  {
+    handleTaskId: 5,
+    disasterReportTaskInfoList: [
+      {
+        id: 12,
+        deptName: 'XXX应急管理厅',
+        dueCompleteTime: '2025-05-23 10:00',
+        status: 1,
+        taskStage: 2,
+        reportPrincipalInfoList: [],
+      },
     ],
   },
+  {
+    handleTaskId: 6,
+    disasterReportTaskInfoList: [],
+  },
 ];
-
 export default [
   {
     url: '/safety_mock_api/disasterHandle/queryDisasterHandleTaskPage',

+ 2 - 2
src/api/disaster-control/index.ts

@@ -2,7 +2,7 @@ import { http } from '@/utils/http/axios/mock';
 import type {
   DisposalManagementListResponse,
   DisposalManagementListQuery,
-  DisposalManagementListItemQuery,
+  DisposalManagementTableQuery,
   DisposalManagementTableResponse,
 } from '@/types/disaster-control';
 import type { QueryPageResponse, QueryPageRequest } from '@/types/disaster';
@@ -17,7 +17,7 @@ export const getDisasterControlCollapseData = (query: QueryPageRequest<DisposalM
   });
 };
 
-export const getDisasterControlTableData = (query: DisposalManagementListItemQuery) => {
+export const getDisasterControlTableData = (query: DisposalManagementTableQuery) => {
   return http.request<DisposalManagementTableResponse[]>({
     url: '/disasterHandle/queryDisasterReportTask',
     method: 'post',

+ 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;

+ 3 - 3
src/main.scss

@@ -14,8 +14,9 @@
     background-color: transparent;
   }
 }
-html {
-  font-size: 16cpx;
+
+.el-button {
+  font-size: 14cpx !important;
 }
 
 body {
@@ -27,7 +28,6 @@ body {
   position: static !important;
 }
 
-
 .flex {
   display: flex;
 }

+ 40 - 154
src/router/full-routes.ts

@@ -304,6 +304,46 @@ export const disasterPreventionRoute = {
           path: 'disposal-management',
           redirect: '',
         },
+        {
+          component: '/disaster/disaster-control/PageDisposalManagementTaskItem',
+          id: 1041,
+          meta: {
+            activeMenu: '/disaster-prevention/disaster-control/disposal-management',
+            alwaysShow: false,
+            frameSrc: '',
+            hidden: false,
+            icon: '',
+            isFrame: 0,
+            isRoot: false,
+            noCache: false,
+            query: '',
+            title: '处置管理详情(任务项)',
+          },
+          name: 'disaster-control-disposal-management-task-item',
+          parentId: 1027,
+          path: 'disposal-management-task-item',
+          redirect: '',
+        },
+        {
+          component: '/disaster/disaster-control/PageDisposalManagementItem',
+          id: 1042,
+          meta: {
+            activeMenu: '/disaster-prevention/disaster-control/disposal-management',
+            alwaysShow: false,
+            frameSrc: '',
+            hidden: false,
+            icon: '',
+            isFrame: 0,
+            isRoot: false,
+            noCache: false,
+            query: '',
+            title: '处置管理详情(列表项)',
+          },
+          name: 'disaster-control-disposal-management-item',
+          parentId: 1027,
+          path: 'disposal-management-item',
+          redirect: '',
+        },
         {
           component: '/disaster/disaster-control/PageLossReport',
           id: 1039,
@@ -385,160 +425,6 @@ export const disasterPreventionRoute = {
   redirect: '',
 };
 
-// export const userRoutesOld: AppRouteRecordRaw =
-//   /**
-//    * 用户管理
-//    */
-//   {
-//     path: '/user',
-//     name: 'User',
-//     component: 'LAYOUT',
-//     meta: {
-//       icon: 'UserOutlined',
-//       title: '用户管理',
-//     },
-//     children: [
-//       {
-//         // 账号管理
-//         path: 'account',
-//         name: 'UserAccount',
-//         component: '/system/user/user',
-//         meta: {
-//           icon: '',
-//           title: '账号管理',
-//         },
-//       },
-//       {
-//         // 角色管理
-//         path: 'role',
-//         name: 'UserRole',
-//         component: '/system/role/role',
-//         meta: {
-//           icon: '',
-//           title: '角色管理',
-//         },
-//       },
-//       {
-//         // 组织管理
-//         path: 'department',
-//         name: 'UserDepartment',
-//         component: '/auth/dept/dept',
-//         meta: {
-//           icon: '',
-//           title: '组织管理',
-//         },
-//       },
-//       {
-//         // 岗位管理 (目前不需要)
-//         path: 'post',
-//         name: 'UserPost',
-//         component: '/auth/post/post',
-//         meta: {
-//           icon: '',
-//           title: '岗位管理',
-//         },
-//       },
-//     ],
-//   };
-
-// export const systemRoutesOld =
-//   /**
-//    * 系统管理 (只有超管可见)
-//    */
-//   {
-//     path: '/system',
-//     name: 'System',
-//     component: 'MENU_LAYOUT',
-//     meta: {
-//       icon: 'OptionsSharp',
-//       title: '系统管理',
-//     },
-//     redirect: 'SystemMenu',
-//     children: [
-//       {
-//         // 租户管理
-//         path: 'tenant',
-//         name: 'SystemTenant',
-//         component: '/system/tenant/tenant',
-//         meta: {
-//           icon: '',
-//           title: '租户管理',
-//         },
-//       },
-//       {
-//         // 菜单管理
-//         path: 'menu',
-//         name: 'SystemMenu',
-//         component: '/system/menu/menu',
-//         meta: {
-//           icon: '',
-//           title: '菜单管理',
-//         },
-//       },
-//       {
-//         // 权限管理
-//         path: 'permission',
-//         name: 'SystemPermission',
-//         component: '/system/permssion/PagePermission',
-//         meta: {
-//           icon: '',
-//           title: '权限管理',
-//         },
-//       },
-//       {
-//         // 权限管理
-//         path: 'comments',
-//         name: 'SystemComments',
-//         component: '/system/comments/PageCommentsManage',
-//         meta: {
-//           icon: '',
-//           title: '评论管理',
-//         },
-//       },
-//       {
-//         // 意见反馈
-//         path: 'feedback',
-//         name: 'SystemFeedback',
-//         component: '/feedback/feedback',
-//         meta: {
-//           icon: '',
-//           title: '意见反馈',
-//         },
-//       },
-//       {
-//         // 反馈处理 。意见反馈的二级页面。菜单不可见!!!
-//         path: 'feedback-handle',
-//         name: 'SystemFeedbackHandle',
-//         component: '/feedback/handleFeedback',
-//         meta: {
-//           icon: '',
-//           title: '反馈处理',
-//           activeMenu: 'SystemFeedback',
-//         },
-//       },
-//       // {
-//       //   // 字典管理 (暂时用不到)
-//       //   path: 'dictionary',
-//       //   name: 'SystemDictionary',
-//       //   component: '/system/dictionary/dictionary',
-//       //   meta: {
-//       //     icon: '',
-//       //     title: '字典管理',
-//       //   },
-//       // },
-//       {
-//         // 日志管理
-//         path: 'log',
-//         name: 'SystemLog',
-//         component: '/system/log/log',
-//         meta: {
-//           icon: '',
-//           title: '日志管理',
-//         },
-//       },
-//     ],
-//   };
-
 /** 平台管理 */
 export const platformRoutes = {
   path: '/platform',

+ 31 - 8
src/types/disaster-control/index.ts

@@ -1,25 +1,48 @@
-import type { UserInfo } from '@/types/push-object';
+import type { PersonGroupItem } from '@/types/person-group/type';
+
 export interface DisposalManagementListQuery {
   reporterId?: number;
 }
 
-export interface DisposalManagementListItemQuery extends DisposalManagementListQuery {
+export interface LossReportReportTaskQuery {
+  taskStage?: string;
+}
+
+export interface DisposalManagementTableQuery extends DisposalManagementListQuery, LossReportReportTaskQuery {
   handleTaskIds: number[];
   reportDeptIds?: number[];
   status?: string;
-  taskStage?: string;
 }
+
 export interface DisposalManagementListResponse {
   id: number;
   taskName: string;
-  tableData: DisposalManagementTableResponse[];
 }
 
-export interface DisposalManagementTableResponse {
+export interface DisposalManagementCollapseListResponse<T> extends DisposalManagementListResponse {
+  tableData: T[];
+}
+
+export interface disasterReportTaskInfoListResponse {
   id: number;
   deptName: string;
   dueCompleteTime: string;
-  status: string;
-  taskStage: string;
-  reportPrincipals: UserInfo[];
+  status: number;
+  taskStage: number;
+  reportPrincipalInfoList: PersonGroupItem[];
+}
+
+export interface DisposalManagementTableResponse {
+  handleTaskId: number;
+  disasterReportTaskInfoList: disasterReportTaskInfoListResponse[];
+}
+
+export interface DisposalManagementRuleForm {
+  taskName: string;
+  deptIds: number[];
+  dueCompleteTime: string;
+  reportRequirement: string;
+  userGroupList: number[];
+  isPush: number | null;
+  realname: string;
 }

+ 39 - 9
src/views/disaster/WorkRecord.md

@@ -1,42 +1,72 @@
 ### 25/5/13
+
 ##### 灾害防范模块
+
 - [x] 准备通用模块-树结构选择
+
 ##### 灾害预警-预警信息
+
 - [x] 不确定后端能否拿到数据 添加页面先不做
+
 ##### 灾害预警-防御通知
-- [x]  创建灾害防御通知页面
-- [x]  提取公共scss(新建页面)
-- [x]  文件上传组件(是否通用?提取公共组件)
-- [x]  文件在线预览组件、文件在线下载组件
+
+- [x] 创建灾害防御通知页面
+- [x] 提取公共 scss(新建页面)
+- [x] 文件上传组件(是否通用?提取公共组件)
+- [x] 文件在线预览组件、文件在线下载组件
 
 ### 25/5/14
+
 #### 灾害防范模块
-- [x] 准备通用hook-form表单
+
+- [x] 准备通用 hook-form 表单
+
 #### 灾害预警模块
+
 - [x] 完成所有静态页面开发
 
 ### 25/5/15
+
 ### 灾害预警模块
-- [x] search引用配置项来开发
-- [x] form引用配置来开发
+
+- [x] search 引用配置项来开发
+- [x] form 引用配置来开发
 - [x] 预警信息做添加页面,将表单数据进行拆分(通用项和定制项)
 - [x] 完成灾害预警模块
 
 ### 25/5/16
+
 ### 预防检查模块
+
 - [x] 任务管理静态页面完成
 - [x] 任务模板页面完成
 - [ ] 任务执行页面完成
 
 ### 25/5/20
+
 ### 完成灾害预警 准备提测
 
 ### 25/5/22
+
 ### 预防检查模块
+
 - [x] 任务管理模块开发完成
 - [ ] 任务执行做到看模板情况
 - [ ] 任务模板的接口、数据结构重构,组件重构
+
 ### 灾害防范模块
-- [x] 有许多公用逻辑可以抽成hook和util(后续优化)
+
+- [x] 有许多公用逻辑可以抽成 hook 和 util(后续优化)
 - [x] 有很多字段和后端不一样,时间来不及修改(后续优化)
-- [x] 有很多公共组件可以在进行二次封装,后续完成后再进行优化
+- [x] 有很多公共组件可以在进行二次封装,后续完成后再进行优化
+
+### 25/5/26
+
+### 灾害处置模块
+
+- [x] 完成基础任务 CollapseItem 组件
+
+### 灾害处置模块-处置管理
+
+- [x] 完成处置管理 Table 页面,接口对完
+- [ ] 完成处置管理表单页面,接口对完

+ 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',
 };

+ 202 - 47
src/views/disaster/disaster-control/PageDisposalManagement.vue

@@ -6,8 +6,14 @@
     <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"
+            @click="handleCreateDisposalManagement(FORM_OPERATE_TYPE.TASK_ITEM)"
+          >
+            创建灾害处置任务
           </el-button>
           <Search
             :searchConfig="DISPOSAL_MANAGEMENT_SEARCH_CONFIG"
@@ -15,13 +21,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>
@@ -33,8 +49,51 @@
               :name="item.taskName"
               :defaultOpen="item.id === 1"
             >
+              <template #viewOperation>
+                <el-tooltip
+                  :content="isViewTask(item.tableData[0].disasterReportTaskInfoList) ? '查看' : '任务尚未发布'"
+                  placement="top"
+                  effect="light"
+                >
+                  <img
+                    :src="ViewDocument"
+                    :class="[
+                      'collapse-item__icon',
+                      { 'collapse-item__icon--disabled': !isViewTask(item.tableData[0].disasterReportTaskInfoList) },
+                    ]"
+                    @click.stop="isViewTask(item.tableData[0].disasterReportTaskInfoList) && handleViewTask(item.id)"
+                  />
+                </el-tooltip>
+              </template>
+              <template #batchOperation v-if="disposalManagementPermissions">
+                <el-button
+                  type="primary"
+                  v-if="isBatchRelease(item.tableData[0].disasterReportTaskInfoList)"
+                  @click.stop="handleBatchRelease(item.tableData[0].disasterReportTaskInfoList)"
+                  >发布
+                </el-button>
+                <el-button
+                  type="primary"
+                  v-if="isBatchWithdraw(item.tableData[0].disasterReportTaskInfoList)"
+                  @click.stop="handleBatchWithdraw(item.tableData[0].disasterReportTaskInfoList)"
+                  >撤回
+                </el-button>
+                <el-button
+                  type="primary"
+                  v-if="isBatchDelete(item.tableData[0].disasterReportTaskInfoList)"
+                  @click.stop="handleBatchDelete(item.id)"
+                  >删除
+                </el-button>
+              </template>
               <template #main-table>
-                <BasicTable :tableData="item.tableData" :tableConfig="tableConfig">
+                <el-button
+                  type="primary"
+                  :icon="Plus"
+                  class="main-table__button"
+                  @click="handleCreateDisposalManagement(FORM_OPERATE_TYPE.TABLE_ITEM, item.taskName)"
+                  >新增</el-button
+                >
+                <BasicTable :tableData="item.tableData[0].disasterReportTaskInfoList" :tableConfig="tableConfig">
                   <template #status="scope">
                     <div class="active-status--div">
                       <div
@@ -45,30 +104,42 @@
                     </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">
+                    <p v-for="user in scope.row.reportPrincipalInfoList" :key="user.id">
                       {{ user.realname }}({{ user.username }})
                     </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 ||
+                        (TASK_STAGE.OVERDUE && disposalManagementPermissions)
+                      "
+                    />
+                    <ActionButton
+                      text="删除"
+                      :popconfirm="{
+                        title: '确定删除吗?',
+                      }"
+                      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 +169,39 @@
   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 type { disasterReportTaskInfoListResponse } from '@/types/disaster-control';
   import { DEFAULT_PAGE_SIZE, DISASTER_CONTROL_PAGE_SIZE_CONFIG } from './src/constant';
-  import type { DisposalManagementListResponse } from '@/types/disaster-control';
+  import type {
+    DisposalManagementCollapseListResponse,
+    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 { useRouter } from 'vue-router';
   import Empty from 'assets/images/empty@1X.png';
+  import ViewDocument from './src/svg/view-document.svg';
+  import { FORM_OPERATE_TYPE } from './src/constant';
+  import { useUserInfoHook } from '@/views/disaster/hooks/userInfo';
+
+  const { permissions } = useUserInfoHook();
 
   const firstLevelDepts = ref<DeptTree[]>([]);
   const searchData = reactive({
@@ -125,27 +215,43 @@
   const total = ref(0);
 
   const collapseLoading = ref(false);
-  const collapseList = ref<DisposalManagementListResponse[]>([]);
+  const collapseList = ref<DisposalManagementCollapseListResponse<DisposalManagementTableResponse>[]>([]);
+  const disposalManagementPermissions = ref(false);
 
-  const { tableConfig } = useTableConfig(DISPOSAL_MANAGEMENT_TABLE_COLUMNS, TABLE_OPTIONS, false);
+  const { tableConfig } = useTableConfig(DISPOSAL_MANAGEMENT_TABLE_COLUMNS, DISPOSAL_MANAGEMENT_TABLE_OPTIONS, false);
 
-  const formatTaskStage = (taskStage: number) => {
-    return TASK_STAGE_OPTIONS.find((item) => item.value === taskStage)?.label;
-  };
-
-  const handleSizeChange = (size: number) => {
+  const handleSizeChange = async (size: number) => {
     pageSize.value = size;
+    await getDisposalData();
+    await getDisposalTableData();
   };
 
-  const handleCurrentChange = (page: number) => {
+  const handleCurrentChange = async (page: number) => {
     currentPage.value = page;
+    await getDisposalData();
+    await getDisposalTableData();
   };
 
   const handleSearch = () => {
-    console.log(searchData);
+    getDisposalTableData();
   };
 
   const taskIds = ref<number[]>([]);
+  const router = useRouter();
+  const Task_RouterName = 'disaster-control-disposal-management-task-item';
+  const Table_RouterName = 'disaster-control-disposal-management-item';
+  const handleCreateDisposalManagement = (type: FORM_OPERATE_TYPE, taskName?: string) => {
+    console.log(type);
+    const routerName = type === FORM_OPERATE_TYPE.TASK_ITEM ? Task_RouterName : Table_RouterName;
+    router.push({
+      name: routerName,
+      query: {
+        operate: 'create',
+        taskName: taskName,
+      },
+    });
+  };
+
   const getDisposalData = async () => {
     collapseLoading.value = true;
     const res = await getDisasterControlCollapseData({
@@ -153,11 +259,16 @@
       pageSize: pageSize.value,
       queryParam: {},
     });
-    collapseList.value = res.records;
-    collapseList.value.forEach((item) => {
-      item.tableData = [];
-    });
-    taskIds.value = res.records.map((item) => item.id);
+    collapseList.value = res.records.map((item) => ({
+      ...item,
+      tableData: [
+        {
+          handleTaskId: item.id,
+          disasterReportTaskInfoList: [],
+        },
+      ],
+    }));
+    taskIds.value = collapseList.value.map((item) => item.id);
     total.value = res.totalRow;
     collapseLoading.value = false;
   };
@@ -169,21 +280,65 @@
       ...searchData,
     });
     collapseList.value.forEach((item) => {
-      item.tableData = res;
+      item.tableData = res.filter((tableItem) => tableItem.handleTaskId === item.id);
     });
     tableConfig.loading = false;
   };
 
+  const isViewTask = (disasterReportTaskInfoList: disasterReportTaskInfoListResponse[]) => {
+    return disasterReportTaskInfoList.some((item) => item.status === ACTIVE_STATUS.ACTIVE);
+  };
+
+  const isBatchRelease = (disasterReportTaskInfoList: disasterReportTaskInfoListResponse[]) => {
+    return disasterReportTaskInfoList.some((item) => item.status === ACTIVE_STATUS.NOT_EFFECTIVE);
+  };
+
+  const isBatchWithdraw = (disasterReportTaskInfoList: disasterReportTaskInfoListResponse[]) => {
+    return 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 handleBatchRelease = (disasterReportTaskInfoList: disasterReportTaskInfoListResponse[]) => {
+    const batchReleaseIds = disasterReportTaskInfoList
+      .filter((item) => item.taskStage === TASK_STAGE.TO_BE_RELEASED)
+      .map((item) => item.id);
+    console.log(batchReleaseIds);
+  };
+
+  const handleBatchWithdraw = (disasterReportTaskInfoList: disasterReportTaskInfoListResponse[]) => {
+    const batchWithdrawIds = disasterReportTaskInfoList
+      .filter((item) => item.taskStage === TASK_STAGE.TO_BE_REPORTED || item.taskStage === TASK_STAGE.OVERDUE)
+      .map((item) => item.id);
+    console.log(batchWithdrawIds);
+  };
+
+  const handleBatchDelete = (id: number) => {
+    console.log('当前任务ID' + id);
+  };
+
   onMounted(async () => {
     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 +348,23 @@
     }
   }
   .collapse-container {
-    display: flex;
-    flex-direction: column;
-    gap: 10cpx;
-    width: 100%;
-    height: calc(63vh - 15cpx);
-    max-height: calc(63vh - 15cpx);
-    overflow-y: auto;
+    &--permission {
+      height: $collapse-container-height-permission;
+      max-height: $collapse-container-height-permission;
+    }
+    &--default {
+      height: $collapse-container-height-default;
+      max-height: $collapse-container-height-default;
+    }
   }
-  .empty-container {
-    width: 100%;
-    height: 100%;
-    @include flex-center;
-    flex-direction: column;
-    gap: 10cpx;
+  .collapse-item__icon {
+    width: 20cpx;
+    &--disabled {
+      cursor: not-allowed;
+      opacity: 0.5;
+    }
   }
-  .pagination-container {
-    display: flex;
-    justify-content: flex-end;
+  .main-table__button {
+    margin-bottom: 10cpx;
   }
 </style>

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

@@ -0,0 +1,55 @@
+<template>
+  <div class="disaster-precaution-container">
+    <header class="disaster-precaution-container__header">
+      <img :src="BackIcon" alt="back" class="back-icon" @click="router.back()" />
+      <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
+    </header>
+    <main class="disaster-precaution-container__main">
+      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+    </main>
+    <footer class="disaster-precaution-container__footer" v-if="operate">
+      <el-button @click="router.back()">取消</el-button>
+      <el-button type="primary" @click="submit">提交</el-button>
+    </footer>
+    <UploadLoading :form-loading="formLoading" v-if="formLoading" />
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { ref, computed, defineAsyncComponent } from 'vue';
+  import UploadLoading from '@/components/UploadLoading.vue';
+  import { useRoute, useRouter } from 'vue-router';
+  import BackIcon from 'assets/svg/back.svg';
+  import { ElMessage } from 'element-plus';
+  const router = useRouter();
+  const route = useRoute();
+  const operate = route.query.operate;
+  const id = route.query.id;
+  const headerTitle = computed(() => {
+    const fixedTitle = '灾害处置任务';
+    if (operate === 'create') {
+      return `创建${fixedTitle}`;
+    } else if (operate === 'edit') {
+      return `编辑${fixedTitle}`;
+    }
+    return `查看${fixedTitle}`;
+  });
+  const dynamicComponent = computed(() => {
+    if (operate === 'create') {
+      return defineAsyncComponent(() => import('./src/components/CreateDisposalManagementItem.vue'));
+    } else if (operate === 'edit') {
+      return defineAsyncComponent(() => import('./src/components/EditDisposalManagementItem.vue'));
+    } else {
+      return defineAsyncComponent(() => import('./src/components/ViewDisposalManagementItem.vue'));
+    }
+  });
+  const dynamicComponentRef = ref();
+  const formLoading = ref(false);
+  const submit = async () => {
+  };
+</script>
+
+<style lang="scss" scoped>
+  @use '../style/disaster.scss' as *;
+  @use './src/style/common.scss' as *;
+</style>

+ 50 - 0
src/views/disaster/disaster-control/PageDisposalManagementTaskItem.vue

@@ -0,0 +1,50 @@
+<template>
+  <div class="disaster-precaution-container">
+    <header class="disaster-precaution-container__header">
+      <img :src="BackIcon" alt="back" class="back-icon" @click="router.back()" />
+      <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
+    </header>
+    <main class="disaster-precaution-container__main">
+      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+    </main>
+    <footer class="disaster-precaution-container__footer" v-if="operate">
+      <el-button @click="router.back()">取消</el-button>
+      <el-button type="primary" @click="submit">提交</el-button>
+    </footer>
+    <UploadLoading :form-loading="formLoading" v-if="formLoading" />
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { ref, computed, defineAsyncComponent } from 'vue';
+  import UploadLoading from '@/components/UploadLoading.vue';
+  import { useRoute, useRouter } from 'vue-router';
+  import BackIcon from 'assets/svg/back.svg';
+  import { ElMessage } from 'element-plus';
+  const router = useRouter();
+  const route = useRoute();
+  const operate = route.query.operate;
+  const id = route.query.id;
+  const headerTitle = computed(() => {
+    const fixedTitle = '灾害处置任务';
+    if (operate === 'create') {
+      return `创建${fixedTitle}`;
+    }
+    return `查看${fixedTitle}`;
+  });
+  const dynamicComponent = computed(() => {
+    if (operate === 'create') {
+      return defineAsyncComponent(() => import('./src/components/CreateDisposalManagementTaskItem.vue'));
+    } else {
+      return defineAsyncComponent(() => import('./src/components/ViewDisposalManagementTaskItem.vue'));
+    }
+  });
+  const dynamicComponentRef = ref();
+  const formLoading = ref(false);
+  const submit = async () => {};
+</script>
+
+<style lang="scss" scoped>
+  @use '../style/disaster.scss' as *;
+  @use './src/style/common.scss' as *;
+</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 !important;
+  }
+</style>

+ 5 - 14
src/views/disaster/disaster-control/src/components/CollapseItem.vue

@@ -1,17 +1,15 @@
 <template>
   <div class="collapse-item">
-    <div class="collapse-item__header">
-      <div class="collapse-item__header--left" @click="toggle">
+    <div class="collapse-item__header" @click="toggle">
+      <div class="collapse-item__header--left">
         <el-icon class="collapse-item__icon">
           <component :is="isOpen ? ArrowUp : ArrowDown" />
         </el-icon>
         <span>{{ name }}</span>
-        <img :src="ViewDocument" alt="查看" class="collapse-item__icon" @click.stop="handleViewDocument" />
+        <slot name="viewOperation" />
       </div>
       <div class="collapse-item__header--right">
-        <el-button type="primary">发布</el-button>
-        <el-button type="primary">撤回</el-button>
-        <el-button type="primary">删除</el-button>
+        <slot name="batchOperation" />
       </div>
     </div>
     <div v-show="isOpen" class="collapse-item__main">
@@ -23,7 +21,6 @@
 <script lang="ts" setup>
   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 isOpen = ref(false);
   const toggle = () => {
@@ -33,9 +30,6 @@
     if (!props.defaultOpen) return;
     isOpen.value = true;
   };
-  const handleViewDocument = () => {
-    console.log('查看');
-  };
   onMounted(() => {
     openFirstCollapseItem();
   });
@@ -56,17 +50,14 @@
       font-size: 20cpx;
       font-weight: 550;
       color: rgba($text-color, 0.85);
+      cursor: pointer;
       &--left {
         @include flex-center;
         gap: 20cpx;
-        cursor: pointer;
       }
     }
     &__main {
       padding-top: 20cpx;
     }
-    &__icon {
-      width: 20cpx;
-    }
   }
 </style>

+ 96 - 0
src/views/disaster/disaster-control/src/components/CreateDisposalManagementItem.vue

@@ -0,0 +1,96 @@
+<template>
+  <div class="info-container">
+    <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig">
+      <template #deptIds>
+        <el-select
+          v-model="ruleFormData.deptIds"
+          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>
+      <template #userGroupList>
+        <GroupSelect v-model="ruleFormData.userGroupList" :groupOptions="groupOptions" />
+      </template>
+      <template #isPush>
+        <el-radio-group v-model="ruleFormData.isPush">
+          <el-radio :label="true">是</el-radio>
+          <el-radio :label="false">否</el-radio>
+        </el-radio-group>
+      </template>
+    </BasicForm>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import BasicForm from '@/components/BasicForm.vue';
+  import GroupSelect from '@/views/disaster/components/GroupSelect.vue';
+  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
+  import {
+    DISPOSAL_MANAGEMENT_ITEM_FROM_CONFIG_CREATE,
+    DISPOSAL_MANAGEMENT_TASK_FROM_DATA,
+    DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_CREATE,
+  } from '../config';
+  import { onMounted, ref } from 'vue';
+  import { useUserInfoHook } from '@/views/disaster/hooks/userInfo';
+  import type { DisposalManagementRuleForm } from '@/types/disaster-control';
+  import type { DeptTree } from '@/types/dept/type';
+  import type { UserGroupOption } from '@/types/person-group/type';
+  import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
+  import { getAllDepartments } from '@/api/auth/dept';
+  import { getAllUserGroup } from '@/api/system/person-group';
+  import { useRoute } from 'vue-router';
+
+  const { realname } = useUserInfoHook();
+  const route = useRoute();
+  const taskName = route.query.taskName as string;
+  const basicFormRef = ref<InstanceType<typeof BasicForm>>();
+
+  const firstLevelDepts = ref<DeptTree[]>([]);
+  const groupOptions = ref<UserGroupOption[]>([]);
+
+  const { ruleFormConfig, ruleFormData, formRules, cloneRuleFormData, beforeRouteLeave } =
+    useFormConfigHook<DisposalManagementRuleForm>(
+      DISPOSAL_MANAGEMENT_ITEM_FROM_CONFIG_CREATE,
+      DISPOSAL_MANAGEMENT_TASK_FROM_DATA,
+      DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_CREATE,
+    );
+
+  const handleValidate = async () => {
+    if (!basicFormRef.value) return;
+    const parentValidateResult = await basicFormRef.value.validateForm();
+    return parentValidateResult;
+  };
+  const getFormData = () => {
+    cloneRuleFormData();
+    return ruleFormData;
+  };
+  const getDeptList = async () => {
+    const res = await getAllDepartments();
+    firstLevelDepts.value = formatDeptTree(res);
+  };
+  const getUserGroupList = async () => {
+    const res = await getAllUserGroup();
+    groupOptions.value = res.groupVOList;
+  };
+  defineExpose({
+    handleValidate,
+    getFormData,
+  });
+  onMounted(() => {
+    ruleFormData.realname = realname;
+    ruleFormData.taskName = taskName;
+    getDeptList();
+    getUserGroupList();
+    cloneRuleFormData();
+    beforeRouteLeave();
+  });
+</script>
+
+<style scoped lang="scss">
+  @use '@/views/disaster/style/info-container.scss' as *;
+  @use '../style/item-common.scss' as *;
+</style>

+ 93 - 0
src/views/disaster/disaster-control/src/components/CreateDisposalManagementTaskItem.vue

@@ -0,0 +1,93 @@
+<template>
+  <div class="info-container">
+    <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig">
+      <template #deptIds>
+        <el-select
+          v-model="ruleFormData.deptIds"
+          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>
+      <template #userGroupList>
+        <GroupSelect v-model="ruleFormData.userGroupList" :groupOptions="groupOptions" />
+      </template>
+      <template #isPush>
+        <el-radio-group v-model="ruleFormData.isPush">
+          <el-radio :label="true">是</el-radio>
+          <el-radio :label="false">否</el-radio>
+        </el-radio-group>
+      </template>
+    </BasicForm>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import BasicForm from '@/components/BasicForm.vue';
+  import GroupSelect from '@/views/disaster/components/GroupSelect.vue';
+  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
+  import {
+    DISPOSAL_MANAGEMENT_TASK_FROM_CONFIG,
+    DISPOSAL_MANAGEMENT_TASK_FROM_DATA,
+    DISPOSAL_MANAGEMENT_TASK_FROM_RULES,
+  } from '../config';
+  import { onMounted, ref } from 'vue';
+  import { useUserInfoHook } from '@/views/disaster/hooks/userInfo';
+  import type { DisposalManagementRuleForm } from '@/types/disaster-control';
+  import type { DeptTree } from '@/types/dept/type';
+  import type { UserGroupOption } from '@/types/person-group/type';
+  import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
+  import { getAllDepartments } from '@/api/auth/dept';
+  import { getAllUserGroup } from '@/api/system/person-group';
+
+  const { realname } = useUserInfoHook();
+
+  const basicFormRef = ref<InstanceType<typeof BasicForm>>();
+
+  const firstLevelDepts = ref<DeptTree[]>([]);
+  const groupOptions = ref<UserGroupOption[]>([]);
+
+  const { ruleFormConfig, ruleFormData, formRules, cloneRuleFormData, beforeRouteLeave } =
+    useFormConfigHook<DisposalManagementRuleForm>(
+      DISPOSAL_MANAGEMENT_TASK_FROM_CONFIG,
+      DISPOSAL_MANAGEMENT_TASK_FROM_DATA,
+      DISPOSAL_MANAGEMENT_TASK_FROM_RULES,
+    );
+
+  const handleValidate = async () => {
+    if (!basicFormRef.value) return;
+    const parentValidateResult = await basicFormRef.value.validateForm();
+    return parentValidateResult;
+  };
+  const getFormData = () => {
+    cloneRuleFormData();
+    return ruleFormData;
+  };
+  const getDeptList = async () => {
+    const res = await getAllDepartments();
+    firstLevelDepts.value = formatDeptTree(res);
+  };
+  const getUserGroupList = async () => {
+    const res = await getAllUserGroup();
+    groupOptions.value = res.groupVOList;
+  };
+  defineExpose({
+    handleValidate,
+    getFormData,
+  });
+  onMounted(() => {
+    ruleFormData.realname = realname;
+    getDeptList();
+    getUserGroupList();
+    cloneRuleFormData();
+    beforeRouteLeave();
+  });
+</script>
+
+<style scoped lang="scss">
+  @use '@/views/disaster/style/info-container.scss' as *;
+  @use '../style/item-common.scss' as *;
+</style>

+ 7 - 0
src/views/disaster/disaster-control/src/components/EditDisposalManagementItem.vue

@@ -0,0 +1,7 @@
+<template>
+  <div> this is createDisposalManagementItem page </div>
+</template>
+
+<script lang="ts" setup></script>
+
+<style lang="scss" scoped></style>

+ 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>

+ 7 - 0
src/views/disaster/disaster-control/src/components/ViewDisposalManagementItem.vue

@@ -0,0 +1,7 @@
+<template>
+  <div> this is createDisposalManagementItem page </div>
+</template>
+
+<script lang="ts" setup></script>
+
+<style lang="scss" scoped></style>

+ 7 - 0
src/views/disaster/disaster-control/src/components/ViewDisposalManagementTaskItem.vue

@@ -0,0 +1,7 @@
+<template>
+  <div> this is viewDisposalManagementTaskItem page </div>
+</template>
+
+<script lang="ts" setup></script>
+
+<style lang="scss" scoped></style>

+ 127 - 0
src/views/disaster/disaster-control/src/config/form.ts

@@ -0,0 +1,127 @@
+/**
+ * 灾害预警信息表单配置
+ */
+import type { FormConfig } from '@/types/basic-form';
+// 通用表单信息
+const BASIC_FROM_CONFIG = {};
+
+// 通用处置管理表单信息
+const DISPOSAL_MANAGEMENT_BASIC_FROM_CONFIG: FormConfig[] = [
+  {
+    label: '应完成上报时间',
+    prop: 'dueCompleteTime',
+    component: 'ElDatePicker',
+    componentProps: {
+      placeholder: '请选择应完成上报时间',
+      type: 'datetime',
+      format: 'YYYY-MM-DD HH:mm:ss',
+      dateFormat: 'MMM DD, YYYY',
+      timeFormat: 'HH:mm:ss',
+      valueFormat: 'YYYY-MM-DD HH:mm:ss',
+    },
+  },
+  {
+    label: '上报要求',
+    prop: 'reportRequirement',
+    component: 'ElInput',
+    componentProps: {
+      type: 'textarea',
+      rows: 5,
+      placeholder: '请输入上报要求',
+      maxlength: 1000,
+      showWordLimit: true,
+    },
+  },
+  {
+    label: '上报人员',
+    prop: 'userGroupList',
+    slot: 'userGroupList',
+  },
+  {
+    label: '是否推送',
+    prop: 'isPush',
+    slot: 'isPush',
+  },
+  {
+    label: '创建人',
+    prop: 'realname',
+    component: 'ElInput',
+    componentProps: {
+      disabled: true,
+    },
+  },
+];
+
+// 处置管理表单信息(任务项)
+export const DISPOSAL_MANAGEMENT_TASK_FROM_CONFIG: FormConfig[] = [
+  {
+    label: '任务名称',
+    prop: 'taskName',
+    component: 'ElInput',
+    componentProps: {
+      placeholder: '请输入任务名称',
+    },
+  },
+  {
+    label: '上报部门',
+    prop: 'deptIds',
+    slot: 'deptIds',
+  },
+  ...DISPOSAL_MANAGEMENT_BASIC_FROM_CONFIG,
+];
+
+// 处置管理表单信息(列表项)
+export const DISPOSAL_MANAGEMENT_ITEM_FROM_CONFIG_CREATE: FormConfig[] = [
+  {
+    label: '任务名称',
+    prop: 'taskName',
+    component: 'ElInput',
+    componentProps: {
+      placeholder: '请输入任务名称',
+      disabled: true,
+    },
+  },
+  {
+    label: '上报部门',
+    prop: 'deptIds',
+    slot: 'deptIds',
+  },
+  ...DISPOSAL_MANAGEMENT_BASIC_FROM_CONFIG,
+];
+
+// 通用表单数据
+const BASIC_FROM_DATA = {};
+const DISPOSAL_MANAGEMENT_BASIC_FROM_DATA = {
+  taskName: '',
+  deptIds: [],
+  dueCompleteTime: '',
+  reportRequirement: '',
+  userGroupList: [],
+  isPush: null,
+  realname: '',
+};
+export const DISPOSAL_MANAGEMENT_TASK_FROM_DATA = {
+  ...DISPOSAL_MANAGEMENT_BASIC_FROM_DATA,
+};
+
+// 通用表单规则
+const BASIC_FROM_RULES = {};
+
+// 处置管理通用表单规则
+const DISPOSAL_MANAGEMENT_BASIC_FROM_RULES = {
+  deptIds: [{ required: true, message: '请选择上报部门', trigger: 'change' }],
+  dueCompleteTime: [{ required: true, message: '请选择应完成上报时间', trigger: 'change' }],
+  userGroupList: [{ required: true, message: '请选择上报人员', trigger: 'change' }],
+  isPush: [{ required: true, message: '请选择是否推送', trigger: 'change' }],
+};
+
+// 处置管理任务项表单规则(任务项)
+export const DISPOSAL_MANAGEMENT_TASK_FROM_RULES = {
+  taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
+  ...DISPOSAL_MANAGEMENT_BASIC_FROM_RULES,
+};
+
+// 处置管理列表项表单规则(列表项)
+export const DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_CREATE = {
+  ...DISPOSAL_MANAGEMENT_BASIC_FROM_RULES,
+};

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

@@ -1,4 +1,35 @@
-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';
+import {
+  DISPOSAL_MANAGEMENT_TASK_FROM_CONFIG,
+  DISPOSAL_MANAGEMENT_TASK_FROM_DATA,
+  DISPOSAL_MANAGEMENT_TASK_FROM_RULES,
+  DISPOSAL_MANAGEMENT_ITEM_FROM_CONFIG_CREATE,
+  DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_CREATE,
+} from './form';
 
-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,
+  DISPOSAL_MANAGEMENT_TASK_FROM_CONFIG,
+  DISPOSAL_MANAGEMENT_TASK_FROM_DATA,
+  DISPOSAL_MANAGEMENT_TASK_FROM_RULES,
+  DISPOSAL_MANAGEMENT_ITEM_FROM_CONFIG_CREATE,
+  DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_CREATE,
+};

+ 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,
 ];

+ 31 - 3
src/views/disaster/disaster-control/src/constant.ts

@@ -6,7 +6,9 @@ import { PAGE_SIZE_CONFIG } from '@/constant/pagination';
 export enum TASK_STAGE {
   TO_BE_RELEASED = 1,
   TO_BE_REPORTED,
-  REPORTED,
+  REPORTED_LOSS,
+  REPORTED_NO_LOSS,
+  OVERDUE,
 }
 
 export const TASK_STAGE_OPTIONS = [
@@ -19,10 +21,36 @@ export const TASK_STAGE_OPTIONS = [
     value: TASK_STAGE.TO_BE_REPORTED,
   },
   {
-    label: '已上报',
-    value: TASK_STAGE.REPORTED,
+    label: '已上报,有损失',
+    value: TASK_STAGE.REPORTED_LOSS,
   },
+  {
+    label: '已上报,无损失',
+    value: TASK_STAGE.REPORTED_NO_LOSS,
+  },
+  {
+    label: '超期未上报',
+    value: TASK_STAGE.OVERDUE,
+  }
 ];
 
 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',
+  },
+]; 
+
+// 表单操作项
+export enum FORM_OPERATE_TYPE {
+  TABLE_ITEM = 'tableItem',
+  TASK_ITEM = 'taskItem',
+}
+

+ 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;
+}

+ 5 - 0
src/views/disaster/disaster-control/src/style/common.scss

@@ -0,0 +1,5 @@
+.disaster-precaution-container__header {
+  flex-direction: row !important;
+  justify-content: flex-start !important;
+  gap: 8cpx !important;
+}

+ 3 - 0
src/views/disaster/disaster-control/src/style/item-common.scss

@@ -0,0 +1,3 @@
+:deep(.el-date-editor) {
+  --el-date-editor-width: 100%;
+}

+ 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;
+};

+ 1 - 1
src/views/disaster/disaster-precaution/src/config/form.ts

@@ -70,7 +70,7 @@ export const TASK_MANAGEMENT_FROM_CONFIG_CREATE: FormConfig[] = [
   BASIC_FORM_CONFIG.TASK_NAME,
   {
     label: '被检查(自查)单位',
-    prop: 'deptName',
+    prop: 'deptIdList',
     slot: 'deptName',
   },
   BASIC_FORM_CONFIG.INSPECT_TYPE,

+ 2 - 0
src/views/disaster/disaster-warning/PageDefenseNotice.vue

@@ -207,10 +207,12 @@
   };
   const handleSizeChange = (value: number) => {
     pagination.pageSize = value;
+    defenseNoticeListQuery.pageSize = value;
     getTableData();
   };
   const handleCurrentChange = (value: number) => {
     pagination.pageNumber = value;
+    defenseNoticeListQuery.pageNumber = value;
     getTableData();
   };
   const getTableData = async () => {

+ 2 - 0
src/views/disaster/disaster-warning/PageWarningInfo.vue

@@ -214,10 +214,12 @@
   };
   const handleSizeChange = (value: number) => {
     pagination.pageSize = value;
+    wanrningInfoListQuery.pageSize = value;
     getTableData();
   };
   const handleCurrentChange = (value: number) => {
     pagination.pageNumber = value;
+    wanrningInfoListQuery.pageNumber = value;
     getTableData();
   };
   const getTableData = async () => {

+ 2 - 0
src/views/disaster/disaster-warning/src/config/form.ts

@@ -51,6 +51,8 @@ export const WARNING_INFO_FROM_CONFIG: FormConfig[] = [
     component: 'ElInput',
     componentProps: {
       placeholder: '请输入信息来源',
+      maxlength: 200,
+      showWordLimit: true,
     },
   },
   {

+ 6 - 0
src/views/disaster/overview/PageOverview.vue

@@ -231,4 +231,10 @@
       gap: 5cpx;
     }
   }
+  :deep(.el-tabs__header) {
+    margin-bottom: 15cpx;
+  }
+  :deep(.el-tabs__item) {
+    font-size: 14cpx;
+  }
 </style>

+ 3 - 0
src/views/disaster/overview/src/components/NotionList.vue

@@ -40,4 +40,7 @@
     font-weight: 600;
     color: rgba($text-color, 0.85);
   }
+  img{
+    width: 20cpx;
+  }
 </style>

+ 0 - 1
src/views/disaster/style/disaster.scss

@@ -36,7 +36,6 @@
       flex-direction: column;
       gap: 20cpx;
       &__header--button {
-        font-size: 14cpx;
         margin-bottom: 20cpx;
       }
     }