PageLossReportItem.vue 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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">{{ headerTitle }}</span>
  6. </header>
  7. <TaskInfoSection :task-name="taskName" @export-loss-detail="exportLossDetail" v-if="!operate" />
  8. <main class="disaster-precaution-container__main">
  9. <component :is="dynamicComponent" ref="dynamicComponentRef" />
  10. </main>
  11. <footer class="disaster-precaution-container__footer" v-if="operate">
  12. <el-button @click="router.back()">取消</el-button>
  13. <el-button type="primary" @click="handleSubmitNext" v-if="operate === 'create'">提交,并创建下一条</el-button>
  14. <el-button type="primary" @click="handleSubmitSingle">提交</el-button>
  15. </footer>
  16. <UploadLoading :form-loading="formLoading" v-if="formLoading" />
  17. </div>
  18. </template>
  19. <script lang="ts" setup>
  20. import { useRouter, useRoute } from 'vue-router';
  21. import { ref, computed, defineAsyncComponent } from 'vue';
  22. import { ElMessage } from 'element-plus';
  23. import UploadLoading from '@/components/UploadLoading.vue';
  24. import TaskInfoSection from './src/components/TaskInfoSection.vue';
  25. import { useUserInfoHook } from '@/views/disaster/hooks';
  26. import { exportLossRecord } from '@/views/disaster/disaster-control/src/util';
  27. import type { LossRecordFormData } from '@/types/disaster-control';
  28. import { createLossRecord, editLossRecord } from '@/api/disaster-control';
  29. import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
  30. import BackIcon from 'assets/svg/back.svg';
  31. const { id: reporterId } = useUserInfoHook();
  32. const router = useRouter();
  33. const route = useRoute();
  34. const reportTaskId = Number(route.params.id);
  35. const id = Number(route.query.id);
  36. const taskName = String(route.query.taskName);
  37. const viewType = String(route.query.type);
  38. const dynamicComponentRef = ref();
  39. const operate = route.query.operation;
  40. const headerTitle = computed(() => {
  41. const fixedTitle = '损失记录';
  42. if (operate === 'create') {
  43. return `创建${fixedTitle}`;
  44. } else if (operate === 'edit') {
  45. return `编辑${fixedTitle}`;
  46. } else {
  47. return `查看${fixedTitle}`;
  48. }
  49. });
  50. const exportLossDetail = async () => {
  51. const params = {
  52. handleTaskId: reportTaskId,
  53. reporterId,
  54. };
  55. await exportLossRecord(params, taskName);
  56. ElMessage.success(`导出${taskName}损失明细成功`);
  57. };
  58. const dynamicComponent = computed(() => {
  59. if (operate === 'create') {
  60. return defineAsyncComponent(() => import('./src/components/CreateLossReportItem.vue'));
  61. } else if (operate === 'edit') {
  62. return defineAsyncComponent(() => import('./src/components/EditLossReportItem.vue'));
  63. } else {
  64. return defineAsyncComponent(() => import('./src/components/ViewLossReportItem.vue'));
  65. }
  66. });
  67. const formLoading = ref(false);
  68. const formatAttachmentList = async (file: File) => {
  69. if (!file) return file;
  70. const fileName = file.name;
  71. const res = await uploadFileApi({ bizType: UPLOAD_BIZ_TYPE.ATTACHMENT, fileName, file });
  72. return res.url;
  73. };
  74. const createLossReportFunc = async (formData: LossRecordFormData) => {
  75. const imagesListRes: string[] = await Promise.all(
  76. (formData.uploadImages || []).map((item) => formatAttachmentList(item)),
  77. );
  78. const createParam = {
  79. reportTaskId,
  80. ...formData,
  81. images: imagesListRes,
  82. };
  83. await createLossRecord(createParam);
  84. };
  85. const editLossReportFunc = async (formData: LossRecordFormData) => {
  86. const imagesListRes: string[] = await Promise.all(
  87. (formData.uploadImages || []).map((item) => formatAttachmentList(item)),
  88. );
  89. formData.images = [...(formData.images || []), ...imagesListRes];
  90. const editParam = {
  91. id,
  92. ...formData,
  93. };
  94. await editLossRecord(editParam);
  95. };
  96. const handleSubmit = async () => {
  97. const validateResult = await dynamicComponentRef.value?.validateForm();
  98. if (!validateResult) return;
  99. const formData = dynamicComponentRef.value?.getFormData();
  100. formLoading.value = true;
  101. let message;
  102. try {
  103. if (operate === 'create') {
  104. await createLossReportFunc(formData);
  105. message = '创建成功';
  106. } else {
  107. await editLossReportFunc(formData);
  108. message = '编辑成功';
  109. }
  110. ElMessage.success(message);
  111. return true; // 成功时返回true
  112. } catch (error) {
  113. return false; // 失败时返回false
  114. } finally {
  115. formLoading.value = false;
  116. }
  117. };
  118. const handleSubmitSingle = async () => {
  119. const success = await handleSubmit();
  120. if (!success) return;
  121. router.back();
  122. };
  123. const handleSubmitNext = async () => {
  124. const success = await handleSubmit();
  125. if (!success) return;
  126. dynamicComponentRef.value?.initFormData();
  127. // 滚动到页面顶部 - 使用更可靠的方法
  128. const mainElement = document.querySelector('.info-container');
  129. if (!mainElement) return;
  130. mainElement.scrollTop = 0;
  131. };
  132. </script>
  133. <style lang="scss" scoped>
  134. @use '../style/disaster.scss' as *;
  135. @use './src/style/common.scss' as *;
  136. </style>