Kaynağa Gözat

用更新时间

chauncey 11 ay önce
ebeveyn
işleme
f12f48666f

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

@@ -12,6 +12,7 @@ import type {
   DisasterReportCreateQuery,
   DisasterReportEditQuery,
   LossRecordCreateQuery,
+  LossRecordEditQuery,
 } from '@/types/disaster-control';
 import type { QueryPageResponse, QueryPageRequest } from '@/types/disaster';
 /**
@@ -148,12 +149,23 @@ export const createLossRecord = (query: LossRecordCreateQuery) => {
   });
 };
 
+/**
+ * 编辑损失记录
+ */
+export const editLossRecord = (query: LossRecordEditQuery) => {
+  return http.request({
+    url: '/disasterHandle/updateLossRecord',
+    method: 'put',
+    data: query,
+  });
+};
+
 /**
  * 删除损失记录
  */
-export const deleteLossRecord = (reportTaskId: number) => {
+export const deleteLossRecord = (reportRecordId: number) => {
   return http.request({
-    url: `/disasterHandle/deleteLossRecord?reportTaskId=${reportTaskId}`,
+    url: `/disasterHandle/deleteLossRecord?reportRecordId=${reportRecordId}`,
     method: 'delete',
   });
 };

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

@@ -1,4 +1,9 @@
-import type { PersonGroupItem } from '@/types/person-group/type';
+export interface ImageItem {
+  url: string;
+  name?: string;
+  size?: number;
+  file?: File;
+}
 
 export interface DisposalManagementListQuery {
   reporterId?: number;
@@ -54,6 +59,10 @@ export interface disasterReportRecordDetailListResponse {
   priority: string;
   fixStatus: number;
   isLoss: number;
+  userGroupList: string;
+  createdBy: string;
+  images: string;
+  fixerList: string;
 }
 
 export interface DisposalManagementTableResponse {
@@ -113,19 +122,22 @@ export interface DisposalManagementRuleFormEdit extends Omit<DisposalManagementC
 }
 
 export interface LossReportItemFormData
-  extends Omit<disasterReportRecordDetailListResponse, 'id' | 'updatedAt' | 'responsibleDeptName' | 'fixStatus'> {
+  extends Omit<
+    disasterReportRecordDetailListResponse,
+    'id' | 'updatedAt' | 'responsibleDeptName' | 'fixStatus' | 'userGroupList' | 'images' | 'fixerList'
+  > {
   reportTaskName: string;
-  images: string[];
   description: string;
   safetyLevel: string;
   isAffectWork: number | null;
-  estimatedLoss: number | null;
+  estimatedLoss: string | null;
   responsibleDeptId: number | null;
   userGroupList: number[];
   isPush: number;
-  createdBy: string;
   remark: string;
   affectedRoom: string; //自己创造的一个数值,不要传给后端
+  images: string[];
+  uploadImages: File[];
 }
 
 export interface LossRecordFormData {
@@ -135,19 +147,24 @@ export interface LossRecordFormData {
   floorNo?: string;
   roomNo?: string;
   affectedItems?: string;
-  images?: File[];
+  images?: string[];
   description?: string;
   safetyLevel?: string;
   isAffectWork?: number;
-  estimatedLoss?: number;
+  estimatedLoss?: string;
   priority?: string;
   responsibleDeptId?: number;
   remark?: string;
   userGroupList?: number[];
   isPush?: number;
+  uploadImages?: File[];
 }
 
 export interface LossRecordCreateQuery extends Omit<LossRecordFormData, 'images'> {
   reportTaskId: number;
   images?: string[];
 }
+
+export interface LossRecordEditQuery extends Omit<LossRecordCreateQuery, 'reportTaskId'> {
+  id: number;
+}

+ 1 - 0
src/types/disaster-precaution/index.ts

@@ -28,6 +28,7 @@ export interface TaskManagementListResponse extends BasicResponse {
 
 export interface TaskExecutionListResponse extends BasicResponse {
   userTypeList: USER_TYPE[];
+  updatedAt: string;
 }
 
 export interface TaskManagementItemResponse

+ 1 - 0
src/types/disaster-warning/index.ts

@@ -43,4 +43,5 @@ export interface DefenseNoticeDetailResponse
     Omit<DefenseNoticeListResponse, 'effectState' | 'updatedAt'> {
   content: string;
   attachmentListRes: FileItem[];
+  pushName: string;
 }

+ 1 - 2
src/views/disaster/components/InspectorSelect.vue

@@ -67,9 +67,8 @@
   import empty from 'assets/images/empty@1X.png';
   import type { TreeNode } from '@/views/disaster/types';
   import type { PersonGroupItem } from '@/types/person-group/type';
-  import { ElMessage, type ElTree } from 'element-plus';
+  import type { ElTree } from 'element-plus';
   import { useUserInfoHook } from '@/views/disaster/hooks/userInfo';
-  import { updateTaskInspector } from '@/api/disaster-precaution';
 
   const { getUserFirstLevelTreeList, treeData, id: userId } = useUserInfoHook();
 

+ 54 - 17
src/views/disaster/disaster-control/PageDisposalRectification.vue

@@ -31,44 +31,53 @@
             </div>
             <template v-else>
               <CollapseItem
+                ref="collapseItemRef"
                 v-for="item in collapseList"
                 :key="item.id"
                 :name="item.taskName"
-                :defaultOpen="item.id === 1"
+                :defaultOpen="item.id === collapseList[0].id"
               >
                 <template #viewOperation> <img :src="ViewDocument" class="collapse-item__icon" /> </template>
                 <template #main-table>
                   <BasicTable :tableData="item.tableData[0].disasterReportRecordDetailList" :tableConfig="tableConfig">
                     <template #affectedArea="scope">
                       <div class="affected-area-container">
-                        <span>{{ scope.row.buildingNo + scope.row.floorNo + scope.row.roomNo }}</span>
+                        <span>{{ scope.row.buildingNo }}-{{ scope.row.floorNo }}-{{ scope.row.roomNo }}</span>
                       </div>
                     </template>
                     <template #affectedItems="scope">
-                      <el-tooltip :content="scope.row.affectedItems" placement="top-start" effect="light">
+                      <el-tooltip
+                        :content="scope.row.affectedItems"
+                        placement="top-start"
+                        effect="light"
+                        v-if="scope.row.affectedItems"
+                      >
                         <div class="affected-items-container">
                           <span>{{ scope.row.affectedItems }}</span>
                         </div>
                       </el-tooltip>
+                      <span v-else>--</span>
+                    </template>
+                    <template #responsibleDeptName="scope">
+                      <span v-if="scope.row.responsibleDeptName">{{ scope.row.responsibleDeptName }}</span>
+                      <span v-else>--</span>
                     </template>
                     <template #priority="scope">
-                      <span>{{ getPriority(scope.row.priority) }}</span>
+                      <span v-if="scope.row.priority">{{ getPriority(scope.row.priority) }}</span>
+                      <span v-else>--</span>
                     </template>
                     <template #fixStatus="scope">
-                      <div class="fix-status-container">
-                        <span>{{ getfixStatus(scope.row.fixStatus) }}</span>
-                      </div>
+                      <span v-if="scope.row.fixStatus">{{ getfixStatus(scope.row.fixStatus) }}</span>
+                      <span v-else>--</span>
                     </template>
                     <template #action="scope">
-                      <div class="action-container" v-if="scope.row.fixStatus === FIX_STATUS.TO_BE_RECTIFIED">
-                        <ActionButton text="查看" />
-                        <ActionButton text="去整改" />
-                        <ActionButton text="添加整改人" />
-                      </div>
-                      <div class="action-container" v-else>
-                        <ActionButton text="查看" />
-                        <ActionButton text="去整改" />
-                      </div>
+                      <ActionButton text="查看" />
+                      <ActionButton text="去整改" />
+                      <ActionButton
+                        text="添加整改人"
+                        v-if="scope.row.fixStatus === FIX_STATUS.TO_BE_RECTIFIED"
+                        @click="handleAddFixer(scope.row.id, scope.row.fixerList)"
+                      />
                     </template>
                   </BasicTable>
                 </template>
@@ -90,6 +99,9 @@
         </section>
       </div>
     </main>
+    <el-dialog v-model="userInfo" title="添加整改人" destroy-on-close>
+      <InspectorSelect :customUserList="currentTaskInspectorList" @cancel="userInfo = false" />
+    </el-dialog>
   </div>
 </template>
 
@@ -97,7 +109,8 @@
   import Search from '@/views/disaster/components/Search.vue';
   import CollapseItem from './src/components/CollapseItem.vue';
   import BasicTable from '@/components/BasicTable.vue';
-  import { onMounted, reactive, ref } from 'vue';
+  import InspectorSelect from '@/views/disaster/components/InspectorSelect.vue';
+  import { nextTick, 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, FIX_STATUS } from './src/constant';
@@ -115,14 +128,20 @@
   import Empty from 'assets/images/empty@1X.png';
   import ViewDocument from './src/svg/view-document.svg';
   import { useDisasterControlHook } from './src/hook';
+  import type { PersonGroupItem } from '@/types/person-group/type';
+  import { queryUserInfoByIds } from '@/api/system/person-group';
 
   const { getPriority, getPriorityDict, priorityDice } = useDisasterControlHook();
+  const collapseItemRef = ref<InstanceType<typeof CollapseItem>[]>([]);
 
   const searchData = reactive({
     priority: '',
     fixStatus: '',
   });
 
+  const userInfo = ref(false);
+  const currentTaskInspectorList = ref<PersonGroupItem[]>([]);
+
   const currentPage = ref(1);
   const pageSize = ref(DEFAULT_PAGE_SIZE);
   const total = ref(0);
@@ -180,6 +199,9 @@
     taskIds.value = collapseList.value.map((item) => item.id);
     total.value = res.totalRow;
     collapseLoading.value = false;
+    nextTick(() => {
+      collapseItemRef.value[0]?.openFirstCollapseItem();
+    });
   };
 
   const getDisposalTableData = async () => {
@@ -194,6 +216,21 @@
     tableConfig.loading = false;
   };
 
+  const currentTaskId = ref<number>();
+  const handleAddFixer = async (id: number, fixerList: string) => {
+    currentTaskId.value = id;
+    const userIds = JSON.parse(fixerList) || [];
+    if (!userIds.length) return;
+    const res = await queryUserInfoByIds(userIds);
+    currentTaskInspectorList.value = res.map((user) => {
+      return {
+        ...user,
+        checked: true,
+      };
+    });
+    userInfo.value = true;
+  };
+
   const isViewTask = (disasterReportTaskInfoList: disasterReportTaskInfoListResponse[]) => {
     return disasterReportTaskInfoList.some((item) => item.status === ACTIVE_STATUS.ACTIVE);
   };

+ 23 - 4
src/views/disaster/disaster-control/PageLossReportItem.vue

@@ -23,13 +23,14 @@
   import { useRouter, useRoute } from 'vue-router';
   import BackIcon from 'assets/svg/back.svg';
   import { LossRecordFormData } from '@/types/disaster-control';
-  import { createLossRecord } from '@/api/disaster-control';
+  import { createLossRecord, editLossRecord } from '@/api/disaster-control';
   import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
   import { ElMessage } from 'element-plus';
+  import UploadLoading from '@/components/UploadLoading.vue';
 
   const router = useRouter();
   const route = useRoute();
-  const id = Number(route.params.id);
+  const reportTaskId = Number(route.params.id);
   const dynamicComponentRef = ref();
   const operate = route.query.operation;
   const headerTitle = computed(() => {
@@ -42,6 +43,8 @@
   const dynamicComponent = computed(() => {
     if (operate === 'create') {
       return defineAsyncComponent(() => import('./src/components/CreateLossReportItem.vue'));
+    } else if (operate === 'edit') {
+      return defineAsyncComponent(() => import('./src/components/EditLossReportItem.vue'));
     } else {
       return '';
     }
@@ -55,15 +58,28 @@
   };
   const createLossReportFunc = async (formData: LossRecordFormData) => {
     const imagesListRes: string[] = await Promise.all(
-      (formData.images || []).map((item) => formatAttachmentList(item)),
+      (formData.uploadImages || []).map((item) => formatAttachmentList(item)),
     );
     const createParam = {
-      reportTaskId: id,
+      reportTaskId,
       ...formData,
       images: imagesListRes,
     };
     await createLossRecord(createParam);
   };
+
+  const editLossReportFunc = async (formData: LossRecordFormData) => {
+    const imagesListRes: string[] = await Promise.all(
+      (formData.uploadImages || []).map((item) => formatAttachmentList(item)),
+    );
+    formData.images = [...(formData.images || []), ...imagesListRes];
+    const editParam = {
+      id: reportTaskId,
+      ...formData,
+    };
+    await editLossRecord(editParam);
+  };
+
   const handleSubmit = async () => {
     const validateResult = await dynamicComponentRef.value?.validateForm();
     if (!validateResult) return;
@@ -74,6 +90,9 @@
       if (operate === 'create') {
         await createLossReportFunc(formData);
         message = '创建成功';
+      } else {
+        await editLossReportFunc(formData);
+        message = '编辑成功';
       }
       ElMessage.success(message);
       return true; // 成功时返回true

+ 10 - 6
src/views/disaster/disaster-control/src/components/CreateLossReportItem.vue

@@ -21,7 +21,7 @@
         </div>
       </template>
       <template #affectedImages>
-        <UploadImages v-model:fileList="ruleFormData.images" :maxCount="9" ref="uploadImagesRef" />
+        <UploadImages :maxCount="9" ref="uploadImagesRef" @uploadSuccess="handleUploadSuccess" />
       </template>
       <template #safetyLevel>
         <el-select v-model="ruleFormData.safetyLevel" placeholder="请选择影响安全评估">
@@ -123,11 +123,12 @@
       if (cleanValue === '' || cleanValue === '.') {
         ruleFormData.estimatedLoss = null;
       } else {
-        ruleFormData.estimatedLoss = Number(cleanValue);
+        // 直接保存字符串形式,在提交表单时再转换为数字
+        ruleFormData.estimatedLoss = cleanValue;
       }
     } else {
-      // 输入合法
-      ruleFormData.estimatedLoss = value ? Number(value) : null;
+      // 输入合法,直接保存字符串
+      ruleFormData.estimatedLoss = value;
     }
   };
 
@@ -137,8 +138,8 @@
     if (ruleFormData.estimatedLoss !== null) {
       const strValue = String(ruleFormData.estimatedLoss);
       if (strValue.endsWith('.')) {
-        // 移除结尾的小数点
-        ruleFormData.estimatedLoss = Number(strValue.slice(0, -1));
+        // 移除结尾的小数点,但仍保持为字符串
+        ruleFormData.estimatedLoss = strValue.slice(0, -1);
       }
     }
   };
@@ -180,6 +181,9 @@
       isLoss: ruleFormData.isLoss,
     };
   };
+  const handleUploadSuccess = (files: File[]) => {
+    ruleFormData.uploadImages = files;
+  };
   const initBasicFormData = () => {
     ruleFormData.reportTaskName = taskName;
     ruleFormData.createdBy = realname;

+ 235 - 0
src/views/disaster/disaster-control/src/components/EditLossReportItem.vue

@@ -0,0 +1,235 @@
+<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
+          :maxCount="9"
+          :imageList="ruleFormData.images"
+          @uploadSuccess="handleUploadSuccess"
+          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 type { DeptTreeItem } from '@/types/dept/type';
+  import { getAllDepartments } from '@/api/auth/dept';
+  import { queryUserInfoByIds } from '@/api/system/person-group';
+  import { formatDeptTree } from '@/views/disaster/utils/formatDeptTree';
+  import { useDisasterControlHook } from '../hook';
+
+  const { safetyLevelDice, priorityDice, getSafetyLevelDict, getPriorityDict, getLossReportItem } =
+    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 = cleanValue;
+      }
+    } else {
+      // 输入合法
+      ruleFormData.estimatedLoss = value;
+    }
+  };
+
+  // 处理失去焦点时,如果是小数点结尾则删除小数点
+  const handleEstimatedLossChange = () => {
+    // 检查当前值是否为字符串且以小数点结尾
+    if (ruleFormData.estimatedLoss !== null) {
+      const strValue = String(ruleFormData.estimatedLoss);
+      if (strValue.endsWith('.')) {
+        // 移除结尾的小数点
+        ruleFormData.estimatedLoss = strValue.slice(0, -1);
+      }
+    }
+  };
+
+  const route = useRoute();
+  const reportTaskId = Number(route.query.id);
+  const id = Number(route.params.id);
+  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 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 getLossReportItemData = async () => {
+    const res = await getLossReportItem(reportTaskId, id);
+    if (!res) return;
+    const userInfo = await queryUserInfoByIds([Number(res.createdBy)]);
+    for (const key in ruleFormData) {
+      if (key in res) {
+        ruleFormData[key] = res[key];
+        ruleFormData.userGroupList = JSON.parse(res.userGroupList) || [];
+        ruleFormData.createdBy = userInfo[0].realname;
+        ruleFormData.images = JSON.parse(res.images) || [];
+      }
+    }
+    cloneRuleFormData();
+  };
+
+  const handleUploadSuccess = (files: File[]) => {
+    ruleFormData.uploadImages = files;
+  };
+  defineExpose({
+    validateForm,
+    getFormData,
+  });
+  onMounted(() => {
+    getLossReportItemData();
+    getSafetyLevelDict();
+    getPriorityDict();
+    getDeptList();
+    getUserGroupList();
+    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>

+ 49 - 8
src/views/disaster/disaster-control/src/components/LossRecord.vue

@@ -49,28 +49,54 @@
               <BasicTable :tableData="item.tableData[0].disasterReportRecordDetailList" :tableConfig="tableConfig">
                 <template #affectedArea="scope">
                   <div class="affected-area-container">
-                    <span>{{ scope.row.buildingNo + scope.row.floorNo + scope.row.roomNo }}</span>
+                    <span>{{ scope.row.buildingNo }}-{{ scope.row.floorNo }}-{{ scope.row.roomNo }}</span>
                   </div>
                 </template>
                 <template #affectedItems="scope">
-                  <el-tooltip :content="scope.row.affectedItems" placement="top-start" effect="light">
+                  <el-tooltip
+                    :content="scope.row.affectedItems"
+                    placement="top-start"
+                    effect="light"
+                    v-if="scope.row.affectedItems"
+                  >
                     <div class="affected-items-container">
                       <span>{{ scope.row.affectedItems }}</span>
                     </div>
                   </el-tooltip>
+                  <span v-else>无损失</span>
+                </template>
+                <template #responsibleDeptName="scope">
+                  <span v-if="scope.row.responsibleDeptName">{{ scope.row.responsibleDeptName }}</span>
+                  <span v-else>--</span>
                 </template>
                 <template #priority="scope">
-                  <span>{{ getPriority(scope.row.priority) }}</span>
+                  <span v-if="scope.row.priority">{{ getPriority(scope.row.priority) }}</span>
+                  <span v-else>--</span>
                 </template>
                 <template #fixStatus="scope">
                   <div class="fix-status-container">
-                    <span>{{ getfixStatus(scope.row.fixStatus) }}</span>
+                    <span v-if="scope.row.fixStatus">{{ getfixStatus(scope.row.fixStatus) }}</span>
+                    <span v-else>--</span>
                   </div>
                 </template>
                 <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="删除" @click="handleDelete(scope.row.id)" />
+                  <div class="action-container" v-if="scope.row.affectedItems">
+                    <ActionButton
+                      text="编辑"
+                      v-if="scope.row.fixStatus === FIX_STATUS.TO_BE_RECTIFIED"
+                      @click="handleEdit(scope.row.id, item.id)"
+                    />
+                    <ActionButton text="查看" />
+                    <ActionButton
+                      text="删除"
+                      v-if="scope.row.fixStatus === FIX_STATUS.TO_BE_RECTIFIED"
+                      @click="handleDelete(scope.row.id)"
+                    />
+                  </div>
+                  <div class="action-container" v-else>
+                    <ActionButton text="编辑" @click="handleEdit(scope.row.id, item.id)" />
+                    <ActionButton text="删除" @click="handleDelete(scope.row.id)" />
+                  </div>
                 </template>
               </BasicTable>
             </template>
@@ -189,9 +215,11 @@
     await getDisposalTableData();
   };
 
+  const defaultName = 'disaster-control-loss-report-item';
+
   const handleReport = (handleTaskId: number, taskName: string) => {
     router.push({
-      name: 'disaster-control-loss-report-item',
+      name: defaultName,
       params: {
         id: handleTaskId,
       },
@@ -199,6 +227,19 @@
     });
   };
 
+  const handleEdit = (handleTaskId: number, id: number) => {
+    router.push({
+      name: defaultName,
+      params: {
+        id: handleTaskId,
+      },
+      query: {
+        id,
+        operation: 'edit',
+      },
+    });
+  };
+
   const handleDelete = async (id: number) => {
     await deleteLossRecord(id);
     await getDisposalData();

+ 20 - 13
src/views/disaster/disaster-control/src/components/UploadImages.vue

@@ -46,16 +46,10 @@
 </template>
 
 <script lang="ts" setup>
-  import { ref, reactive, computed } from 'vue';
+  import { ref, reactive, computed, watch } 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;
-  }
+  import type { ImageItem } from '@/types/disaster-control';
 
   const props = defineProps({
     maxCount: {
@@ -70,9 +64,11 @@
       type: Array as () => string[],
       default: () => ['.jpg', '.jpeg', '.png'],
     },
+    imageList: {
+      type: Array as () => string[],
+    },
   });
-
-  const emit = defineEmits(['update:fileList', 'change']);
+  const emit = defineEmits(['uploadSuccess']);
 
   const fileInput = ref<HTMLInputElement | null>(null);
   const uploadedImages = reactive<ImageItem[]>([]);
@@ -198,10 +194,21 @@
   });
 
   const emitChange = () => {
-    const files = uploadedImages.map((item) => item.file);
-    emit('update:fileList', files);
-    emit('change', files);
+    const files = uploadedImages.filter((item) => item.file).map((item) => item.file);
+    emit('uploadSuccess', files);
   };
