PageDisposalRectificationItem.vue 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <div class="disaster-precaution-container">
  3. <header class="disaster-precaution-container__header">
  4. <img :src="BackIcon" alt="back" class="back-icon" @click="router.back()" />
  5. <span class="disaster-precaution-container__title">整改处理</span>
  6. </header>
  7. <main class="disaster-precaution-container__main">
  8. <section class="disaster-information">
  9. <div class="disaster-information__title">
  10. <div class="disaster-information--line"></div>
  11. <span>受灾信息</span>
  12. </div>
  13. <div class="disaster-information__content">
  14. <section class="disaster-information__content--loss" v-if="LossReportItemFormData?.isLoss">
  15. <el-row :gutter="20">
  16. <el-col :span="8">
  17. <div class="disaster-information__content--item">
  18. <span class="label">受灾物品:</span>
  19. <span class="value">{{ LossReportItemFormData?.affectedItems }}</span>
  20. </div>
  21. </el-col>
  22. <el-col :span="8">
  23. <div class="disaster-information__content--item">
  24. <span class="label">地点:</span>
  25. <span class="value">
  26. {{ LossReportItemFormData?.buildingNo }}
  27. {{ LossReportItemFormData?.floorNo }}
  28. {{ LossReportItemFormData?.roomNo }}
  29. </span>
  30. </div>
  31. </el-col>
  32. <el-col :span="8">
  33. <div class="disaster-information__content--item">
  34. <span class="label">上报时间:</span>
  35. <span class="value">{{ LossReportItemFormData?.updatedAt }}</span>
  36. </div>
  37. </el-col>
  38. </el-row>
  39. <el-row :gutter="20">
  40. <el-col :span="8">
  41. <div class="disaster-information__content--item">
  42. <span class="label">影响安全评估:</span>
  43. <span class="value">{{ getSafetyLevel(LossReportItemFormData?.safetyLevel) }}</span>
  44. </div>
  45. </el-col>
  46. <el-col :span="8">
  47. <div class="disaster-information__content--item">
  48. <span class="label">是否影响正常工作:</span>
  49. <span class="value">
  50. {{ LossReportItemFormData?.isAffectWork === 1 ? '是' : '否' }}
  51. </span>
  52. </div>
  53. </el-col>
  54. <el-col :span="8">
  55. <div class="disaster-information__content--item" v-if="LossReportItemFormData?.estimatedLoss">
  56. <span class="label">损失金额评估:</span>
  57. <span class="value">{{ LossReportItemFormData?.estimatedLoss }}元</span>
  58. </div>
  59. </el-col>
  60. </el-row>
  61. <div class="disaster-information__content--item">
  62. <span class="label">损失描述:</span>
  63. <span class="value">{{ LossReportItemFormData?.description }}</span>
  64. </div>
  65. <div class="disaster-information__content--item" v-if="LossReportItemFormData?.images">
  66. <span class="label">受灾图片:</span>
  67. <div class="image-container">
  68. <el-image
  69. v-for="(image, index) in JSON.parse(LossReportItemFormData?.images)"
  70. :key="index"
  71. :src="image"
  72. :zoom-rate="1.2"
  73. :max-scale="7"
  74. :min-scale="0.2"
  75. :preview-src-list="JSON.parse(LossReportItemFormData?.images)"
  76. show-progress
  77. :initial-index="index"
  78. fit="contain"
  79. />
  80. </div>
  81. </div>
  82. <div class="disaster-information__content--item" v-if="LossReportItemFormData?.remark">
  83. <span class="label">备注:</span>
  84. <span class="value">{{ LossReportItemFormData?.remark }}</span>
  85. </div>
  86. </section>
  87. </div>
  88. </section>
  89. <section class="disaster-information">
  90. <div class="disaster-information__title">
  91. <div class="disaster-information--line"></div>
  92. <span>整改处理</span>
  93. </div>
  94. <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig">
  95. <template #fixImages>
  96. <UploadImages @uploadSuccess="handleUploadImageSuccess" />
  97. </template>
  98. <template #fixMaterials>
  99. <Upload label="上传文件" @uploadSuccess="handleUploadFileSuccess" />
  100. </template>
  101. </BasicForm>
  102. </section>
  103. </main>
  104. <footer class="disaster-precaution-container__footer">
  105. <el-button @click="router.back()">取消</el-button>
  106. <el-button type="primary" v-if="isShowNextSubmit">提交,并处置下一条</el-button>
  107. <el-button type="primary" @click="handleSubmit">提交</el-button>
  108. </footer>
  109. <UploadLoading :form-loading="formLoading" v-if="formLoading" />
  110. </div>
  111. </template>
  112. <script lang="ts" setup>
  113. import BackIcon from 'assets/svg/back.svg';
  114. import { useRoute, useRouter } from 'vue-router';
  115. import UploadLoading from '@/components/UploadLoading.vue';
  116. import BasicForm from '@/components/BasicForm.vue';
  117. import UploadImages from './src/components/UploadImages.vue';
  118. import Upload from '@/views/disaster/components/Upload.vue';
  119. import { ref, onMounted } from 'vue';
  120. import { useDisasterControlHook } from './src/hook';
  121. import { useFormConfigHook } from '@/hooks/useFormConfigHook';
  122. import { useUserInfoHook } from '@/views/disaster/hooks/userInfo';
  123. import { createDisposalRectification } from '@/api/disaster-control';
  124. import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
  125. import type { FileItem } from '@/views/disaster/types';
  126. import type { disasterReportRecordDetailListResponse, DisposalRectificationFormData } from '@/types/disaster-control';
  127. import {
  128. DISPOSAL_RECTIFICATION_FORM_CONFIG,
  129. DISPOSAL_RECTIFICATION_FORM_DATA,
  130. DISPOSAL_RECTIFICATION_FORM_RULES,
  131. } from './src/config';
  132. import { ElMessage } from 'element-plus';
  133. const basicFormRef = ref<InstanceType<typeof BasicForm>>();
  134. const LossReportItemFormData = ref<disasterReportRecordDetailListResponse>();
  135. const { getLossReportItem, getSafetyLevel, getSafetyLevelDict } = useDisasterControlHook();
  136. const { realname, id: userId } = useUserInfoHook();
  137. const router = useRouter();
  138. const route = useRoute();
  139. const id = Number(route.params.id);
  140. const handleTaskId = Number(route.query.handleTaskId);
  141. const fixTaskId = Number(route.query.fixTaskId);
  142. const formLoading = ref(false);
  143. const getLossReportItemData = async () => {
  144. const res = await getLossReportItem(handleTaskId, id);
  145. LossReportItemFormData.value = res;
  146. };
  147. const { ruleFormConfig, ruleFormData, formRules, cloneRuleFormData, beforeRouteLeave } =
  148. useFormConfigHook<DisposalRectificationFormData>(
  149. DISPOSAL_RECTIFICATION_FORM_CONFIG,
  150. DISPOSAL_RECTIFICATION_FORM_DATA,
  151. DISPOSAL_RECTIFICATION_FORM_RULES,
  152. );
  153. const rectificationIds = ref<number[]>([]);
  154. const isShowNextSubmit = ref(false);
  155. const handleUploadImageSuccess = (files: File[]) => {
  156. ruleFormData.uploadImages = files;
  157. };
  158. const handleUploadFileSuccess = (files: FileItem[]) => {
  159. ruleFormData.uploadFiles = files;
  160. };
  161. const formatImageList = async (file: File) => {
  162. if (!file) return file;
  163. const fileName = file.name;
  164. const res = await uploadFileApi({ bizType: UPLOAD_BIZ_TYPE.ATTACHMENT, fileName, file });
  165. return res.url;
  166. };
  167. const formatFileList = async (file: FileItem) => {
  168. if (!file.file) return file;
  169. const fileName = file.fileName;
  170. const res = await uploadFileApi({ bizType: UPLOAD_BIZ_TYPE.ATTACHMENT, fileName, file: file.file });
  171. const fileType = file.fileType;
  172. const fileSize = file.fileSize;
  173. const fileId = file.fileId;
  174. const fileUrl = res.url;
  175. return {
  176. fileName,
  177. fileType,
  178. fileSize,
  179. fileUrl,
  180. fileId,
  181. };
  182. };
  183. const handleSubmit = async () => {
  184. if (!basicFormRef.value) return;
  185. const validateResult = await basicFormRef.value.validateForm();
  186. if (!validateResult) return;
  187. formLoading.value = true;
  188. try {
  189. const imagesListRes: string[] = await Promise.all(
  190. (ruleFormData.uploadImages || []).map((item) => formatImageList(item)),
  191. );
  192. const fileListRes: FileItem[] = await Promise.all(
  193. (ruleFormData.uploadFiles || []).map((item) => formatFileList(item)),
  194. );
  195. const imagesListString = JSON.stringify(imagesListRes);
  196. const fileListString = JSON.stringify(fileListRes);
  197. ruleFormData.fixImages = imagesListString;
  198. ruleFormData.fixMaterials = fileListString;
  199. await createDisposalRectification({
  200. fixTaskId,
  201. ...ruleFormData,
  202. });
  203. ElMessage.success('提交成功');
  204. cloneRuleFormData();
  205. router.back();
  206. } finally {
  207. formLoading.value = false;
  208. }
  209. };
  210. onMounted(() => {
  211. ruleFormData.createdBy = userId;
  212. ruleFormData.createdByName = realname;
  213. cloneRuleFormData();
  214. beforeRouteLeave();
  215. getLossReportItemData();
  216. getSafetyLevelDict();
  217. const sessionRectificationIds = sessionStorage.getItem('rectificationIds') || '[]';
  218. rectificationIds.value = JSON.parse(sessionRectificationIds);
  219. isShowNextSubmit.value = rectificationIds.value.length > 1 && rectificationIds.value.includes(id);
  220. });
  221. </script>
  222. <style lang="scss" scoped>
  223. @use '../style/disaster.scss' as *;
  224. @use './src/style/common.scss' as *;
  225. @use './src//style/view-item.scss' as *;
  226. .disaster-precaution-container__main {
  227. display: flex !important;
  228. flex-direction: column !important;
  229. gap: 30px !important;
  230. }
  231. :deep(.el-date-editor) {
  232. --el-date-editor-width: 100%;
  233. }
  234. </style>