Explorar o código

处置整改完成

chauncey hai 10 meses
pai
achega
27328766b8

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

@@ -217,3 +217,20 @@ export const getDisasterLossDetail = (data: DisasterLossDetailQuery) => {
     data,
   });
 };
+
+/**
+ * 导出损失明细xml
+ */
+export const exportLossRecordToXML = (data: DisasterLossDetailQuery) => {
+  return http.request(
+    {
+      url: '/disasterHandle/exportDisasterLossDetailByTask',
+      method: 'post',
+      data,
+      responseType: 'blob',
+    },
+    {
+      isTransformResponse: false,
+    },
+  );
+};

+ 15 - 0
src/api/disaster-precaution/index.ts

@@ -188,3 +188,18 @@ export const updateTaskInspector = (data: { id: number; inspectorIdList: number[
     data,
   });
 };
+
+/**
+ * 导出检查任务详情PDF
+ */
+export const exportTaskDetailPDF = (preventInspectTaskId: number) => {
+  return http.request({
+    url: `/preventInspectTask/exportTaskDetail?preventInspectTaskId=${preventInspectTaskId}`,
+    method: 'post',
+    responseType: 'blob',
+    },
+    {
+      isTransformResponse: false,
+    },
+  );
+};

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

@@ -207,11 +207,13 @@ export interface DisposalRectificationCreateQuery extends DisposalRectificationF
 
 export interface DisasterLossDetailQuery {
   handleTaskId: number;
-  reporterId?: number;
+  reportDeptId?: number;
   fixerId?: number;
+  reportRecordId?: number;
 }
 
 export interface LossRecordListDetail {
+  id: number;
   fixTaskId: number;
   affectedItems: string;
   buildingNo?: string;

+ 16 - 5
src/views/disaster/disaster-control/PageDisposalRectification.vue

@@ -49,7 +49,7 @@
                         'collapse-item__icon',
                         { 'collapse-item__icon--disabled': !item.tableData[0].disasterReportRecordDetailList.length },
                       ]"
-                      @click="handleViewTask(item.id)"
+                      @click="handleViewTask(item.id, 'task')"
                     />
                   </el-tooltip>
                 </template>
@@ -93,7 +93,9 @@
                         <div class="action-container" v-if="scope.row.fixStatus === FIX_STATUS.TO_BE_RECTIFIED">
                           <ActionButton
                             text="查看"
-                            @click="handleViewTask(item.id, scope.row.id, scope.row.fixTaskId, scope.row.deptId)"
+                            @click="
+                              handleViewTask(item.id, 'item', scope.row.fixTaskId, scope.row.deptId, scope.row.id)
+                            "
                           />
                           <ActionButton
                             text="去整改"
@@ -115,7 +117,9 @@
                         <div class="action-container" v-else>
                           <ActionButton
                             text="查看"
-                            @click="handleViewTask(item.id, scope.row.id, scope.row.fixTaskId, scope.row.deptId)"
+                            @click="
+                              handleViewTask(item.id, 'item', scope.row.fixTaskId, scope.row.deptId, scope.row.id)
+                            "
                           />
                           <ActionButton
                             text="去整改"
@@ -328,16 +332,23 @@
     });
   };
 
