Explorar el Código

feat: 演练记录

wyf hace 9 meses
padre
commit
e9d4fbe3c6

+ 17 - 9
src/api/emergency-drill/emergency-drill.ts

@@ -8,6 +8,7 @@ import {
   DrillPlanRecord,
   ExecuteDrillPlanRuleForm,
   DrillRecordRuleForm,
+  DrillApprovalItem,
 } from '@/views/emergency/emergency-drill/types';
 import type { DrillSignlistQuery, DrillSignListResponse } from '@/types/emergency-drill';
 
@@ -28,9 +29,7 @@ export const createEmergencyDrillPlan = (params: CreateEmergencyDrillRuleForm) =
       drillContent: params.drillContent,
       dueCompleteTime: params.dueCompleteTime,
       responsibleDeptIdList: '[' + params.responsibleDeptIdList?.join(',') + ']',
-      coordinateDeptIdList: params.coordinateDeptIdList
-        ? '[' + params.coordinateDeptIdList?.join(',') + ']'
-        : undefined,
+      coordinateDeptIdList: params.coordinateDeptIdList ? '[' + params.coordinateDeptIdList?.join(',') + ']' : '',
       preplanId: params.preplanId,
       approvalTemplateId: params.approvalTemplateId,
     },
@@ -46,7 +45,7 @@ export const saveEmergencyDrillExecute = (params: ExecuteDrillPlanRuleForm) => {
       drillTime: params.drillTime,
       drillLocation: params.drillLocation,
       personInChargeId: params.personInChargeId,
-      drillDeptIdList: params.drillDeptIdList ? '[' + params.drillDeptIdList?.join(',') + ']' : null,
+      drillDeptIdList: params.drillDeptIdList ? '[' + params.drillDeptIdList?.join(',') + ']' : '',
       drillScript: params.drillScript,
       saveOrSubmit: 0,
     },
@@ -61,7 +60,7 @@ export const submitEmergencyDrillExecute = (params: ExecuteDrillPlanRuleForm) =>
       drillTime: params.drillTime,
       drillLocation: params.drillLocation,
       personInChargeId: params.personInChargeId,
-      drillDeptIdList: params.drillDeptIdList ? '[' + params.drillDeptIdList?.join(',') + ']' : null,
+      drillDeptIdList: params.drillDeptIdList ? '[' + params.drillDeptIdList?.join(',') + ']' : '',
       drillScript: params.drillScript,
       saveOrSubmit: 1,
     },
@@ -104,10 +103,19 @@ export const queryEmergencyDrillPlanDetail = (id) => {
   });
 };
 
