PageDisposalRectificationItem.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. <DisasterInfo :LossReportItemFormData="lossReportItem" v-if="lossReportItem?.isLoss" />
  9. <section class="disaster-information">
  10. <div class="disaster-information__title">
  11. <div class="disaster-information--line"></div>
  12. <span>整改处理</span>
  13. </div>
  14. <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="formRules" :formConfig="ruleFormConfig">
  15. <template #fixImages>
  16. <UploadImages ref="uploadImagesRef" @uploadSuccess="handleUploadImageSuccess" />
  17. </template>
  18. <template #fixMaterials>
  19. <UploadFiles ref="uploadFilesRef" label="上传材料" @uploadSuccess="handleUploadFileSuccess" />
  20. </template>
  21. </BasicForm>
  22. </section>
  23. </main>
  24. <footer class="disaster-precaution-container__footer">
  25. <el-button @click="router.back()">取消</el-button>
  26. <el-button type="primary" v-if="isShowNextSubmit" @click="handleNextSubmit">提交,并处置下一条</el-button>
  27. <el-button type="primary" @click="handleSubmit">提交</el-button>
  28. </footer>
  29. <UploadLoading :form-loading="formLoading" v-if="formLoading" />
  30. </div>
  31. </template>
  32. <script lang="ts" setup>
  33. import BackIcon from 'assets/svg/back.svg';
  34. import { useRoute, useRouter } from 'vue-router';
  35. import { ref, onMounted, watch, computed, onUnmounted } from 'vue';
  36. import { ElMessage } from 'element-plus';
  37. import UploadLoading from '@/components/UploadLoading.vue';
  38. import BasicForm from '@/components/BasicForm.vue';
  39. import UploadImages from './src/components/UploadImages.vue';
  40. import UploadFiles from '@/views/disaster/components/UploadFiles.vue';
  41. import DisasterInfo from './src/components/DisasterInfo.vue';
  42. import { useDisasterControlHook } from './src/hook';
  43. import { useFormConfigHook } from '@/hooks/useFormConfigHook';
  44. import { useUserInfoHook } from '@/views/disaster/hooks';
  45. import type { FileItem } from '@/views/disaster/types';
  46. import type { DisposalRectificationFormData } from '@/types/disaster-control';
  47. import { createDisposalRectification } from '@/api/disaster-control';
  48. import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
  49. import {
  50. DISPOSAL_RECTIFICATION_FORM_CONFIG,
  51. DISPOSAL_RECTIFICATION_FORM_DATA,
  52. DISPOSAL_RECTIFICATION_FORM_RULES,
  53. } from './src/config';
  54. interface RectificationIds {
  55. id: number;
  56. fixTaskId: number;
  57. }
  58. const basicFormRef = ref<InstanceType<typeof BasicForm>>();
  59. const uploadImagesRef = ref<InstanceType<typeof UploadImages>>();
  60. const uploadFilesRef = ref<InstanceType<typeof UploadFiles>>();
  61. const { getLossReportItem, lossReportItem } = useDisasterControlHook();
  62. const { realname, id: userId } = useUserInfoHook();
  63. const router = useRouter();
  64. const route = useRoute();
  65. const id = ref<number>(Number(route.params.id));
  66. const handleTaskId = Number(route.query.handleTaskId);
  67. const fixTaskId = computed(() => {
  68. return Number(route.query.fixTaskId);
  69. });
  70. const formLoading = ref(false);
  71. const { ruleFormConfig, ruleFormData, formRules, cloneRuleFormData, beforeRouteLeave } =
  72. useFormConfigHook<DisposalRectificationFormData>(
  73. DISPOSAL_RECTIFICATION_FORM_CONFIG,
  74. DISPOSAL_RECTIFICATION_FORM_DATA,
  75. DISPOSAL_RECTIFICATION_FORM_RULES,
  76. );
  77. const rectificationIds = ref<RectificationIds[]>([]);
  78. const isShowNextSubmit = computed(() => {
  79. const reportTaskIds = rectificationIds.value.map((item) => item.id);
  80. return rectificationIds.value.length > 1 && reportTaskIds.includes(id.value);
  81. });
  82. const handleUploadImageSuccess = (files: File[]) => {
  83. ruleFormData.uploadImages = files;
  84. };
  85. const handleUploadFileSuccess = (files: FileItem[]) => {
  86. ruleFormData.uploadFiles = files;
  87. };
  88. const formatImageList = async (file: File) => {
  89. if (!file) return file;
  90. const fileName = file.name;
  91. const res = await uploadFileApi({ bizType: UPLOAD_BIZ_TYPE.ATTACHMENT, fileName, file });
  92. return res.url;
  93. };
  94. const formatFileList = async (file: FileItem) => {
  95. if (!file.file) return file;
  96. const fileName = file.fileName;
  97. const res = await uploadFileApi({ bizType: UPLOAD_BIZ_TYPE.ATTACHMENT, fileName, file: file.file });
  98. const fileType = file.fileType;
  99. const fileSize = file.fileSize;
  100. const fileId = file.fileId;
  101. const fileUrl = res.url;
  102. return {
  103. fileName,
  104. fileType,
  105. fileSize,
  106. fileUrl,
  107. fileId,
  108. };
  109. };
  110. const submitDisposalRectification = async () => {
  111. const imagesListRes: string[] = await Promise.all(
  112. (ruleFormData.uploadImages || []).map((item) => formatImageList(item)),
  113. );
  114. const fileListRes: FileItem[] = await Promise.all(
  115. (ruleFormData.uploadFiles || []).map((item) => formatFileList(item)),
  116. );
  117. const imagesListString = JSON.stringify(imagesListRes);
  118. const fileListString = JSON.stringify(fileListRes);
  119. ruleFormData.fixImages = imagesListString;
  120. ruleFormData.fixMaterials = fileListString;
  121. await createDisposalRectification({
  122. fixTaskId: fixTaskId.value,
  123. ...ruleFormData,
  124. });
  125. ElMessage.success('提交成功');
  126. cloneRuleFormData();
  127. };
  128. const handleSubmit = async () => {
  129. if (!basicFormRef.value) return;
  130. const validateResult = await basicFormRef.value.validateForm();
  131. if (!validateResult) return;
  132. formLoading.value = true;
  133. try {
  134. await submitDisposalRectification();
  135. router.back();
  136. } finally {
  137. formLoading.value = false;
  138. }
  139. };
  140. const defaultRouterName = 'disaster-control-disposal-rectification-item';
  141. const handleNextSubmit = async () => {
  142. if (!basicFormRef.value) return;
  143. const validateResult = await basicFormRef.value.validateForm();
  144. if (!validateResult) return;
  145. formLoading.value = true;
  146. try {
  147. await submitDisposalRectification();
  148. } finally {
  149. formLoading.value = false;
  150. }
  151. const reportTaskIds = rectificationIds.value.map((item) => item.id);
  152. // 查找当前id在数组中的索引
  153. const currentIndex = reportTaskIds.indexOf(id.value);
  154. if (currentIndex !== -1) {
  155. // 从数组中移除当前id
  156. rectificationIds.value.splice(currentIndex, 1);
  157. // 确定下一个要处理的id和fixTaskId
  158. let nextId;
  159. let nextFixTaskId;
  160. if (currentIndex < rectificationIds.value.length) {
  161. // 如果不是最后一个元素,取当前索引位置的元素(移除当前id后,下一个id会自动前移)
  162. nextId = rectificationIds.value[currentIndex].id;
  163. nextFixTaskId = rectificationIds.value[currentIndex].fixTaskId;
  164. } else {
  165. // 如果是最后一个元素,取第一个元素
  166. nextId = rectificationIds.value[0].id;
  167. nextFixTaskId = rectificationIds.value[0].fixTaskId;
  168. }
  169. // 保存更新后的数组到sessionStorage
  170. sessionStorage.setItem('rectificationIds', JSON.stringify(rectificationIds.value));
  171. router.replace({
  172. name: defaultRouterName,
  173. params: {
  174. id: nextId,
  175. },
  176. query: {
  177. handleTaskId,
  178. fixTaskId: nextFixTaskId,
  179. },
  180. });
  181. }
  182. const mainElement = document.querySelector('.disaster-precaution-container__main');
  183. if (!mainElement) return;
  184. mainElement.scrollTop = 0;
  185. };
  186. const initRuleFormCreatedBy = () => {
  187. ruleFormData.createdBy = userId;
  188. ruleFormData.createdByName = realname;
  189. };
  190. onMounted(() => {
  191. initRuleFormCreatedBy();
  192. cloneRuleFormData();
  193. beforeRouteLeave();
  194. getLossReportItem(handleTaskId, id.value);
  195. const sessionRectificationIds = sessionStorage.getItem('rectificationIds') || '[]';
  196. rectificationIds.value = JSON.parse(sessionRectificationIds);
  197. });
  198. onUnmounted(() => {
  199. sessionStorage.removeItem('rectificationIds');
  200. });
  201. watch(
  202. () => route.params.id,
  203. (newId) => {
  204. id.value = Number(newId);
  205. getLossReportItem(handleTaskId, id.value);
  206. basicFormRef.value?.clearValidate();
  207. initRuleFormCreatedBy();
  208. uploadImagesRef.value?.removeAllImages();
  209. uploadFilesRef.value?.removeAllFiles();
  210. cloneRuleFormData();
  211. },
  212. );
  213. </script>
  214. <style lang="scss" scoped>
  215. @use '../style/disaster.scss' as *;
  216. @use './src/style/common.scss' as *;
  217. @use './src//style/view-item.scss' as *;
  218. .disaster-precaution-container__main {
  219. display: flex !important;
  220. flex-direction: column !important;
  221. gap: 30px !important;
  222. }
  223. </style>