+  watch(
+    () => props.imageList,
+    (newVal) => {
+      if (!newVal) return;
+      const urlList = newVal.map((item) => {
+        return {
+          url: item,
+        };
+      });
+      uploadedImages.push(...urlList);
+    },
+  );
 </script>
 
 <style lang="scss" scoped>

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

@@ -266,6 +266,7 @@ export const LOSS_REPORT_ITEM_FORM_DATA = {
   createdBy: '',
   remark: '',
   affectedRoom: '永远存在', //自己创造的一个数值,不要传给后端 这个数值永远存在
+  uploadImages: [],
 };
 
 // 通用表单规则

+ 1 - 0
src/views/disaster/disaster-control/src/config/table.ts

@@ -120,6 +120,7 @@ export const LOSS_RECORD_TABLE_COLUMNS: TableColumnProps[] = [
     label: '整改部门',
     prop: 'responsibleDeptName',
     align: 'center',
+    slot: 'responsibleDeptName',
   },
   {
     label: '优先级',

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

@@ -6,6 +6,7 @@ import { ref } from 'vue';
 import { queryDictTypeDetail } from '@/api/dict';
 import type { SysDictDataDetail } from '@/api/dict';
 import { DICT_CODE } from '@/constant/dict';
+import { getLossRecordTableData } from '@/api/disaster-control';
 
 export const useDisasterControlHook = () => {
   const safetyLevelDice = ref<SysDictDataDetail[]>([]);
@@ -21,11 +22,19 @@ export const useDisasterControlHook = () => {
   const getPriority = (priorityCode: string) => {
     return priorityDice.value.find((item) => item.itemCode === priorityCode)?.itemValue;
   };
+  const getLossReportItem = async (handleTaskId: number, id: number) => {
+    const res = await getLossRecordTableData({
+      handleTaskIds: [handleTaskId],
+    });
+    const disasterReportRecordDetailList = res[0].disasterReportRecordDetailList;
+    return disasterReportRecordDetailList.find((item) => item.id === id);
+  };
   return {
     priorityDice,
     safetyLevelDice,
     getPriorityDict,
     getSafetyLevelDict,
     getPriority,
+    getLossReportItem,
   };
 };

+ 4 - 4
src/views/disaster/disaster-precaution/PageTaskExecution.vue

@@ -68,7 +68,7 @@
               <!-- 仅审批人员可以看到 -->
               <ActionButton
                 v-if="
-                  scope.row.userTypeList.includes(USER_TYPE.APPROVER) && !isOverdue24Hours(scope.row.dueCompleteTime)
+                  scope.row.userTypeList.includes(USER_TYPE.APPROVER) && !isOverdue24Hours(scope.row.updatedAt)
                 "
                 text="撤回"
                 :popconfirm="{
@@ -214,10 +214,10 @@
     getTableData();
   };
   // 判断是否超过应完成时间24小时
-  const isOverdue24Hours = (dueCompleteTime: string) => {
-    if (!dueCompleteTime) return false;
+  const isOverdue24Hours = (updatedAt: string) => {
+    if (!updatedAt) return false;
 
-    const dueTime = new Date(dueCompleteTime).getTime();
+    const dueTime = new Date(updatedAt).getTime();
     const currentTime = refreshTime.value;
 
     // 计算24小时的毫秒数: 24 * 60 * 60 * 1000 = 86400000

+ 5 - 3
src/views/disaster/disaster-warning/src/components/ViewDefenseNoticeItem.vue

@@ -14,8 +14,9 @@
       </div>
       <span class="publish-info">
         <p class="info-item">
-          创建人:<span class="info-content">
-            {{ defenseNoticeDetail?.realname }} {{ defenseNoticeDetail?.pushTime }}
+          <span>{{ defenseNoticeDetail?.pushTime? '发布人:': '创建人:' }}</span>
+          <span class="info-content">
+            {{  defenseNoticeDetail?.pushTime? defenseNoticeDetail.pushName : defenseNoticeDetail?.realname }} {{ defenseNoticeDetail?.pushTime }}
           </span>
         </p>
       </span>
@@ -25,7 +26,7 @@
       <div v-html="defenseNoticeDetail?.content"></div>
     </section>
     <section class="attachment">
-      <span class="info-content">附件({{ defenseNoticeDetail?.attachmentListRes.length }})</span>
+      <span class="info-content">附件({{ defenseNoticeDetail?.attachmentListRes.length }})</span>
       <a @click="downloadAll">下载全部</a>
       <div class="attachment-list">
         <div
@@ -139,6 +140,7 @@
     a {
       color: $primary-color;
       cursor: pointer;
+      
     }
   }
   .attachment-list {