-export const queryEmergencyDrillRecord = (id) => {
+export const queryEmergencyDrillRecordInEdit = (id) => {
   return http.request<DrillPlanRecord>({
-    url: `/emergencyDrill/queryEmergencyDrillRecord?drillPlanId=${id}`,
-    method: 'get',
+    url: `/emergencyDrill/queryEmergencyDrillRecord`,
+    method: 'post',
+    data: { drillPlanId: id, editOrView: 0 },
+  });
+};
+
+export const queryEmergencyDrillRecordInView = (id) => {
+  return http.request<DrillPlanRecord>({
+    url: `/emergencyDrill/queryEmergencyDrillRecord`,
+    method: 'post',
+    data: { drillPlanId: id, editOrView: 1 },
   });
 };
 
@@ -151,7 +159,7 @@ export const signDrillScript = (data: { drillPlanId: number; planToParticipateCo
  * 查询审批模板
  */
 export const queryDrillApproval = (approvalTemplateId: number, drillId: number) => {
-  return http.request<any>({
+  return http.request<DrillApprovalItem[]>({
     url: `/approvalManagement/queryApprovalProcess`,
     method: 'post',
     data: {

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

@@ -190,8 +190,13 @@
     uploadedImages.length = 0;
   };
 
+  const getUploadedImages = () => {
+    return uploadedImages;
+  };
+
   defineExpose({
     removeAllImages,
+    getUploadedImages,
   });
 
   const emitChange = () => {
@@ -209,6 +214,9 @@
       });
       uploadedImages.push(...urlList);
     },
+    {
+      immediate: true,
+    },
   );
   onUnmounted(() => {
     removeAllImages();

+ 18 - 3
src/views/emergency/emergency-drill/PageDrillPlanItem.vue

@@ -5,7 +5,7 @@
       <span class="breadcrumb-title">{{ headerTitle }}</span>
     </header>
     <main class="safety-platform-container__main">
-      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" />
+      <component :is="dynamicComponent" :id="id" ref="dynamicComponentRef" @record-submitted="handleRecordSubmitted" />
     </main>
     <footer class="safety-platform-container__footer">
       <!-- 提交按钮 -->
@@ -18,8 +18,13 @@
         <el-button type="primary" @click="executeSubmit">提交</el-button>
       </div>
       <div v-if="operate === 'record'">
-        <el-button @click="recordSave">保存</el-button>
-        <el-button type="primary" @click="recordSubmit">提交审批</el-button>
+        <div v-if="!isRecordSubmitted">
+          <el-button @click="recordSave">保存</el-button>
+          <el-button type="primary" @click="recordSubmit">提交审批</el-button>
+        </div>
+        <div v-else>
+          <el-button type="primary" @click="enableEditRecord">修改</el-button>
+        </div>
       </div>
     </footer>
     <UploadLoading :form-loading="formLoading" v-if="formLoading" />
@@ -38,6 +43,7 @@
   const route = useRoute();
   const operate = route.query.operate;
   const id = route.query.id;
+  const isRecordSubmitted = ref(false);
   const headerTitle = computed(() => {
     switch (operate) {
       case 'create':
@@ -111,6 +117,15 @@
   const recordSubmit = async () => {
     await dynamicComponentRef.value.startSubmitDrillRecord();
   };
+
+  function handleRecordSubmitted() {
+    isRecordSubmitted.value = true;
+  }
+
+  function enableEditRecord() {
+    isRecordSubmitted.value = false;
+    dynamicComponentRef.value.enableEditRecord();
+  }
 </script>
 
 <style scoped lang="scss">

+ 4 - 3
src/views/emergency/emergency-drill/PageDrillPlanList.vue

@@ -52,7 +52,7 @@
               <ActionButton
                 v-else-if="scope.row.status < 6"
                 text="演练记录"
-                @click="handleToRecord(scope.row.id)"
+                @click="handleToRecord(scope.row)"
               ></ActionButton>
               <ActionButton
                 text="删除"
@@ -179,11 +179,12 @@
     });
   }
 
-  function handleToRecord(id: number) {
+  function handleToRecord(row: DrillPlanItem) {
     router.push({
       name: 'emergency-drill-plan-item',
       query: {
-        id: id,
+        planId: row.id,
+        approvalId: row.approvalTemplateId,
         operate: 'record',
       },
     });

+ 76 - 38
src/views/emergency/emergency-drill/components/DrillApprovalDialog.vue

@@ -8,34 +8,29 @@
         <el-form-item
           v-for="(item, index) in formData.approverListInfo"
           :key="item.approvalOrder"
-          :label="`第${item.approvalOrder + 1}步,${item.deptName}`"
-          :prop="'approverListInfo.' + index + '.approverName'"
+          :label="`第${item.approvalOrder + 1}步,${item.deptName}(${item.approvalType ? '或签' : '会签'})`"
+          :prop="'approverListInfo.' + index + '.approverList'"
           :rules="{ required: true, message: '请选择审批人', trigger: 'change' }"
         >
           <el-select
-            v-model="item.approverName"
+            v-model="item.approverList"
             placeholder="请输入审批人"
             value-key="id"
             filterable
+            multiple
             remote
-            :disabled="formDisabled"
+            :disabled="!item.approverType"
             :remote-method="remoteMethod"
             :loading="loading"
-            @change="(value) => selectKeeper(value, index)"
           >
-            <el-option
-              v-for="item in userOptions"
-              :key="item.id"
-              :label="`${item.realname}(${item.username})${item.deptName}`"
-              :value="item"
-            />
+            <el-option v-for="item in userOptions" :key="item.id" :label="item.realname" :value="item" />
           </el-select>
         </el-form-item>
       </el-form>
     </template>
     <template #footer>
       <el-button type="primary" @click="handleSumbit">提交</el-button>
-      <el-button @click="handleCancel">取消</el-button>
+      <el-button @click="closeDialog">取消</el-button>
     </template>
   </BasicDialog>
 </template>
@@ -47,39 +42,88 @@
   import type { QueryUserInfoByUserNameRes } from '@/types/person-group/type';
   import { queryUserInfoByUserName } from '@/api/system/person-group';
   import { FormInstance } from 'element-plus';
-  import { rules } from '@/types/camera/constant';
 
   const props = defineProps<{
-    approvalData: DrillApprovalItem;
+    approvalData: DrillApprovalItem[];
   }>();
   const emits = defineEmits<{
-    (e: 'success'): void;
+    (e: 'filled', data: DrillApprovalRuleForm): void;
   }>();
 
   const basicDialogRef = ref<InstanceType<typeof BasicDialog>>();
   const formRef = ref<FormInstance>();
 
   const openDialog = () => {
-    initForm();
+    initForm(props.approvalData);
     basicDialogRef.value?.openDialog();
   };
 
-  const formDisabled = ref(props.approvalData.approverType === 0);
+  const closeDialog = () => {
+    if (!basicDialogRef.value) return;
+    clearForm();
+    basicDialogRef.value.closeDialog();
+  };
 
   const formData = reactive<DrillApprovalRuleForm>({
     approvalDescription: '',
     approverListInfo: [],
   });
+  function initForm(originalData: DrillApprovalItem[]) {
+    // 初始化转换结果
+    const result: {
+      approvalOrder: number;
+      approvalType: number;
+      approverType: number;
+      deptName: string;
+      approverList: any[];
+      approverIds?: number[];
+      // approverName: string[];
+    }[] = [];
+    // 遍历原始数据数组
+    originalData.forEach((item) => {
+      if (item.approverType === 0) {
+        // 固定
 
-  function initForm() {
-    props.approvalData.processInfoList.forEach((x, index) => {
-      formData.approverListInfo.push({
-        approvalOrder: index,
-        deptName: x.approvalDeptName,
-        approverId: x.approverId,
-        approverName: x.approverName,
-      });
+        // 收集当前审批环节的所有审批人ID和名称
+        const approverIds: number[] = [];
+        const approverNames: string[] = [];
+        // 默认为第一个流程项的部门名称
+        let deptName = '';
+        // 处理流程列表
+        item.processInfoList.forEach((process, index) => {
+          // 收集审批人信息
+          approverIds.push(process.approverId);
+          approverNames.push(process.approverName);
+          // 设置部门名称(取第一个流程项的部门名称)
+          if (index === 0) {
+            deptName = process.approvalDeptName;
+          }
+        });
+        // 添加到转换结果中
+        result.push({
+          approvalOrder: item.approvalOrder,
+          approverType: item.approverType,
+          approvalType: item.processInfoList[0].approvalType,
+          deptName,
+          approverList: approverNames,
+          approverIds: approverIds,
+          // approverName: approverNames,
+        });
+      } else {
+        // 自选
+        result.push({
+          approvalOrder: item.approvalOrder,
+          approverType: item.approverType,
+          approvalType: item.processInfoList[0].approvalType,
+          deptName: '',
+          approverList: [],
+          // approverId: [],
+          // approverName: [],
+        });
+      }
     });
+
+    formData.approverListInfo = result;
   }
 
   function clearForm() {
@@ -94,16 +138,14 @@
       });
     });
     if (!validate) return;
-    console.log(formData);
-    // 提交表单接口
-    // emits('success');
+    emits('filled', formData);
   };
 
-  const handleCancel = () => {
-    if (!basicDialogRef.value) return;
-    clearForm();
-    basicDialogRef.value.closeDialog();
-  };
+  // const handleCancel = () => {
+  //   if (!basicDialogRef.value) return;
+  //   clearForm();
+  //   basicDialogRef.value.closeDialog();
+  // };
 
   // 人员选择
   const userOptions = ref<QueryUserInfoByUserNameRes[]>([]);
@@ -117,11 +159,6 @@
     userOptions.value = await queryUserInfoByUserName(query);
     loading.value = false;
   };
-  function selectKeeper(value, index) {
-    if (!value) return;
-    formData.approverListInfo[index].approverId = value.id;
-    formData.approverListInfo[index].approverName = value.realname;
-  }
 
   const refreshFromData = () => {
     formRef.value?.clearValidate();
@@ -129,6 +166,7 @@
 
   defineExpose({
     openDialog,
+    closeDialog,
   });
 </script>
 

+ 2 - 5
src/views/emergency/emergency-drill/components/DrillPlanExecuteForm.vue

@@ -29,7 +29,7 @@
           collapse-tags
           :show-all-levels="false"
           :max-collapse-tags="3"
-          placeholder="请选择配合部门"
+          placeholder="请选择演练部门"
         >
         </el-cascader>
       </template>
@@ -148,10 +148,7 @@
 
   function stringToArray(str?: string): number[] | undefined {
     if (!str) return undefined;
-    // 去除字符串中的方括号
-    const trimmed = str.replace(/\[|\]/g, '');
-    // 将剩余部分转换为数字并放入数组
-    return [Number(trimmed)];
+    return JSON.parse(str);
   }
 
   function unformatAttachment(file?: string) {

+ 27 - 16
src/views/emergency/emergency-drill/components/DrillPlanExecuteItem.vue

@@ -29,24 +29,32 @@
         <el-row :gutter="20">
           <el-col :span="8">
             <div class="drill-container__content--item">
-              <span class="label">责任部门:</span>
-              <template v-for="(dept, index) in safatyJsonParse(drillData.responsibleDeptNameList)" :key="index">
-                <span class="value">
-                  {{ dept }}
-                  <span v-if="index !== safatyJsonParse(drillData.responsibleDeptNameList).length - 1">、</span>
-                </span>
-              </template>
+              <div>
+                <span class="label">责任部门:</span>
+                <template v-for="(dept, index) in safatyJsonParse(drillData.responsibleDeptNameList)" :key="index">
+                  <span class="value">
+                    {{ dept }}
+                    <span v-if="index !== safatyJsonParse(drillData.responsibleDeptNameList).length - 1">、</span>
+                  </span>
+                </template>
+              </div>
             </div>
           </el-col>
           <el-col :span="8">
-            <div class="drill-container__content--item" v-if="drillData.coordinateDeptNameList">
-              <span class="label">配合部门:</span>
-              <template v-for="(dept, index) in safatyJsonParse(drillData.coordinateDeptNameList)" :key="index">
-                <span class="value">
-                  {{ dept }}
-                  <span v-if="index !== safatyJsonParse(drillData.coordinateDeptNameList).length - 1">、</span>
-                </span>
-              </template>
+            <div class="drill-container__content--item">
+              <div>
+                <span class="label">配合部门:</span>
+                <template
+                  v-if="drillData.coordinateDeptNameList"
+                  v-for="(dept, index) in safatyJsonParse(drillData.coordinateDeptNameList)"
+                  :key="index"
+                >
+                  <span class="value">
+                    {{ dept }}
+                    <span v-if="index !== safatyJsonParse(drillData.coordinateDeptNameList).length - 1">、</span>
+                  </span>
+                </template>
+              </div>
             </div>
           </el-col>
           <el-col :span="8">
@@ -76,7 +84,7 @@
       <DrillPlanExecuteForm
         v-if="drillData"
         ref="drillPlanExecuteFormRef"
-        :ins-name="drillScopeDice[0].itemValue"
+        :ins-name="drillScopeDice[0].itemCode"
         :drill-data="drillData"
         style="margin-top: 20px"
       />
@@ -195,15 +203,18 @@
         getDrillData();
       } catch (e) {
         console.log(e);
+        ElMessage.error('保存失败');
       }
     } else {
       try {
         await submitEmergencyDrillExecute(executeParams);
         ElMessage.success('提交成功');
         drillPlanExecuteFormRef.value.formClearValidate();
+        drillData.value = undefined;
         getDrillData();
       } catch (e) {
         console.log(e);
+        ElMessage.error('提交失败');
       }
     }
   }

+ 65 - 52
src/views/emergency/emergency-drill/components/DrillPlanRecordForm.vue

@@ -6,13 +6,19 @@
           v-if="!uploadImgDisabled"
           :maxCount="9"
           ref="uploadImagesRef"
-          @uploadChange="handleUploadChange"
+          :image-list="recordImageList"
+          @upload-success="handleUploadChange"
         />
-        <ShowImages v-else :image-list="ruleFormData.drillImage" />
+        <ShowImages style="min-height: 100px" v-else :image-list="recordImageList" />
       </template>
     </BasicForm>
   </div>
-  <DrillApprovalDialog v-if="approvalInfo" ref="drillApprovalDialogRef" :approval-data="approvalInfo" />
+  <DrillApprovalDialog
+    v-if="approvalInfo"
+    ref="drillApprovalDialogRef"
+    :approval-data="approvalInfo"
+    @filled="handleSubmitRecord"
+  />
 </template>
 
 <script setup lang="ts">
@@ -22,51 +28,36 @@
   import DrillApprovalDialog from './DrillApprovalDialog.vue';
   import { useFormConfigHook } from '@/hooks/useFormConfigHook';
   import { DRILL_RECORD_FORM_CONFIG, DRILL_RECORD_FORM_RULES, DRILL_RECORD_FORM_DATA } from '../configs/plan/form';
-  import { DrillApprovalItem, DrillPlanRecord, DrillRecordRuleForm } from '../types';
-  import { onMounted, ref } from 'vue';
+  import { DrillApprovalItem, DrillApprovalRuleForm, DrillPlanRecord, DrillRecordRuleForm } from '../types';
+  import { computed, onMounted, ref, watch } from 'vue';
   import { queryDrillApproval } from '@/api/emergency-drill/emergency-drill';
+  import { useRoute } from 'vue-router';
 
   const props = defineProps<{
-    drillRecord?: DrillPlanRecord;
+    disabled: boolean;
+    drillRecord?: DrillPlanRecord | null;
   }>();
 
-  const handleUploadChange = (files: File[]) => {};
+  const emits = defineEmits<{
+    (e: 'submitDrillRecord', data: DrillRecordRuleForm): void;
+  }>();
 
-  const approvalInfo = ref();
-  const approvalDataExample: DrillApprovalItem = {
-    // 审批顺序为第1步
-    approvalOrder: 1,
-    // 审批人选择方式为固定(0-固定)
-    approverType: 0,
-    // 审批流程列表,包含两个审批节点
-    processInfoList: [
-      {
-        approvalDeptId: 101,
-        approvalDeptName: '技术部',
-        approverId: 1001,
-        approverName: '张明',
-        approvalType: 0, // 会签
-        approvalStatus: 1, // 已审批
-        approvalContent: '同意该方案,建议补充安全预案',
-      },
-      {
-        approvalDeptId: 102,
-        approvalDeptName: '安全管理部',
-        approverId: 1002,
-        approverName: '李华',
-        approvalType: 1, // 或签
-        approvalStatus: 2, // 待审批
-        approvalContent: '', // 待审批时无内容
-      },
-    ],
+  const route = useRoute();
+  const uploadImagesRef = ref<InstanceType<typeof UploadImages>>();
+  const handleUploadChange = (val) => {
+    // console.log('files', val);
+    // console.log('files', uploadImagesRef.value!.getUploadedImages());
+    ruleFormData.drillImagesFile = uploadImagesRef.value!.getUploadedImages();
   };
 
+  const approvalInfo = ref();
+
   async function getApprovalInfo() {
-    // if (!props.drillRecord) return;
+    const planId = Number(route.query.planId);
+    const approvalId = Number(route.query.approvalId);
     try {
-      // approvalInfo.value = await queryDrillApproval(props.drillRecord.approvalTemplateId, props.drillRecord.drillPlanId);
-      approvalInfo.value = approvalDataExample;
-      console.log(approvalInfo.value);
+      approvalInfo.value = await queryDrillApproval(approvalId, planId);
+      // console.log(approvalInfo.value);
     } catch (e) {
       console.log(e);
     }
@@ -110,18 +101,25 @@
   }
 
   const uploadImgDisabled = ref(false);
-  function disableFormInput() {
-    uploadImgDisabled.value = true;
-    ruleFormConfig.value.forEach((x) => {
-      if (x.componentProps) x.componentProps.disabled = true;
-    });
-  }
-  function enableFormInput() {
-    uploadImgDisabled.value = false;
-    ruleFormConfig.value.forEach((x) => {
-      if (x.componentProps) x.componentProps.disabled = false;
-    });
-  }
+
+  watch(
+    () => props.disabled,
+    (val) => {
+      uploadImgDisabled.value = val;
+      ruleFormConfig.value.forEach((x) => {
+        if (x.componentProps) x.componentProps.disabled = val;
+      });
+    },
+    {
+      immediate: true,
+    },
+  );
+
+  const recordImageList = computed(() => {
+    if (!ruleFormData.drillImage) return [];
+    // return '';
+    return JSON.parse(ruleFormData.drillImage);
+  });
 
   // 弹窗
   const drillApprovalDialogRef = ref();
@@ -130,13 +128,28 @@
     drillApprovalDialogRef.value.openDialog();
   }
 
+  function closeApprovalDialog() {
+    drillApprovalDialogRef.value.closeDialog();
+  }
+
+  function handleSubmitRecord(approverData: DrillApprovalRuleForm) {
+    ruleFormData.approvalDescription = approverData.approvalDescription;
+    ruleFormData.approvalInfoList = approverData.approverListInfo.map((x) => {
+      return {
+        approvalOrder: x.approvalOrder,
+        approverIdList:
+          '[' + (x.approverType === 1 ? x.approverList.map((x) => x.id).join(',') : x.approverIds?.join(',')) + ']',
+      };
+    });
+    emits('submitDrillRecord', ruleFormData);
+  }
+
   defineExpose({
     formValidate,
     formClearValidate,
     getFormData,
-    disableFormInput,
-    enableFormInput,
     openApprovalDialog,
+    closeApprovalDialog,
   });
 </script>
 

+ 87 - 9
src/views/emergency/emergency-drill/components/DrillPlanRecordItem.vue

@@ -1,6 +1,11 @@
 <template>
-  <div>
-    <DrillPlanRecordForm ref="drillPlanRecordFormRef" :drill-record="recordData" />
+  <div v-if="recordData !== undefined">
+    <DrillPlanRecordForm
+      ref="drillPlanRecordFormRef"
+      :disabled="disableForm"
+      :drill-record="recordData"
+      @submit-drill-record="finishSubmitDrillRecord"
+    />
   </div>
 </template>
 
@@ -8,18 +13,33 @@
   import DrillPlanRecordForm from './DrillPlanRecordForm.vue';
   import { onMounted, ref } from 'vue';
   import { useRoute } from 'vue-router';
-  import { DrillPlanRecord } from '../types';
-  import { queryEmergencyDrillRecord, saveEmergencyDrillRecord } from '@/api/emergency-drill/emergency-drill';
+  import { DrillPlanRecord, DrillRecordRuleForm } from '../types';
+  import {
+    queryEmergencyDrillRecordInEdit,
+    saveEmergencyDrillRecord,
+    submitEmergencyDrillRecord,
+  } from '@/api/emergency-drill/emergency-drill';
   import { ElMessage } from 'element-plus';
+  import { UPLOAD_BIZ_TYPE, uploadFileApi } from '@/api/minio';
 
   const route = useRoute();
-  const id = route.query.id;
-  const recordData = ref<DrillPlanRecord>();
+  const id = route.query.planId;
+  const recordData = ref<DrillPlanRecord | null>();
+  const disableForm = ref(false);
+
+  const emits = defineEmits<{
+    (e: 'recordSubmitted'): void;
+  }>();
 
   async function getDrillData() {
     try {
-      recordData.value = await queryEmergencyDrillRecord(id);
+      recordData.value = await queryEmergencyDrillRecordInEdit(Number(id));
+      if (recordData.value.approvalStatus != null) {
+        emits('recordSubmitted');
+        disableForm.value = true;
+      }
     } catch (e) {
+      recordData.value = null;
       console.log(e);
     }
   }
@@ -29,12 +49,27 @@
   });
 
   const drillPlanRecordFormRef = ref();
-
   async function saveDrillRecord() {
     if (!drillPlanRecordFormRef) return;
-    const formData = drillPlanRecordFormRef.value.getFormData();
+    const formData: DrillRecordRuleForm = drillPlanRecordFormRef.value.getFormData();
+    formData.drillImage =
+      '[' +
+      (
+        await Promise.all(
+          (formData.drillImagesFile || []).map((item) => {
+            if (!item.file && item.url) {
+              return '"' + item.url + '"';
+            } else {
+              return formatImageList(item.file!);
+            }
+          }),
+        )
+      ).join(',') +
+      ']';
     if (!formData.drillPlanId) formData.drillPlanId = Number(id);
+
     try {
+      // console.log(formData);
       await saveEmergencyDrillRecord(formData);
       ElMessage.success('保存成功');
       drillPlanRecordFormRef.value.formClearValidate();
@@ -42,6 +77,7 @@
       getDrillData();
     } catch (e) {
       console.log(e);
+      ElMessage.error('保存失败');
     }
   }
 
@@ -52,9 +88,51 @@
     drillPlanRecordFormRef.value.openApprovalDialog();
   }
 
+  async function finishSubmitDrillRecord(innerFormData: DrillRecordRuleForm) {
+    try {
+      innerFormData.drillImage =
+        '[' +
+        (
+          await Promise.all(
+            (innerFormData.drillImagesFile || []).map((item) => {
+              if (!item.file && item.url) {
+                return '"' + item.url + '"';
+              } else {
+                return formatImageList(item.file!);
+              }
+            }),
+          )
+        ).join(',') +
+        ']';
+      if (!innerFormData.drillPlanId) innerFormData.drillPlanId = Number(id);
+
+      await submitEmergencyDrillRecord(innerFormData);
+      ElMessage.success('提交成功');
+      drillPlanRecordFormRef.value.formClearValidate();
+      drillPlanRecordFormRef.value.closeApprovalDialog();
+      recordData.value = undefined;
+      getDrillData();
+    } catch (e) {
+      console.log(e);
+      ElMessage.error('提交失败');
+    }
+  }
+
+  const formatImageList = 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 + '"';
+  };
+
+  function enableEditRecord() {
+    disableForm.value = false;
+  }
+
   defineExpose({
     saveDrillRecord,
     startSubmitDrillRecord,
+    enableEditRecord,
   });
 </script>
 

+ 20 - 16
src/views/emergency/emergency-drill/components/DrillPlanViewActivities.vue

@@ -29,24 +29,28 @@
         <el-row :gutter="20">
           <el-col :span="8">
             <div class="drill-container__content--item">
-              <span class="label">责任部门:</span>
-              <template v-for="(dept, index) in safatyJsonParse(drillData.responsibleDeptNameList)" :key="index">
-                <span class="value">
-                  {{ dept }}
-                  <span v-if="index !== safatyJsonParse(drillData.responsibleDeptNameList).length - 1">、</span>
-                </span>
-              </template>
+              <div>
+                <span class="label">责任部门:</span>
+                <template v-for="(dept, index) in safatyJsonParse(drillData.responsibleDeptNameList)" :key="index">
+                  <span class="value">
+                    {{ dept }}
+                    <span v-if="index !== safatyJsonParse(drillData.responsibleDeptNameList).length - 1">、</span>
+                  </span>
+                </template>
+              </div>
             </div>
           </el-col>
           <el-col :span="8">
             <div class="drill-container__content--item" v-if="drillData.coordinateDeptNameList">
-              <span class="label">配合部门:</span>
-              <template v-for="(dept, index) in safatyJsonParse(drillData.coordinateDeptNameList)" :key="index">
-                <span class="value">
-                  {{ dept }}
-                  <span v-if="index !== safatyJsonParse(drillData.coordinateDeptNameList).length - 1">、</span>
-                </span>
-              </template>
+              <div>
+                <span class="label">配合部门:</span>
+                <template v-for="(dept, index) in safatyJsonParse(drillData.coordinateDeptNameList)" :key="index">
+                  <span class="value">
+                    {{ dept }}
+                    <span v-if="index !== safatyJsonParse(drillData.coordinateDeptNameList).length - 1">、</span>
+                  </span>
+                </template>
+              </div>
             </div>
           </el-col>
           <el-col :span="8">
@@ -68,7 +72,7 @@
         </el-row>
       </div>
     </div>
-    <div class="drill-activity-container">
+    <div class="drill-activity-container" style="margin-top: 20px">
       <div class="drill-container__title">
         <div class="drill-container--line"></div>
         <span>演练实施</span>
@@ -118,7 +122,7 @@
       </div>
     </div>
 
-    <div class="drill-container__title">
+    <div class="drill-container__title" style="margin-top: 20px">
       <div class="drill-container--line"></div>
       <span>演练参与部门</span>
     </div>

+ 16 - 2
src/views/emergency/emergency-drill/components/DrillPlanViewRecords.vue

@@ -5,6 +5,19 @@
       <span class="text"> {{ recordData![item.value] }}</span>
     </div>
   </div>
+  <div
+    v-else
+    style="
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      flex-direction: column;
+      margin-top: calc(70vh - 500px);
+    "
+  >
+    <img :src="EmptyImg" alt="empty" />
+    <span>暂无数据</span>
+  </div>
 </template>
 
 <script setup lang="ts">
@@ -12,7 +25,8 @@
   import { useRoute } from 'vue-router';
   import { DrillPlanRecord } from '../types';
   import { DRILL_VIEW_RECORD } from '../constants';
-  import { queryEmergencyDrillRecord } from '@/api/emergency-drill/emergency-drill';
+  import { queryEmergencyDrillRecordInView } from '@/api/emergency-drill/emergency-drill';
+  import EmptyImg from 'assets/images/empty@1X.png';
 
   const route = useRoute();
   const id = route.query.id;
@@ -20,7 +34,7 @@
 
   async function getData() {
     try {
-      recordData.value = await queryEmergencyDrillRecord(id);
+      recordData.value = await queryEmergencyDrillRecordInView(id);
     } catch (e) {
       console.log(e);
     }

+ 8 - 8
src/views/emergency/emergency-drill/components/ShowImages.vue

@@ -2,11 +2,11 @@
   <div class="show-box-container">
     <div v-for="(image, index) in imageList" :key="index" class="image-preview">
       <el-image
-        :src="image.url"
+        :src="image"
         :zoom-rate="1.2"
         :max-scale="7"
         :min-scale="0.2"
-        :preview-src-list="imageList.map((item) => item.url)"
+        :preview-src-list="imageList"
         show-progress
         :initial-index="index"
         fit="contain"
@@ -17,16 +17,16 @@
 
 <script setup lang="ts">
   // import type { ImageItem } from '@/types/disaster-control';
-  import { computed } from 'vue';
+  // import { computed } from 'vue';
 
   const props = defineProps<{
-    imageList?: string;
+    imageList?: string[];
   }>();
 
-  const imageList = computed(() => {
-    if (!props.imageList) return [];
-    return JSON.parse(props.imageList);
-  });
+  // const images = computed(() => {
+  //   if (!props.imageList) return [];
+  //   return JSON.parse(props.imageList);
+  // });
 </script>
 
 <style scoped>

+ 8 - 2
src/views/emergency/emergency-drill/types.ts

@@ -1,3 +1,5 @@
+import { ImageItem } from '@/types/disaster-control';
+
 export interface DrillPlanItem {
   /*自增主键 */
   id: number;
@@ -196,6 +198,7 @@ export interface DrillRecordRuleForm {
   drillDescription?: string;
   /*演练照片 */
   drillImage?: string;
+  drillImagesFile?: ImageItem[];
   /*演练效果评估 */
   drillEffectAssess?: string;
   /*演练记录审批内容 */
@@ -234,8 +237,11 @@ export interface DrillApprovalRuleForm {
   approvalDescription?: string;
   approverListInfo: {
     approvalOrder: number;
+    approvalType: number;
+    approverType: number;
     deptName: string;
-    approverId: number;
-    approverName: string;
+    approverList: any[];
+    approverIds?: number[];
+    // approverName: string[];
   }[];
 }