Explorar o código

完成损失上报

chauncey hai 11 meses
pai
achega
0b64b8abe9
Modificáronse 24 ficheiros con 846 adicións e 142 borrados
  1. 30 0
      src/api/disaster-control/index.ts
  2. 6 0
      src/components/BasicForm.vue
  3. 1 0
      src/constant/dict.ts
  4. 1 1
      src/hooks/useFormConfigHook.ts
  5. 1 1
      src/styles/common.scss
  6. 30 7
      src/types/disaster-control/index.ts
  7. 3 1
      src/views/disaster/disaster-control/PageDisposalManagementItem.vue
  8. 3 1
      src/views/disaster/disaster-control/PageDisposalManagementTaskItem.vue
  9. 19 13
      src/views/disaster/disaster-control/PageDisposalRectification.vue
  10. 5 2
      src/views/disaster/disaster-control/PageLossReport.vue
  11. 82 33
      src/views/disaster/disaster-control/PageLossReportItem.vue
  12. 222 0
      src/views/disaster/disaster-control/src/components/CreateLossReportItem.vue
  13. 48 24
      src/views/disaster/disaster-control/src/components/LossRecord.vue
  14. 4 5
      src/views/disaster/disaster-control/src/components/ReportTask.vue
  15. 285 0
      src/views/disaster/disaster-control/src/components/UploadImages.vue
  16. 62 18
      src/views/disaster/disaster-control/src/config/form.ts
  17. 4 2
      src/views/disaster/disaster-control/src/config/index.ts
  18. 1 6
      src/views/disaster/disaster-control/src/config/search.ts
  19. 0 16
      src/views/disaster/disaster-control/src/constant.ts
  20. 31 0
      src/views/disaster/disaster-control/src/hook.ts
  21. 0 6
      src/views/disaster/disaster-control/src/style/collapse.scss
  22. 4 0
      src/views/disaster/disaster-control/src/style/item-common.scss
  23. 1 5
      src/views/disaster/disaster-control/src/util.ts
  24. 3 1
      src/views/disaster/disaster-precaution/PageTaskItem.vue

+ 30 - 0
src/api/disaster-control/index.ts

@@ -11,6 +11,7 @@ import type {
   DisposalManagementCreateQuery,
   DisasterReportCreateQuery,
   DisasterReportEditQuery,
+  LossRecordCreateQuery,
 } from '@/types/disaster-control';
 import type { QueryPageResponse, QueryPageRequest } from '@/types/disaster';
 /**
@@ -127,3 +128,32 @@ export const getLossRecordTableData = (query: LossRecordTableQuery) => {
 /**
  * 添加上报责任人
  */
+export const addReporter = (reportTaskId: number, reporterIds: number[]) => {
+  return http.request({
+    url: `/disasterHandle/addDisasterReportTaskReporters?reportTaskId=${reportTaskId}&reporterIds=${reporterIds.join(
+      ',',
+    )}`,
+    method: 'post',
+  });
+};
+
+/**
+ * 创建损失记录
+ */
+export const createLossRecord = (query: LossRecordCreateQuery) => {
+  return http.request({
+    url: '/disasterHandle/saveLossRecord',
+    method: 'post',
+    data: query,
+  });
+};
+
+/**
+ * 删除损失记录
+ */
+export const deleteLossRecord = (reportTaskId: number) => {
+  return http.request({
+    url: `/disasterHandle/deleteLossRecord?reportTaskId=${reportTaskId}`,
+    method: 'delete',
+  });
+};

+ 6 - 0
src/components/BasicForm.vue

@@ -42,9 +42,15 @@
     formRef.value?.validateField(field);
   };
 
+  // 清除表单验证信息
+  const clearValidate = () => {
+    formRef.value?.resetFields();
+  };
+
   defineExpose({
     validateForm,
     validateField,
+    clearValidate,
   });
 </script>
 

+ 1 - 0
src/constant/dict.ts

@@ -3,4 +3,5 @@ export const DICT_CODE = {
   DISASTER_LEVEL: 'disaster_level',
   DISASTER_TYPE: 'disaster_type',
   PRIORITY: 'disaster_fix_priority',
+  SAFETY_LEVEL: 'disaster_safety_impact'
 };

+ 1 - 1
src/hooks/useFormConfigHook.ts

@@ -23,7 +23,7 @@ export const useFormConfigHook = <T extends Record<string, any> = Record<string,
   data: T,
   rules: FormRules<T>,
 ) => {
-  const ruleFormConfig = reactive<FormConfig[]>(config);
+  const ruleFormConfig = ref<FormConfig[]>(config);
   const ruleFormData = reactive<T>(cloneDeep(data));
   const initRuleFormData = ref<T>();
   const formRules = reactive<FormRules<T>>(rules);

+ 1 - 1
src/styles/common.scss

@@ -30,5 +30,5 @@
 }
 
 .el-button--primary {
-  --el-button-bg-color: #1777ff !important;
+  --el-button-bg-color: #1980ff !important;
 }

+ 30 - 7
src/types/disaster-control/index.ts

@@ -51,7 +51,7 @@ export interface disasterReportRecordDetailListResponse {
   affectedItems: string;
   updatedAt: string;
   responsibleDeptName: string;
-  priority: number;
+  priority: string;
   fixStatus: number;
   isLoss: number;
 }
@@ -113,18 +113,41 @@ export interface DisposalManagementRuleFormEdit extends Omit<DisposalManagementC
 }
 
 export interface LossReportItemFormData