-  const handleViewTask = (handleTaskId: number, lossTaskId?: number, fixTaskId?: number, deptId?: number) => {
+  const handleViewTask = (
+    handleTaskId: number,
+    type: 'task' | 'item',
+    fixTaskId?: number,
+    deptId?: number,
+    reportRecordId?: number,
+  ) => {
     router.push({
       name: 'disaster-control-disposal-rectification-item-detail',
       params: {
         id: handleTaskId,
       },
       query: {
-        lossTaskId,
         fixTaskId,
         deptId,
+        reportRecordId,
+        type,
       },
     });
   };

+ 7 - 1
src/views/disaster/disaster-control/PageLossReportItem.vue

@@ -4,6 +4,7 @@
       <img :src="BackIcon" alt="back" class="back-icon" @click="router.back()" />
       <span class="disaster-precaution-container__title">{{ headerTitle }}</span>
     </header>
+    <TaskInfoSection :task-name="taskName" @export-loss-detail="exportLossDetail" v-if="!operate" />
     <main class="disaster-precaution-container__main">
       <component :is="dynamicComponent" ref="dynamicComponentRef" />
     </main>
@@ -21,6 +22,7 @@
   import { ref, computed, defineAsyncComponent } from 'vue';
   import { ElMessage } from 'element-plus';
   import UploadLoading from '@/components/UploadLoading.vue';
+  import TaskInfoSection from './src/components/TaskInfoSection.vue';
   import type { LossRecordFormData } from '@/types/disaster-control';
   import { createLossRecord, editLossRecord } from '@/api/disaster-control';
   import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
@@ -30,6 +32,7 @@
   const route = useRoute();
   const reportTaskId = Number(route.params.id);
   const id = Number(route.query.id);
+  const taskName = String(route.query.taskName);
   const dynamicComponentRef = ref();
   const operate = route.query.operation;
   const headerTitle = computed(() => {
@@ -42,13 +45,16 @@
       return `查看${fixedTitle}`;
     }
   });
+  const exportLossDetail = () => {
+    ElMessage.warning('暂未开放');
+  };
   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 '';
+      return defineAsyncComponent(() => import('./src/components/ViewLossReportItem.vue'));
     }
   });
   const formLoading = ref(false);

+ 35 - 4
src/views/disaster/disaster-control/PageViewDisposalRectification.vue

@@ -32,6 +32,7 @@
                   :damagedList="reportTask.lossRecordList"
                   :active-id="activeTaskId"
                   @update:activeId="handleActiveTask"
+                  @update:activeReportRecordId="handleActiveReportRecordId"
                 />
               </section>
               <section class="disaster-info-container">
@@ -63,6 +64,7 @@
   import Rectification from './src/components/Rectification.vue';
   import { useDisasterControlHook } from './src/hook';
   import { useUserInfoHook } from '../hooks';
+  import { exportLossRecord } from './src/util';
   import type { PersonGroupItem } from '@/types/person-group/type';
   import type { ReportTaskListDetail, LossRecordListDetail } from '@/types/disaster-control';
   import { queryUserInfoByIds } from '@/api/system/person-group';
@@ -71,12 +73,19 @@
   const router = useRouter();
   const route = useRoute();
   const handleTaskId = Number(route.params.id);
