index.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <script setup lang="ts">
  2. /**
  3. * @Name: index.vue
  4. * @Description: 导入页
  5. * @Author: Cheney
  6. */
  7. import { Upload, View } from '@element-plus/icons-vue';
  8. import { reactive, ref } from 'vue';
  9. import { ElMessage, genFileId, UploadInstance, UploadRawFile } from 'element-plus';
  10. import { SUCCESS_CODE, WARNING_CODE } from '/@/utils/requestCode';
  11. import * as api from './api';
  12. import { VxeGridProps } from 'vxe-table';
  13. const upload = ref<UploadInstance>();
  14. const upBtnLoading = ref(false);
  15. const defaultLabel = ref('ASIN');
  16. const filter = reactive({
  17. reportFilter: '',
  18. reportDateFilter: '',
  19. typeFilter: '',
  20. variableFilter: '',
  21. });
  22. const gridOptions = reactive<VxeGridProps>({
  23. loading: upBtnLoading,
  24. round: true,
  25. // border: 'inner',
  26. stripe: true,
  27. resizable: true,
  28. height: 900,
  29. toolbarConfig: {
  30. custom: true,
  31. },
  32. columns: [
  33. // { type: 'seq', width: 70 },
  34. // { field: 'name', title: 'Name' },
  35. ],
  36. data: [],
  37. });
  38. /**
  39. * @description 替换文件并上传
  40. * @param files 文件列表
  41. */
  42. function handleExceed(files: any) {
  43. upload.value!.clearFiles();
  44. const file = files[0] as UploadRawFile;
  45. file.uid = genFileId();
  46. upload.value!.handleStart(file);
  47. upload.value!.submit();
  48. }
  49. /**
  50. * 统一处理响应
  51. * @param response 后端返回的响应
  52. */
  53. function handleResponse(response: any) {
  54. if (response.code === SUCCESS_CODE) {
  55. ElMessage.success({ message: response.msg, plain: true });
  56. } else if (response.code === WARNING_CODE) {
  57. ElMessage.warning({ message: response.msg, plain: true });
  58. } else {
  59. ElMessage.error({ message: response.msg, plain: true });
  60. }
  61. }
  62. /**
  63. * 上传文件
  64. * @param uploadRequest 上传请求
  65. */
  66. async function handleCustomUpload(uploadRequest: any) {
  67. upBtnLoading.value = true;
  68. try {
  69. const { file } = uploadRequest;
  70. const response = await api.uploadFile(file);
  71. handleResponse(response);
  72. processResponseData(response.data);
  73. uploadRequest.onSuccess(response); // 通知 el-upload 上传成功
  74. } catch (error) {
  75. console.log('==Error==', error);
  76. uploadRequest.onError(error);
  77. } finally {
  78. upBtnLoading.value = false;
  79. }
  80. }
  81. /**
  82. * 处理响应数据,更新 gridOptions
  83. * @param data 响应数据
  84. */
  85. function processResponseData(data: any) {
  86. const limitedData = data.length > 15 ? data.slice(0, 15) : data;
  87. if (data.length > 0) {
  88. filter.reportFilter = data[0].Reporting_Range || '';
  89. filter.reportDateFilter = data[0].Reporting_Date || '';
  90. filter.typeFilter = data[0].ASIN ? 'ASIN View' : 'Brand View';
  91. filter.variableFilter = data[0].ASIN ? data[0].ASIN : data[0].brand || '';
  92. } else {
  93. filter.reportFilter = '';
  94. filter.reportDateFilter = '';
  95. filter.typeFilter = '';
  96. filter.variableFilter = '';
  97. }
  98. // 动态生成 columns 配置
  99. gridOptions.columns = Object.keys(limitedData[0] || {}).map((key) => {
  100. const title = key.replace(/_/g, ' '); // 将下划线替换成空格
  101. let minWidth = title.length * 10;
  102. if (key === 'ASIN' || key === 'brand') {
  103. minWidth = 130;
  104. }
  105. return {
  106. field: key,
  107. title,
  108. minWidth,
  109. };
  110. });
  111. gridOptions.data = limitedData;
  112. // 更新默认标签
  113. if (limitedData[0].brand) {
  114. defaultLabel.value = 'Brand';
  115. } else {
  116. defaultLabel.value = 'ASIN';
  117. }
  118. }
  119. /**
  120. * 确认导入
  121. */
  122. async function confirmUpload() {
  123. try {
  124. const response = await api.confirmUploadFile({ upload: true });
  125. handleResponse(response);
  126. if (response.code === SUCCESS_CODE) {
  127. gridOptions.data = [];
  128. gridOptions.columns = [];
  129. filter.reportFilter = '';
  130. filter.reportDateFilter = '';
  131. filter.typeFilter = '';
  132. filter.variableFilter = '';
  133. }
  134. } catch (error) {
  135. console.error('==Error==', error);
  136. }
  137. }
  138. </script>
  139. <template>
  140. <div class="py-2 px-2.5" style="background-color: #f7f7f7">
  141. <el-card body-class="flex justify-between gap-3.5" shadow="hover" style="border: none; margin-bottom: 10px">
  142. <div class="flex flex-wrap gap-7">
  143. <div>
  144. <span class="font-bold mr-2" style="color: #303133">报告类型:</span>
  145. <el-input v-model="filter.reportFilter" :disabled="true" style="width: 200px"></el-input>
  146. </div>
  147. <div>
  148. <span class="font-bold mr-2" style="color: #303133">报告日期:</span>
  149. <el-input v-model="filter.reportDateFilter" :disabled="true" style="width: 200px"></el-input>
  150. </div>
  151. <div>
  152. <span class="font-bold mr-2" style="color: #303133">类型:</span>
  153. <el-input v-model="filter.typeFilter" :disabled="true" style="width: 200px"></el-input>
  154. </div>
  155. <div>
  156. <span class="font-bold mr-2" style="color: #303133">{{ defaultLabel }}:</span>
  157. <el-input v-model="filter.variableFilter" :disabled="true" style="width: 240px"></el-input>
  158. </div>
  159. </div>
  160. <div class="flex gap-3.5">
  161. <!-- 想要不页面不跳动可以加72的高度 -->
  162. <div>
  163. <el-upload
  164. ref="upload"
  165. action="#"
  166. :limit="1"
  167. :show-file-list="false"
  168. :auto-upload="true"
  169. :on-exceed="handleExceed"
  170. :http-request="handleCustomUpload">
  171. <template #trigger>
  172. <el-button :loading="upBtnLoading" plain color="#6366f1" :icon="View">导入预览</el-button>
  173. </template>
  174. </el-upload>
  175. </div>
  176. <el-button plain round type="warning" :icon="Upload" @click="confirmUpload"> 确认导入 </el-button>
  177. </div>
  178. </el-card>
  179. <el-card shadow="hover" style="border: none">
  180. <div class="text-xl font-bold text-center font-sans subpixel-antialiased">导入预览</div>
  181. <vxe-grid v-bind="gridOptions"></vxe-grid>
  182. </el-card>
  183. </div>
  184. </template>
  185. <style scoped></style>