-  extends Omit<disasterReportRecordDetailListResponse, 'id' | 'isLoss' | 'priority'> {
+  extends Omit<disasterReportRecordDetailListResponse, 'id' | 'updatedAt' | 'responsibleDeptName' | 'fixStatus'> {
   reportTaskName: string;
-  isLoss: number | null;
   images: string[];
   description: string;
   safetyLevel: string;
   isAffectWork: number | null;
-  estimatedLoss: number;
+  estimatedLoss: number | null;
   responsibleDeptId: number | null;
   userGroupList: number[];
-  isPush: number | null;
-  priority: number | null;
-  remark: string;
+  isPush: number;
   createdBy: string;
+  remark: string;
+  affectedRoom: string; //自己创造的一个数值,不要传给后端
+}
+
+export interface LossRecordFormData {
+  reportTaskName: string;
+  isLoss: number;
+  buildingNo?: string;
+  floorNo?: string;
+  roomNo?: string;
+  affectedItems?: string;
+  images?: File[];
+  description?: string;
+  safetyLevel?: string;
+  isAffectWork?: number;
+  estimatedLoss?: number;
+  priority?: string;
+  responsibleDeptId?: number;
+  remark?: string;
+  userGroupList?: number[];
+  isPush?: number;
+}
+
+export interface LossRecordCreateQuery extends Omit<LossRecordFormData, 'images'> {
+  reportTaskId: number;
+  images?: string[];
 }

+ 3 - 1
src/views/disaster/disaster-control/PageDisposalManagementItem.vue

@@ -5,7 +5,9 @@
       <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
     </header>
     <main class="disaster-precaution-container__main">
-      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+      <section>
+        <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+      </section>
     </main>
     <footer class="disaster-precaution-container__footer" v-if="operate">
       <el-button @click="router.back()">取消</el-button>

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

@@ -5,7 +5,9 @@
       <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
     </header>
     <main class="disaster-precaution-container__main">
-      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+      <section>
+        <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+      </section>
     </main>
     <footer class="disaster-precaution-container__footer" v-if="operate">
       <el-button @click="router.back()">取消</el-button>

+ 19 - 13
src/views/disaster/disaster-control/PageDisposalRectification.vue

@@ -10,7 +10,18 @@
             :searchConfig="DISPOSAL_RECTIFICATION_SEARCH_CONFIG"
             :searchData="searchData"
             @update:searchData="handleSearch"
-          />
+          >
+            <template #priority>
+              <el-select v-model="searchData.priority" placeholder="请选择优先级" class="custom-select">
+                <el-option
+                  v-for="item in priorityDice"
+                  :key="item.itemCode"
+                  :label="item.itemValue"
+                  :value="item.itemCode"
+                />
+              </el-select>
+            </template>
+          </Search>
         </header>
         <section class="disaster-precaution__section">
           <div class="collapse-container" v-loading="collapseLoading">
@@ -41,16 +52,7 @@
                       </el-tooltip>
                     </template>
                     <template #priority="scope">
-                      <div
-                        class="priority-container"
-                        :class="
-                          scope.row.priority === PRIORITY_STATUS.URGENT
-                            ? 'priority-container--urgent'
-                            : 'priority-container--normal'
-                        "
-                      >
-                        <span>{{ getPriorityStatus(scope.row.priority) }}</span>
-                      </div>
+                      <span>{{ getPriority(scope.row.priority) }}</span>
                     </template>
                     <template #fixStatus="scope">
                       <div class="fix-status-container">
@@ -98,7 +100,7 @@
   import { onMounted, reactive, ref } from 'vue';
   import { getDisasterControlCollapseData, getLossRecordTableData } from '@/api/disaster-control';
   import type { disasterReportTaskInfoListResponse } from '@/types/disaster-control';
-  import { DEFAULT_PAGE_SIZE, DISASTER_CONTROL_PAGE_SIZE_CONFIG, PRIORITY_STATUS, FIX_STATUS } from './src/constant';
+  import { DEFAULT_PAGE_SIZE, DISASTER_CONTROL_PAGE_SIZE_CONFIG, FIX_STATUS } from './src/constant';
   import type { DisposalManagementCollapseListResponse, LossRecordTableResponse } from '@/types/disaster-control';
   import useTableConfig from '@/hooks/useTableConfigHook';
   import {
@@ -106,12 +108,15 @@
     LOSS_RECORD_TABLE_COLUMNS,
     DISPOSAL_MANAGEMENT_TABLE_OPTIONS,
   } from './src/config';
-  import { getPriorityStatus, getfixStatus } from './src/util';
+  import { getfixStatus } from './src/util';
   import { ACTIVE_STATUS } 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 { useDisasterControlHook } from './src/hook';
+
+  const { getPriority, getPriorityDict, priorityDice } = useDisasterControlHook();
 
   const searchData = reactive({
     priority: '',
@@ -198,6 +203,7 @@
   };
 
   onMounted(async () => {
+    getPriorityDict();
     await getDisposalData();
     await getDisposalTableData();
   });

+ 5 - 2
src/views/disaster/disaster-control/PageLossReport.vue

@@ -14,8 +14,8 @@
 
 <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);
+  import { computed, ref, defineAsyncComponent, onUnmounted } from 'vue';
+  const activeName = ref(sessionStorage.getItem('loss-report-active') || LOSS_REPORT_TABS[0].value);
   const dynamicComponent = computed(() => {
     switch (activeName.value) {
       case LOSS_REPORT_TABS[0].value:
@@ -24,6 +24,9 @@
         return defineAsyncComponent(() => import('./src/components/LossRecord.vue'));
     }
   });
+  onUnmounted(() => {
+    sessionStorage.setItem('loss-report-active', activeName.value);
+  });
 </script>
 
 <style scoped lang="scss">

+ 82 - 33
src/views/disaster/disaster-control/PageLossReportItem.vue

@@ -2,52 +2,101 @@
   <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">创建损失记录</span>
+      <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
     </header>
     <main class="disaster-precaution-container__main">
-      <div class="loss-report-form-container">
-        <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig">
-          <template #isLoss>
-            <el-radio-group v-model="ruleFormData.isLoss">
-              <el-radio :label="1">是</el-radio>
-              <el-radio :label="0">否</el-radio>
-            </el-radio-group>
-          </template>
-        </BasicForm>
-      </div>
+      <section>
+        <component :is="dynamicComponent" ref="dynamicComponentRef" />
+      </section>
     </main>
-    <footer class="disaster-precaution-container__footer">
+    <footer class="disaster-precaution-container__footer" v-if="operate">
       <el-button @click="router.back()">取消</el-button>
-      <el-button type="primary">提交,并创建下一条</el-button>
-      <el-button type="primary">提交</el-button>
+      <el-button type="primary" @click="handleSubmitNext" v-if="operate === 'create'">提交,并创建下一条</el-button>
+      <el-button type="primary" @click="handleSubmitSingle">提交</el-button>
     </footer>
+    <UploadLoading :form-loading="formLoading" v-if="formLoading" />
   </div>
 </template>
 
 <script lang="ts" setup>
-  import { onMounted } from 'vue';
-  import { useRoute, useRouter } from 'vue-router';
-  import BasicForm from '@/components/BasicForm.vue';
-  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
-  import { LOSS_REPORT_ITEM_FORM_CONFIG, LOSS_REPORT_ITEM_FORM_DATA, LOSS_REPORT_ITEM_FROM_RULES } from './src/config';
-  import type { LossReportItemFormData } from '@/types/disaster-control';
+  import { ref, computed, defineAsyncComponent } from 'vue';
+  import { useRouter, useRoute } from 'vue-router';
   import BackIcon from 'assets/svg/back.svg';
-  import { useUserInfoHook } from '@/views/disaster/hooks/userInfo';
-  const route = useRoute();
+  import { LossRecordFormData } from '@/types/disaster-control';
+  import { createLossRecord } from '@/api/disaster-control';
+  import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
+  import { ElMessage } from 'element-plus';
+
   const router = useRouter();
-  const taskName = String(route.query.taskName);
+  const route = useRoute();
   const id = Number(route.params.id);
-  const { ruleFormConfig, ruleFormData, formRules, cloneRuleFormData, beforeRouteLeave } =
-    useFormConfigHook<LossReportItemFormData>(
-      LOSS_REPORT_ITEM_FORM_CONFIG,
-      LOSS_REPORT_ITEM_FORM_DATA,
-      LOSS_REPORT_ITEM_FROM_RULES,
-    );
-  const { realname } = useUserInfoHook();
-  onMounted(() => {
-    ruleFormData.reportTaskName = taskName;
-    ruleFormData.createdBy = realname;
+  const dynamicComponentRef = ref();
+  const operate = route.query.operation;
+  const headerTitle = computed(() => {
+    const fixedTitle = '损失记录';
+    if (operate === 'create') {
+      return `创建${fixedTitle}`;
+    }
+    return `查看${fixedTitle}`;
+  });
+  const dynamicComponent = computed(() => {
+    if (operate === 'create') {
+      return defineAsyncComponent(() => import('./src/components/CreateLossReportItem.vue'));
+    } else {
+      return '';
+    }
   });
+  const formLoading = ref(false);
+  const formatAttachmentList = async (file: File) => {
+    if (!file) return file;
+    const fileName = file.name;
+    const res = await uploadFileApi({ bizType: UPLOAD_BIZ_TYPE.ATTACHMENT, fileName, file });
+    return res.url;
+  };
+  const createLossReportFunc = async (formData: LossRecordFormData) => {
+    const imagesListRes: string[] = await Promise.all(
+      (formData.images || []).map((item) => formatAttachmentList(item)),
+    );
+    const createParam = {
+      reportTaskId: id,
+      ...formData,
+      images: imagesListRes,
+    };
+    await createLossRecord(createParam);
+  };
+  const handleSubmit = async () => {
+    const validateResult = await dynamicComponentRef.value?.validateForm();
+    if (!validateResult) return;
+    const formData = dynamicComponentRef.value?.getFormData();
+    formLoading.value = true;
+    let message;
+    try {
+      if (operate === 'create') {
+        await createLossReportFunc(formData);
+        message = '创建成功';
+      }
+      ElMessage.success(message);
+      return true; // 成功时返回true
+    } catch (error) {
+      return false; // 失败时返回false
+    } finally {
+      formLoading.value = false;
+    }
+  };
+  const handleSubmitSingle = async () => {
+    const success = await handleSubmit();
+    if (!success) return;
+    router.back();
+  };
+  const handleSubmitNext = async () => {
+    const success = await handleSubmit();
+    if (!success) return;
+    dynamicComponentRef.value?.initFormData();
+    // 滚动到页面顶部 - 使用更可靠的方法
+    const mainElement = document.querySelector('.disaster-precaution-container__main');
+    if (!mainElement) return;
+    mainElement.scrollTop = 0;
+  };
 </script>
 
 <style lang="scss" scoped>

+ 222 - 0
src/views/disaster/disaster-control/src/components/CreateLossReportItem.vue

@@ -0,0 +1,222 @@
+<template>
+  <div class="info-container">
+    <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig">
+      <template #isLoss>
+        <el-radio-group v-model="ruleFormData.isLoss">
+          <el-radio :label="1">是</el-radio>
+          <el-radio :label="0">否</el-radio>
+        </el-radio-group>
+      </template>
+      <template #affectedRoom>
+        <div class="affected-room-container">
+          <el-form-item prop="buildingNo">
+            <el-input v-model="ruleFormData.buildingNo" placeholder="楼号" />
+          </el-form-item>
+          <el-form-item prop="floorNo">
+            <el-input v-model="ruleFormData.floorNo" placeholder="楼层" />
+          </el-form-item>
+          <el-form-item prop="roomNo">
+            <el-input v-model="ruleFormData.roomNo" placeholder="房间号" />
+          </el-form-item>
+        </div>
+      </template>
+      <template #affectedImages>
+        <UploadImages v-model:fileList="ruleFormData.images" :maxCount="9" ref="uploadImagesRef" />
+      </template>
+      <template #safetyLevel>
+        <el-select v-model="ruleFormData.safetyLevel" placeholder="请选择影响安全评估">
+          <el-option
+            v-for="item in safetyLevelDice"
+            :key="item.itemCode"
+            :label="item.itemValue"
+            :value="item.itemCode"
+          />
+        </el-select>
+      </template>
+      <template #isAffectWork>
+        <el-select v-model="ruleFormData.isAffectWork" placeholder="请选择是否影响正常工作">
+          <el-option label="是" value="1" />
+          <el-option label="否" value="0" />
+        </el-select>
+      </template>
+      <template #lossAssessmentAmount>
+        <el-input
+          v-model="ruleFormData.estimatedLoss"
+          placeholder="请输入损失评估金额"
+          @input="handleEstimatedLossInput"
+          @change="handleEstimatedLossChange"
+        />
+      </template>
+      <template #priority>
+        <el-select v-model="ruleFormData.priority" placeholder="请选择处置优先级">
+          <el-option v-for="item in priorityDice" :key="item.itemCode" :label="item.itemValue" :value="item.itemCode" />
+        </el-select>
+      </template>
+      <template #responsibleDeptId>
+        <el-select v-model="ruleFormData.responsibleDeptId" placeholder="请选择整改责任部门" filterable>
+          <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="1">是</el-radio>
+          <el-radio :label="0">否</el-radio>
+        </el-radio-group>
+      </template>
+    </BasicForm>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { onMounted, ref, watch } from 'vue';
+  import { useRoute } from 'vue-router';
+  import UploadImages from './UploadImages.vue';
+  import BasicForm from '@/components/BasicForm.vue';
+  import { useFormConfigHook } from '@/hooks/useFormConfigHook';
+  import {
+    LOSS_REPORT_ITEM_FORM_CONFIG_LOSS,
+    LOSS_REPORT_ITEM_FORM_CONFIG_NO_LOSS,
+    LOSS_REPORT_ITEM_FORM_DATA,
+    LOSS_REPORT_ITEM_FROM_RULES,
+  } from '../config';
+  import type { LossReportItemFormData } from '@/types/disaster-control';
+  import GroupSelect from '@/views/disaster/components/GroupSelect.vue';
+  import { getAllUserGroup } from '@/api/system/person-group';
+  import type { UserGroupOption } from '@/types/person-group/type';
+  import { useUserInfoHook } from '@/views/disaster/hooks/userInfo';
+  import type { DeptTreeItem } from '@/types/dept/type';
+  import { getAllDepartments } from '@/api/auth/dept';
+  import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
+  import { useDisasterControlHook } from '../hook';
+
+  const { safetyLevelDice, priorityDice, getSafetyLevelDict, getPriorityDict } = useDisasterControlHook();
+
+  // 处理损失评估金额输入,只允许输入数字和小数点,且小数点后最多10位
+  const handleEstimatedLossInput = (value: string) => {
+    // 允许数字开头、小数点结尾、小数点后最多10位数字的情况
+    const regex = /^(\d+\.?|\.\d{1,10}|\d+\.\d{0,10})$/;
+
+    // 如果是正在输入的状态(以小数点结尾),直接允许
+    if (value.endsWith('.') && value.indexOf('.') === value.lastIndexOf('.')) {
+      return;
+    }
+
+    if (!regex.test(value)) {
+      // 尝试清理和修复输入值
+      let cleanValue = value.replace(/[^\d.]/g, '');
+      const dotParts = cleanValue.split('.');
+
+      if (dotParts.length > 2) {
+        // 保留第一个小数点和小数部分
+        cleanValue = dotParts[0] + '.' + dotParts.slice(1).join('');
+      }
+
+      // 处理小数部分超过10位的情况
+      const dotIndex = cleanValue.indexOf('.');
+      if (dotIndex !== -1 && dotIndex < cleanValue.length - 11) {
+        cleanValue = cleanValue.substring(0, dotIndex + 11);
+      }
+
+      if (cleanValue === '' || cleanValue === '.') {
+        ruleFormData.estimatedLoss = null;
+      } else {
+        ruleFormData.estimatedLoss = Number(cleanValue);
+      }
+    } else {
+      // 输入合法
+      ruleFormData.estimatedLoss = value ? Number(value) : null;
+    }
+  };
+
+  // 处理失去焦点时,如果是小数点结尾则删除小数点
+  const handleEstimatedLossChange = () => {
+    // 检查当前值是否为字符串且以小数点结尾
+    if (ruleFormData.estimatedLoss !== null) {
+      const strValue = String(ruleFormData.estimatedLoss);
+      if (strValue.endsWith('.')) {
+        // 移除结尾的小数点
+        ruleFormData.estimatedLoss = Number(strValue.slice(0, -1));
+      }
+    }
+  };
+
+  const route = useRoute();
+  const taskName = String(route.query.taskName);
+  const groupOptions = ref<UserGroupOption[]>([]);
+  const { ruleFormConfig, ruleFormData, formRules, cloneRuleFormData, beforeRouteLeave } =
+    useFormConfigHook<LossReportItemFormData>(
+      LOSS_REPORT_ITEM_FORM_CONFIG_LOSS,
+      LOSS_REPORT_ITEM_FORM_DATA,
+      LOSS_REPORT_ITEM_FROM_RULES,
+    );
+  const { realname } = useUserInfoHook();
+  const firstLevelDepts = ref<DeptTreeItem[]>([]);
+  const basicFormRef = ref<InstanceType<typeof BasicForm>>();
+  const uploadImagesRef = ref<InstanceType<typeof UploadImages>>();
+  const getUserGroupList = async () => {
+    const res = await getAllUserGroup();
+    groupOptions.value = res.groupVOList;
+  };
+  const getDeptList = async () => {
+    const res = await getAllDepartments();
+    firstLevelDepts.value = formatDeptTree(res);
+  };
+  const validateForm = async () => {
+    if (!basicFormRef.value) return;
+    const validateResult = await basicFormRef.value.validateForm();
+    return validateResult;
+  };
+  const getFormData = () => {
+    cloneRuleFormData();
+    if (ruleFormData.isLoss) {
+      const { createdBy, ...rest } = ruleFormData;
+      return rest;
+    }
+    return {
+      reportTaskName: ruleFormData.reportTaskName,
+      isLoss: ruleFormData.isLoss,
+    };
+  };
+  const initBasicFormData = () => {
+    ruleFormData.reportTaskName = taskName;
+    ruleFormData.createdBy = realname;
+  };
+  const initFormData = () => {
+    uploadImagesRef.value?.removeAllImages();
+    basicFormRef.value?.clearValidate();
+    initBasicFormData();
+    cloneRuleFormData();
+  };
+  defineExpose({
+    validateForm,
+    getFormData,
+    initFormData,
+  });
+  onMounted(() => {
+    initBasicFormData();
+    getSafetyLevelDict();
+    getPriorityDict();
+    getDeptList();
+    getUserGroupList();
+    cloneRuleFormData();
+    beforeRouteLeave();
+  });
+  watch(
+    () => ruleFormData.isLoss,
+    (newVal) => {
+      if (newVal) {
+        ruleFormConfig.value = LOSS_REPORT_ITEM_FORM_CONFIG_LOSS;
+      } else {
+        ruleFormConfig.value = LOSS_REPORT_ITEM_FORM_CONFIG_NO_LOSS;
+      }
+    },
+  );
+</script>
+
+<style scoped lang="scss">
+  @use '@/views/disaster/style/info-container.scss' as *;
+  @use '../style/item-common.scss' as *;
+</style>

+ 48 - 24
src/views/disaster/disaster-control/src/components/LossRecord.vue

@@ -26,14 +26,26 @@
           <span>暂无数据</span>
         </div>
         <template v-else>
-          <CollapseItem v-for="item in collapseList" :key="item.id" :name="item.taskName" :defaultOpen="item.id === 1">
+          <CollapseItem
+            ref="collapseItemRef"
+            v-for="item in collapseList"
+            :key="item.id"
+            :name="item.taskName"
+            :defaultOpen="item.id === collapseList[0].id"
+          >
             <template #viewOperation>
               <div class="update-time-container">
                 <span>发布时间:{{ item.updatedAt }}</span>
               </div>
             </template>
             <template #main-table>
-              <el-button type="primary" :icon="Plus" class="main-table__button">新增</el-button>
+              <el-button
+                type="primary"
+                :icon="Plus"
+                class="main-table__button"
+                @click="handleReport(item.id, item.taskName)"
+                >新增</el-button
+              >
               <BasicTable :tableData="item.tableData[0].disasterReportRecordDetailList" :tableConfig="tableConfig">
                 <template #affectedArea="scope">
                   <div class="affected-area-container">
@@ -48,16 +60,7 @@
                   </el-tooltip>
                 </template>
                 <template #priority="scope">
-                  <div
-                    class="priority-container"
-                    :class="
-                      scope.row.priority === PRIORITY_STATUS.URGENT
-                        ? 'priority-container--urgent'
-                        : 'priority-container--normal'
-                    "
-                  >
-                    <span>{{ getPriorityStatus(scope.row.priority) }}</span>
-                  </div>
+                  <span>{{ getPriority(scope.row.priority) }}</span>
                 </template>
                 <template #fixStatus="scope">
                   <div class="fix-status-container">
@@ -67,7 +70,7 @@
                 <template #action="scope">
                   <ActionButton text="编辑" v-if="scope.row.fixStatus === FIX_STATUS.TO_BE_RECTIFIED" />
                   <ActionButton text="查看" v-if="scope.row.isLoss === IS_LOSS.NO_LOSS" />
-                  <ActionButton text="删除" />
+                  <ActionButton text="删除" @click="handleDelete(scope.row.id)" />
                 </template>
               </BasicTable>
             </template>
@@ -91,22 +94,16 @@
 </template>
 
 <script lang="ts" setup>
-  import { ref, reactive, onMounted } from 'vue';
+  import { ref, reactive, onMounted, nextTick } from 'vue';
   import { Plus } from '@element-plus/icons-vue';
   import Search from '@/views/disaster/components/Search.vue';
   import BasicTable from '@/components/BasicTable.vue';
   import ActionButton from '@/components/ActionButton.vue';
   import { getAllDepartments } from '@/api/auth/dept';
   import CollapseItem from './CollapseItem.vue';
-  import {
-    DEFAULT_PAGE_SIZE,
-    DISASTER_CONTROL_PAGE_SIZE_CONFIG,
-    PRIORITY_STATUS,
-    IS_LOSS,
-    FIX_STATUS,
-  } from '../constant';
+  import { DEFAULT_PAGE_SIZE, DISASTER_CONTROL_PAGE_SIZE_CONFIG, IS_LOSS, FIX_STATUS } from '../constant';
   import type { DisposalManagementCollapseListResponse, LossRecordTableResponse } from '@/types/disaster-control';
-  import { getReportTaskList, getLossRecordTableData } from '@/api/disaster-control';
+  import { getReportTaskList, getLossRecordTableData, deleteLossRecord } from '@/api/disaster-control';
   import {
     LOSS_RECORD_LOSS_RECORD_SEARCH_CONFIG,
     LOSS_RECORD_TABLE_COLUMNS,
@@ -116,14 +113,20 @@
   import useTableConfig from '@/hooks/useTableConfigHook';
   import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
   import type { DeptTreeItem } from '@/types/dept/type';
-  import { getPriorityStatus, getfixStatus } from '../util';
+  import { getfixStatus } from '../util';
+  import { useRouter } from 'vue-router';
+  import { ElMessage } from 'element-plus';
+  import { useDisasterControlHook } from '../hook';
 
-  const firstLevelDepts = ref<DeptTreeItem[]>([]);
+  const { getPriority, getPriorityDict } = useDisasterControlHook();
 
+  const firstLevelDepts = ref<DeptTreeItem[]>([]);
+  const router = useRouter();
   const currentPage = ref(1);
   const pageSize = ref(DEFAULT_PAGE_SIZE);
   const total = ref(0);
   const collapseLoading = ref(false);
+  const collapseItemRef = ref<InstanceType<typeof CollapseItem>[]>([]);
   const { tableConfig } = useTableConfig(LOSS_RECORD_TABLE_COLUMNS, DISPOSAL_MANAGEMENT_TABLE_OPTIONS, false);
   const searchData = reactive({
     handleDeptIds: [],
@@ -156,6 +159,9 @@
     taskIds.value = res.records.map((item) => item.handleTaskId);
     total.value = res.totalRow;
     collapseLoading.value = false;
+    nextTick(() => {
+      collapseItemRef.value[0]?.openFirstCollapseItem();
+    });
   };
 
   const getDisposalTableData = async () => {
@@ -183,9 +189,27 @@
     await getDisposalTableData();
   };
 
+  const handleReport = (handleTaskId: number, taskName: string) => {
+    router.push({
+      name: 'disaster-control-loss-report-item',
+      params: {
+        id: handleTaskId,
+      },
+      query: { taskName, operation: 'create' },
+    });
+  };
+
+  const handleDelete = async (id: number) => {
+    await deleteLossRecord(id);
+    await getDisposalData();
+    await getDisposalTableData();
+    ElMessage.success('删除成功');
+  };
+
   onMounted(async () => {
     const result = await getAllDepartments();
     firstLevelDepts.value = formatDeptTree(result);
+    getPriorityDict();
     await getDisposalData();
     await getDisposalTableData();
   });

+ 4 - 5
src/views/disaster/disaster-control/src/components/ReportTask.vue

@@ -28,7 +28,7 @@
           <ActionButton
             text="添加上报人"
             v-if="scope.row.isReportPrincipal"
-            @click="handleAddReporter(scope.row.handleTaskId, scope.row.reporterList)"
+            @click="handleAddReporter(scope.row.id, scope.row.reporterList)"
           />
         </div>
         <!-- 已上报任务阶段 -->
@@ -67,7 +67,7 @@
     LOSS_REPORT_REPORT_TASK_TABLE_COLUMNS,
   } from '../config';
   import useTableConfig from '@/hooks/useTableConfigHook';
-  import { getReportTaskList } from '@/api/disaster-control';
+  import { getReportTaskList, addReporter } from '@/api/disaster-control';
   import type { LossReportReportTaskQuery, LossReportReportTaskResponse } from '@/types/disaster-control';
   import type { QueryPageRequest } from '@/types/disaster';
   import { TASK_STAGE } from '../constant';
@@ -124,7 +124,7 @@
       params: {
         id: handleTaskId,
       },
-      query: { taskName },
+      query: { taskName, operation: 'create' },
     });
   };
   const userInfo = ref(false);
@@ -145,8 +145,7 @@
   };
   const handleSubmitReporter = async (ids: number[]) => {
     if (!currentTaskId.value) return;
-    console.log(ids);
-    console.log(currentTaskId.value);
+    await addReporter(currentTaskId.value, ids);
     ElMessage.success('添加上报责任人成功');
     userInfo.value = false;
     getTableData();

+ 285 - 0
src/views/disaster/disaster-control/src/components/UploadImages.vue

@@ -0,0 +1,285 @@
+<template>
+  <div class="upload-container">
+    <div v-for="(image, index) in uploadedImages" :key="index" class="image-preview">
+      <el-image
+        :src="image.url"
+        :zoom-rate="1.2"
+        :max-scale="7"
+        :min-scale="0.2"
+        :preview-src-list="uploadedImages.map((item) => item.url)"
+        show-progress
+        :initial-index="index"
+        fit="contain"
+      />
+      <div class="delete-icon" @click="removeImage(index)">×</div>
+    </div>
+
+    <div
+      v-show="!isMaximum"
+      class="upload-box"
+      :class="{ dragging: isDragging }"
+      @click="!isMaximum && triggerUpload()"
+      @drop.prevent="onDrop"
+      @dragover.prevent
+      @dragenter.prevent="onDragEnter"
+      @dragleave.prevent="onDragLeave"
+    >
+      <input
+        ref="fileInput"
+        type="file"
+        accept=".jpg,.jpeg,.png"
+        multiple
+        @change="handleFileChange"
+        style="display: none"
+        :disabled="isMaximum"
+      />
+      <div class="upload-icons">
+        <div class="plus-icon">
+          <el-icon><Plus /></el-icon>
+        </div>
+        <div class="camera-icon">
+          <el-icon><Camera /></el-icon>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+  import { ref, reactive, computed } from 'vue';
+  import { Camera, Plus } from '@element-plus/icons-vue';
+  import { ElMessage } from 'element-plus';
+
+  interface ImageItem {
+    file: File;
+    url: string;
+    name: string;
+    size: number;
+  }
+
+  const props = defineProps({
+    maxCount: {
+      type: Number,
+      default: 9,
+    },
+    maxSize: {
+      type: Number,
+      default: 10, // 默认10MB
+    },
+    acceptTypes: {
+      type: Array as () => string[],
+      default: () => ['.jpg', '.jpeg', '.png'],
+    },
+  });
+
+  const emit = defineEmits(['update:fileList', 'change']);
+
+  const fileInput = ref<HTMLInputElement | null>(null);
+  const uploadedImages = reactive<ImageItem[]>([]);
+
+  // 计算属性:是否已达到最大上传数量
+  const isMaximum = computed(() => {
+    return uploadedImages.length >= props.maxCount;
+  });
+
+  const isDragging = ref(false);
+
+  const onDragEnter = () => {
+    if (!isMaximum.value) {
+      isDragging.value = true;
+    }
+  };
+
+  const onDragLeave = () => {
+    isDragging.value = false;
+  };
+
+  const onDrop = (e: DragEvent) => {
+    isDragging.value = false;
+    if (!isMaximum.value && e.dataTransfer?.files) {
+      handleDrop(e);
+    }
+  };
+
+  const triggerUpload = () => {
+    fileInput.value?.click();
+  };
+
+  const handleFileChange = (e: Event) => {
+    const target = e.target as HTMLInputElement;
+    if (target.files) {
+      addFiles(Array.from(target.files));
+    }
+  };
+
+  const handleDrop = (e: DragEvent) => {
+    if (e.dataTransfer?.files) {
+      addFiles(Array.from(e.dataTransfer.files));
+    }
+  };
+
+  // 检查文件是否已存在
+  const isFileExist = (file: File): boolean => {
+    // 通过文件名和文件大小判断是否为同一文件
+    return uploadedImages.some((item) => item.name === file.name && item.size === file.size);
+  };
+
+  const checkFileValid = (file: File): boolean => {
+    // 检查文件是否已上传
+    if (isFileExist(file)) {
+      ElMessage.warning(`文件"${file.name}"已上传过,请勿重复上传`);
+      return false;
+    }
+
+    // 检查文件类型
+    const type = file.type.toLowerCase();
+    const isValidType = type.includes('jpeg') || type.includes('jpg') || type.includes('png');
+
+    if (!isValidType) {
+      ElMessage.error(`文件"${file.name}"格式不正确,请上传jpg、png或jpeg格式的图片`);
+      return false;
+    }
+
+    // 检查文件大小
+    const sizeInMB = file.size / (1024 * 1024);
+    if (sizeInMB > props.maxSize) {
+      ElMessage.error(`文件"${file.name}"大小超过${props.maxSize}MB限制`);
+      return false;
+    }
+
+    return true;
+  };
+
+  const addFiles = (files: File[]) => {
+    // 过滤出有效的图片文件
+    const validFiles = files.filter(checkFileValid);
+
+    // 检查是否超过最大数量限制
+    const remainingSlots = props.maxCount - uploadedImages.length;
+    if (validFiles.length > remainingSlots) {
+      ElMessage.warning(`最多只能上传${props.maxCount}张图片`);
+    }
+
+    const filesToAdd = validFiles.slice(0, remainingSlots);
+
+    // 添加到已上传列表
+    filesToAdd.forEach((file) => {
+      const url = URL.createObjectURL(file);
+      uploadedImages.push({
+        file,
+        url,
+        name: file.name,
+        size: file.size,
+      });
+    });
+
+    // 触发更新事件
+    if (filesToAdd.length > 0) {
+      emitChange();
+    }
+  };
+
+  const removeImage = (index: number) => {
+    // 释放对象URL以避免内存泄漏
+    URL.revokeObjectURL(uploadedImages[index].url);
+    uploadedImages.splice(index, 1);
+    emitChange();
+  };
+
+  const removeAllImages = () => {
+    uploadedImages.forEach((item) => {
+      URL.revokeObjectURL(item.url);
+    });
+    uploadedImages.length = 0;
+  };
+
+  defineExpose({
+    removeAllImages,
+  });
+
+  const emitChange = () => {
+    const files = uploadedImages.map((item) => item.file);
+    emit('update:fileList', files);
+    emit('change', files);
+  };
+</script>
+
+<style lang="scss" scoped>
+  .upload-container {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 5px;
+    width: 100%;
+  }
+
+  .upload-box,
+  .image-preview {
+    width: 100px;
+    height: 100px;
+    background-color: #f7f8fa;
+    border-radius: 4px;
+  }
+
+  .upload-box {
+    @include flex-center;
+    border: 1px dashed #d9d9d9;
+    cursor: pointer;
+    transition: all 0.3s;
+
+    &:hover {
+      border-color: $primary-color;
+    }
+
+    &.dragging {
+      border-color: $primary-color;
+      border-width: 2px;
+      background-color: rgba($primary-color, 0.05);
+      transform: scale(1.02);
+      box-shadow: 0 0 8px rgba($primary-color, 0.3);
+    }
+  }
+
+  .upload-icons {
+    @include flex-center;
+    flex-direction: column;
+    gap: 5px;
+    color: #b5b8be;
+    .plus-icon {
+      @include flex-center;
+      width: 26px;
+      height: 26px;
+      font-size: 20px;
+    }
+    .camera-icon {
+      @include flex-center;
+      width: 35px;
+      height: 30px;
+      font-size: 30px;
+    }
+  }
+
+  .image-preview {
+    position: relative;
+    overflow: hidden;
+    .el-image {
+      width: 100%;
+      height: 100%;
+    }
+
+    .delete-icon {
+      position: absolute;
+      top: 0;
+      right: 0;
+      width: 20px;
+      height: 20px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      background-color: rgba(0, 0, 0, 0.5);
+      color: white;
+      cursor: pointer;
+      font-size: 16px;
+      border-radius: 0 0 0 4px;
+    }
+  }
+</style>

+ 62 - 18
src/views/disaster/disaster-control/src/config/form.ts

@@ -113,9 +113,9 @@ export const DISPOSAL_MANAGEMENT_ITEM_FROM_CONFIG_EDIT: FormConfig[] = [
   ...DISPOSAL_MANAGEMENT_BASIC_FROM_CONFIG,
 ];
 
-// 创建损失记录表单信息
-export const LOSS_REPORT_ITEM_FORM_CONFIG: FormConfig[] = [
-  {
+// 创建损失记录表单信息通用项目
+const LOSS_REPORT_ITEM_FORM_CONFIG_COMMON = {
+  TASK_NAME: {
     label: '任务名称',
     prop: 'reportTaskName',
     component: 'ElInput',
@@ -123,11 +123,32 @@ export const LOSS_REPORT_ITEM_FORM_CONFIG: FormConfig[] = [
       disabled: true,
     },
   },
-  {
+  IS_LOSS: {
     label: '是否损失',
     prop: 'isLoss',
     slot: 'isLoss',
   },
+  CREATED_BY: {
+    label: '创建人',
+    prop: 'createdBy',
+    component: 'ElInput',
+    componentProps: {
+      disabled: true,
+    },
+  },
+};
+
+// 创建损失记录表单信息(无损失)
+export const LOSS_REPORT_ITEM_FORM_CONFIG_NO_LOSS: FormConfig[] = [
+  LOSS_REPORT_ITEM_FORM_CONFIG_COMMON.TASK_NAME,
+  LOSS_REPORT_ITEM_FORM_CONFIG_COMMON.IS_LOSS,
+  LOSS_REPORT_ITEM_FORM_CONFIG_COMMON.CREATED_BY,
+];
+
+// 创建损失记录表单信息(有损失)
+export const LOSS_REPORT_ITEM_FORM_CONFIG_LOSS: FormConfig[] = [
+  LOSS_REPORT_ITEM_FORM_CONFIG_COMMON.TASK_NAME,
+  LOSS_REPORT_ITEM_FORM_CONFIG_COMMON.IS_LOSS,
   {
     label: '损失楼号、楼层、房间号',
     prop: 'affectedRoom',
@@ -136,7 +157,10 @@ export const LOSS_REPORT_ITEM_FORM_CONFIG: FormConfig[] = [
   {
     label: '受灾物品',
     prop: 'affectedItems',
-    slot: 'affectedItems',
+    component: 'ElInput',
+    componentProps: {
+      placeholder: '请输入受灾物品',
+    },
   },
   {
     label: '受灾图片',
@@ -146,7 +170,14 @@ export const LOSS_REPORT_ITEM_FORM_CONFIG: FormConfig[] = [
   {
     label: '损失描述',
     prop: 'description',
-    slot: 'description',
+    component: 'ElInput',
+    componentProps: {
+      placeholder: '请输入损失描述',
+      type: 'textarea',
+      rows: 4,
+      maxlength: 1000,
+      showWordLimit: true,
+    },
   },
   {
     label: '影响安全评估',
@@ -186,16 +217,16 @@ export const LOSS_REPORT_ITEM_FORM_CONFIG: FormConfig[] = [
   {
     label: '备注',
     prop: 'remark',
-    slot: 'remark',
-  },
-  {
-    label: '创建人',
-    prop: 'createdBy',
     component: 'ElInput',
     componentProps: {
-      disabled: true,
+      placeholder: '请输入备注',
+      type: 'textarea',
+      rows: 4,
+      maxlength: 1000,
+      showWordLimit: true,
     },
   },
+  LOSS_REPORT_ITEM_FORM_CONFIG_COMMON.CREATED_BY,
 ];
 
 // 通用表单数据
@@ -218,7 +249,7 @@ export const DISPOSAL_MANAGEMENT_TASK_FROM_DATA_EDIT = {
 };
 export const LOSS_REPORT_ITEM_FORM_DATA = {
   reportTaskName: '',
-  isLoss: null,
+  isLoss: 1,
   buildingNo: '',
   floorNo: '',
   roomNo: '',
@@ -227,13 +258,14 @@ export const LOSS_REPORT_ITEM_FORM_DATA = {
   description: '',
   safetyLevel: '',
   isAffectWork: null,
-  estimatedLoss: 0,
+  estimatedLoss: null,
   responsibleDeptId: null,
   userGroupList: [],
-  isPush: null,
-  priority: null,
-  remark: '',
+  isPush: 1,
+  priority: '',
   createdBy: '',
+  remark: '',
+  affectedRoom: '永远存在', //自己创造的一个数值,不要传给后端 这个数值永远存在
 };
 
 // 通用表单规则
@@ -267,7 +299,19 @@ export const DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_EDIT = {
   ...DISPOSAL_MANAGEMENT_BASIC_FROM_RULES,
 };
 
-// 创建损失记录表单规则(无损失)
+// 创建损失记录表单规则
 export const LOSS_REPORT_ITEM_FROM_RULES = {
   isLoss: [{ required: true, message: '请选择是否损失', trigger: 'change' }],
+  affectedRoom: [{ required: true, message: '', trigger: 'blur' }],
+  buildingNo: [{ required: true, message: '请输入楼号', trigger: 'blur' }],
+  floorNo: [{ required: true, message: '请输入楼层', trigger: 'blur' }],
+  roomNo: [{ required: true, message: '请输入房间号', trigger: 'blur' }],
+  affectedItems: [{ required: true, message: '请输入受灾物品', trigger: 'blur' }],
+  description: [{ required: true, message: '请输入损失描述', trigger: 'blur' }],
+  safetyLevel: [{ required: true, message: '请选择影响安全评估', trigger: 'change' }],
+  isAffectWork: [{ required: true, message: '请选择是否影响正常工作', trigger: 'change' }],
+  priority: [{ required: true, message: '请选择处置优先级', trigger: 'change' }],
+  responsibleDeptId: [{ required: true, message: '请选择整改责任部门', trigger: 'change' }],
+  userGroupList: [{ required: true, message: '请选择整改责任人', trigger: 'change' }],
+  isPush: [{ required: true, message: '请选择是否推送', trigger: 'change' }],
 };

+ 4 - 2
src/views/disaster/disaster-control/src/config/index.ts

@@ -20,7 +20,8 @@ import {
   DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_CREATE,
   DISPOSAL_MANAGEMENT_ITEM_FROM_CONFIG_EDIT,
   DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_EDIT,
-  LOSS_REPORT_ITEM_FORM_CONFIG,
+  LOSS_REPORT_ITEM_FORM_CONFIG_LOSS,
+  LOSS_REPORT_ITEM_FORM_CONFIG_NO_LOSS,
   LOSS_REPORT_ITEM_FORM_DATA,
   LOSS_REPORT_ITEM_FROM_RULES,
 } from './form';
@@ -43,7 +44,8 @@ export {
   DISPOSAL_MANAGEMENT_ITEM_FROM_RULES_EDIT,
   DISPOSAL_RECTIFICATION_SEARCH_CONFIG,
   DISPOSAL_MANAGEMENT_TASK_FROM_DATA_EDIT,
-  LOSS_REPORT_ITEM_FORM_CONFIG,
+  LOSS_REPORT_ITEM_FORM_CONFIG_LOSS,
+  LOSS_REPORT_ITEM_FORM_CONFIG_NO_LOSS,
   LOSS_REPORT_ITEM_FORM_DATA,
   LOSS_REPORT_ITEM_FROM_RULES,
 };

+ 1 - 6
src/views/disaster/disaster-control/src/config/search.ts

@@ -7,7 +7,6 @@ import {
   TASK_STAGE_OPTIONS_DISPOSAL_MANAGEMENT,
   TASK_STAGE_OPTIONS_REPORT_TASK,
   FIX_STATUS_OPTIONS,
-  PRIORITY_STATUS_OPTIONS,
 } from '../constant';
 
 // 通用搜索配置
@@ -78,11 +77,7 @@ export const DISPOSAL_RECTIFICATION_SEARCH_CONFIG: SearchConfig[] = [
   {
     label: '优先级',
     prop: 'priority',
-    component: 'ElSelect',
-    selectOptions: PRIORITY_STATUS_OPTIONS,
-    componentProps: {
-      placeholder: '请选择优先级',
-    },
+    slot: 'priority',
   },
   BASIC_SEARCH_CONFIG.FIX_STATUS,
 ];

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

@@ -19,11 +19,6 @@ export enum FIX_STATUS {
   TEMPORARY_CLOSED,
 }
 
-export enum PRIORITY_STATUS {
-  NORMAL = 0,
-  URGENT,
-}
-
 export enum IS_LOSS {
   NO_LOSS = 0,
   LOSS,
@@ -56,17 +51,6 @@ export const TASK_STAGE_OPTIONS_DISPOSAL_MANAGEMENT = [
   ...TASK_STAGE_OPTIONS_BASIC,
 ];
 
-export const PRIORITY_STATUS_OPTIONS = [
-  {
-    label: '优先处理',
-    value: PRIORITY_STATUS.URGENT,
-  },
-  {
-    label: '正常处理',
-    value: PRIORITY_STATUS.NORMAL,
-  },
-];
-
 export const TASK_STAGE_OPTIONS_REPORT_TASK = [...TASK_STAGE_OPTIONS_BASIC];
 
 export const FIX_STATUS_OPTIONS = [

+ 31 - 0
src/views/disaster/disaster-control/src/hook.ts

@@ -0,0 +1,31 @@
+/**
+ * 灾害处置公用hook
+ */
+
+import { ref } from 'vue';
+import { queryDictTypeDetail } from '@/api/dict';
+import type { SysDictDataDetail } from '@/api/dict';
+import { DICT_CODE } from '@/constant/dict';
+
+export const useDisasterControlHook = () => {
+  const safetyLevelDice = ref<SysDictDataDetail[]>([]);
+  const priorityDice = ref<SysDictDataDetail[]>([]);
+  const getSafetyLevelDict = async () => {
+    const res = await queryDictTypeDetail(DICT_CODE.SAFETY_LEVEL);
+    safetyLevelDice.value = res.sysDictDataList;
+  };
+  const getPriorityDict = async () => {
+    const res = await queryDictTypeDetail(DICT_CODE.PRIORITY);
+    priorityDice.value = res.sysDictDataList;
+  };
+  const getPriority = (priorityCode: string) => {
+    return priorityDice.value.find((item) => item.itemCode === priorityCode)?.itemValue;
+  };
+  return {
+    priorityDice,
+    safetyLevelDice,
+    getPriorityDict,
+    getSafetyLevelDict,
+    getPriority,
+  };
+};

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

@@ -1,5 +1,4 @@
 @use '@/styles/variables.scss' as *;
-$priority-urgent-color: #ff4d4f;
 .collapse-container {
   display: flex;
   flex-direction: column;
@@ -28,11 +27,6 @@ $priority-urgent-color: #ff4d4f;
   display: flex;
   justify-content: flex-end;
 }
-.priority-container {
-  &--urgent {
-    color: $priority-urgent-color;
-  }
-}
 .affected-items-container {
   width: 100%;
   overflow: hidden;

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

@@ -1,3 +1,7 @@
 :deep(.el-date-editor) {
   --el-date-editor-width: 100%;
 }
+
+.affected-room-container {
+  display: flex;
+}

+ 1 - 5
src/views/disaster/disaster-control/src/util.ts

@@ -1,4 +1,4 @@
-import { TASK_STAGE_OPTIONS_DISPOSAL_MANAGEMENT, PRIORITY_STATUS_OPTIONS, FIX_STATUS_OPTIONS } from './constant';
+import { TASK_STAGE_OPTIONS_DISPOSAL_MANAGEMENT, FIX_STATUS_OPTIONS } from './constant';
 
 // 获取任务阶段
 export const getTaskStage = (taskStage: number) => {
@@ -8,7 +8,3 @@ export const getTaskStage = (taskStage: number) => {
 export const getfixStatus = (fixStatus: number) => {
   return FIX_STATUS_OPTIONS.find((item) => item.value === fixStatus)?.label;
 };
-
-export const getPriorityStatus = (priorityStatus: number) => {
-  return PRIORITY_STATUS_OPTIONS.find((item) => item.value === priorityStatus)?.label;
-};

+ 3 - 1
src/views/disaster/disaster-precaution/PageTaskItem.vue

@@ -5,7 +5,9 @@
       <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
     </header>
     <main class="disaster-precaution-container__main">
-      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+      <section>
+        <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+      </section>
     </main>
     <footer class="disaster-precaution-container__footer" v-if="operate">
       <el-button @click="router.back()">取消</el-button>