-  const { lossTaskId, fixTaskId, deptId } = route.query as unknown as {
-    lossTaskId: number;
+  const {
+    fixTaskId,
+    deptId,
+    reportRecordId,
+    type: viewType,
+  } = route.query as unknown as {
     fixTaskId: number;
     deptId: number;
+    reportRecordId: number;
+    type: 'task' | 'item';
   };
   const activeTaskId = ref<number>(Number(fixTaskId));
+  const activeReportRecordId = ref<number>(Number(reportRecordId));
 
   const handleActiveTask = (fixTaskId: number) => {
     activeTaskId.value = fixTaskId;
@@ -84,11 +93,33 @@
     lossRecordListInfo.value = lossRecordList.value.find((item) => item.fixTaskId === activeTaskId.value);
     getFixUserList(lossRecordListInfo.value?.fixPrincipals);
   };
+  const handleActiveReportRecordId = (reportRecordId: number) => {
+    activeReportRecordId.value = reportRecordId;
+  };
   const { id: fixerId } = useUserInfoHook();
   const { getDisasterLossDetailList, disasterLossDetailList } = useDisasterControlHook();
 
-  const exportLossDetail = () => {
-    ElMessage.warning('暂未开放');
+  const exportLossDetail = async () => {
+    if (!disasterLossDetailList.value) return;
+    let name;
+    const params = {
+      handleTaskId,
+      fixerId,
+    };
+    if (viewType === 'task') {
+      name = disasterLossDetailList.value?.handleTaskName;
+      await exportLossRecord(params, name);
+    } else {
+      name = lossRecordListInfo.value?.affectedItems;
+      await exportLossRecord(
+        {
+          ...params,
+          reportRecordId: activeReportRecordId.value,
+        },
+        name,
+      );
+    }
+    ElMessage.success(`导出${name}损失明细成功`);
   };
   const activeId = ref<number | null>(null);
   const handleCollapseToggle = (itemId: number) => {

+ 6 - 4
src/views/disaster/disaster-control/src/components/DamagedList.vue

@@ -7,7 +7,7 @@
         v-for="damagedItem in damagedList"
         :key="damagedItem.fixTaskId"
         :class="{ active: activeTaskId === damagedItem.fixTaskId }"
-        @click="handleActiveTask(damagedItem.fixTaskId)"
+        @click="handleActiveTask(damagedItem.fixTaskId, damagedItem.id)"
       >
         <span class="nav-item__name">{{ damagedItem.affectedItems }}</span>
       </div>
@@ -22,13 +22,15 @@
     damagedList: LossRecordListDetail[];
     activeId: number;
   }>();
-  const emit = defineEmits<{
+  const emits = defineEmits<{
     (e: 'update:activeId', value: number): void;
+    (e: 'update:activeReportRecordId', value: number): void;
   }>();
   const activeTaskId = ref<number>(props.activeId);
-  const handleActiveTask = (fixTaskId: number) => {
+  const handleActiveTask = (fixTaskId: number, reportRecordId: number) => {
     activeTaskId.value = fixTaskId;
-    emit('update:activeId', fixTaskId);
+    emits('update:activeId', fixTaskId);
+    emits('update:activeReportRecordId', reportRecordId);
   };
   watch(
     () => props.activeId,

+ 15 - 2
src/views/disaster/disaster-control/src/components/LossRecord.vue

@@ -46,6 +46,7 @@
                     'collapse-item__icon',
                     { 'collapse-item__icon--disabled': !item.tableData[0].disasterReportRecordDetailList.length },
                   ]"
+                  @click="handleView(item.handleTaskId, item.taskName)"
                 />
               </el-tooltip>
             </template>
@@ -99,7 +100,7 @@
                         v-if="isOverdue(item.dueCompleteTime) && scope.row.fixStatus === FIX_STATUS.TO_BE_RECTIFIED"
                         @click="handleEdit(item.handleTaskId, scope.row.reportTaskId, scope.row.id)"
                       />
-                      <ActionButton text="查看" />
+                      <ActionButton text="查看" @click="handleView(item.handleTaskId, item.taskName)" />
                       <ActionButton
                         text="删除"
                         v-if="scope.row.fixStatus === FIX_STATUS.TO_BE_RECTIFIED"
@@ -107,7 +108,11 @@
                       />
                     </div>
                     <div class="action-container" v-else>
-                      <ActionButton text="查看" v-if="scope.row.fixStatus === FIX_STATUS.TEMPORARY_CLOSED" />
+                      <ActionButton
+                        text="查看"
+                        v-if="scope.row.fixStatus === FIX_STATUS.TEMPORARY_CLOSED"
+                        @click="handleView(item.handleTaskId, item.taskName)"
+                      />
                       <ActionButton
                         text="编辑"
                         @click="handleEdit(item.handleTaskId, scope.row.reportTaskId, scope.row.id)"
@@ -279,6 +284,14 @@
     });
   };
 
+  const handleView = (id: number, taskName: string) => {
+    router.push({
+      name: defaultName,
+      params: { id },
+      query: { taskName },
+    });
+  };
+
   const handleDelete = async (id: number) => {
     await deleteLossRecord(id);
     await getDisposalTableData();

+ 10 - 2
src/views/disaster/disaster-control/src/components/ReportTask.vue

@@ -38,7 +38,7 @@
             scope.row.taskStage === TASK_STAGE.REPORTED_LOSS || scope.row.taskStage === TASK_STAGE.REPORTED_NO_LOSS
           "
         >
-          <ActionButton text="查看记录" />
+          <ActionButton text="查看记录" @click="handleView(scope.row.id, scope.row.taskName)" />
         </div>
         <div class="action-container" v-else-if="scope.row.taskStage === TASK_STAGE.OVERDUE">
           <span>--</span>
@@ -119,15 +119,23 @@
     }
     getTableData();
   };
+  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,
       },
       query: { taskName, operation: 'create' },
     });
   };
+  const handleView = (id: number, taskName: string) => {
+    router.push({
+      name: defaultName,
+      params: { id },
+      query: { taskName },
+    });
+  };
   const userInfo = ref(false);
   const currentTaskId = ref<number>();
   const currentTaskInspectorList = ref<PersonGroupItem[]>([]);

+ 65 - 0
src/views/disaster/disaster-control/src/components/ViewLossReportItem.vue

@@ -0,0 +1,65 @@
+<template>
+  <div class="info-container">
+    <!-- <CollapseItem
+      v-for="reportTask in disasterLossDetailList?.reportTaskList"
+      :key="reportTask.reportDeptId"
+      :name="reportTask.reportDeptName"
+      :isActive="activeId === reportTask.reportDeptId"
+      @toggle="handleCollapseToggle(reportTask.reportDeptId)"
+    > -->
+      <!-- <template #view-operation>
+        <div class="rectification-info">
+          <span class="num">{{ reportTask.lossRecordCount }}</span>
+          <span>条,整改完成{{ reportTask.fixFinishCount }}条</span>
+        </div>
+      </template>
+      <template #right-header>
+        <span class="collapse-item__header--right">
+          {{ activeId === reportTask.reportTaskId ? '收起' : '立即查看' }}
+        </span>
+      </template>
+      <template #main-table>
+        <div class="rectification-table">
+          <section class="damaged-list-container">
+            <DamagedList
+              :damagedList="reportTask.lossRecordList"
+              :active-id="activeTaskId"
+              @update:activeId="handleActiveTask"
+            />
+          </section>
+          <section class="disaster-info-container">
+            <DisasterInfo :LossReportItemFormData="lossRecordListInfo" rectification v-if="lossRecordListInfo" />
+            <Rectification
+              v-if="lossRecordListInfo?.fixRecordList"
+              :rectification-list="lossRecordListInfo?.fixRecordList"
+              :rectification-dept-name="lossRecordListInfo?.responsibleDeptName"
+              :rectification-responsible-user-list="rectificationResponsibleUserList"
+              :rectification-priority="lossRecordListInfo?.priority"
+            />
+          </section>
+        </div>
+      </template> -->
+    <!-- </CollapseItem> -->
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { useRoute } from 'vue-router';
+  import { onMounted } from 'vue';
+  import CollapseItem from './CollapseItem.vue';
+  import { useDisasterControlHook } from '../hook';
+  import { useUserInfoHook } from '@/views/disaster/hooks';
+
+  const route = useRoute();
+  const handleTaskId = Number(route.params.id);
+  const { id: reporterId } = useUserInfoHook();
+  const { getDisasterLossDetailList, disasterLossDetailList } = useDisasterControlHook();
+  onMounted(async () => {
+    await getDisasterLossDetailList({ handleTaskId, reporterId });
+    console.log(disasterLossDetailList.value);
+  });
+</script>
+
+<style lang="scss" scoped>
+  @use '@/views/disaster/style/info-container.scss' as *;
+</style>

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

@@ -1,4 +1,6 @@
 import { TASK_STAGE_OPTIONS_DISPOSAL_MANAGEMENT, FIX_STATUS_OPTIONS } from './constant';
+import type { DisasterLossDetailQuery } from '@/types/disaster-control';
+import { exportLossRecordToXML } from '@/api/disaster-control';
 
 // 获取任务阶段
 const getTaskStage = (taskStage: number) => {
@@ -9,4 +11,17 @@ const getfixStatus = (fixStatus: number) => {
   return FIX_STATUS_OPTIONS.find((item) => item.value === fixStatus)?.label;
 };
 
-export { getTaskStage, getfixStatus };
+// 导出损失明细
+const exportLossRecord = async (data: DisasterLossDetailQuery, name: string) => {
+  const res = await exportLossRecordToXML(data);
+  const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
+  const url = window.URL.createObjectURL(blob);
+  const a = document.createElement('a');
+  a.href = url;
+  a.download = `${name}损失明细.xlsx`;
+  a.click();
+  a.remove();
+  window.URL.revokeObjectURL(url);
+};
+
+export { getTaskStage, getfixStatus, exportLossRecord };

+ 2 - 5
src/views/disaster/disaster-precaution/PageTaskExecutionDetail.vue

@@ -6,7 +6,7 @@
     </header>
     <main class="disaster-precaution-container__main">
       <div class="disaster-precaution">
-        <div class="export-file" @click="handleExportTaksTable" v-if="operationType === 'view'">
+        <div class="export-file" @click="exportTaskDetailToPDF(id)" v-if="operationType === 'view'">
           <el-button type="primary">
             <template #icon>
               <img :src="ExportIcon" />
@@ -63,6 +63,7 @@
   import { ElMessage } from 'element-plus';
   import TemplateTableMerge from './src/components/TemplateTableMerge.vue';
   import { useUserInfoHook } from '@/views/disaster/hooks';
+  import { exportTaskDetailToPDF } from './src/utils';
   import type {
     TaskExecutionDetailResponse,
     TemplateDetailResponse,
@@ -149,10 +150,6 @@
     }
   });
 
-  const handleExportTaksTable = () => {
-    ElMessage.warning('导出功能后端正在开发中,暂时无法下载');
-  };
-
   onMounted(() => {
     getTaskExecutionDetailList();
     getUserFirstLevelTreeList();

+ 2 - 5
src/views/disaster/disaster-precaution/src/components/ViewTaskItem.vue

@@ -6,7 +6,7 @@
     <p class="title">
       被检查自查单位:<span class="content">{{ deptName }}</span>
     </p>
-    <div class="export-file" @click="handleExportTaksTable" v-if="taskState === TASK_STAGE.COMPLETED">
+    <div class="export-file" @click="exportTaskDetailToPDF(id)" v-if="taskState === TASK_STAGE.COMPLETED">
       <el-button type="primary">
         <template #icon>
           <img :src="ExportIcon" />
@@ -28,8 +28,8 @@
 <script setup lang="ts">
   import { useRoute } from 'vue-router';
   import { ref, onMounted } from 'vue';
-  import { ElMessage } from 'element-plus';
   import TemplateTableMerge from './TemplateTableMerge.vue';
+  import { exportTaskDetailToPDF } from '../utils';
   import type { SpanTableData } from '@/views/disaster/disaster-precaution/src/type';
   import type { TemplateDetailResponse, ContentItem } from '@/types/disaster-precaution';
   import { getTaskExecutionDetail, getTaskTemplateDetail } from '@/api/disaster-precaution';
@@ -69,9 +69,6 @@
       getTaskExecutionDetailList_Template();
     }
   };
-  const handleExportTaksTable = () => {
-    ElMessage.warning('导出功能后端正在开发中,暂时无法下载');
-  };
   onMounted(() => {
     getTaskExecutionDetailList();
   });

+ 17 - 0
src/views/disaster/disaster-precaution/src/utils/export-pdf.ts

@@ -0,0 +1,17 @@
+/**
+ * 导出检查任务详情pdf
+ */
+import { exportTaskDetailPDF } from '@/api/disaster-precaution';
+const exportTaskDetailToPDF = async (preventInspectTaskId: number) => {
+  const res = await exportTaskDetailPDF(preventInspectTaskId);
+  const blob = new Blob([res.data], { type: 'application/pdf' });
+  const url = window.URL.createObjectURL(blob);
+  const a = document.createElement('a');
+  a.href = url;
+  a.download = '检查任务详情.pdf';
+  a.click();
+  a.remove();
+  window.URL.revokeObjectURL(url);
+};
+
+export { exportTaskDetailToPDF };

+ 2 - 1
src/views/disaster/disaster-precaution/src/utils/index.ts

@@ -1,4 +1,5 @@
 import { formatSpanTableData } from './format-data';
 import { isToolTip } from './is-tooltip';
+import { exportTaskDetailToPDF } from './export-pdf';
 
-export { formatSpanTableData, isToolTip };
+export { formatSpanTableData, isToolTip, exportTaskDetailToPDF };