file.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import { ref, watchEffect, computed, watch } from 'vue';
  2. import { Message } from 'element-ui';
  3. import { getFileType } from '@/utils/filter';
  4. import { fileUploadAbort } from '@/api/app';
  5. export const pictureFormat = ['webp', 'jpg', 'jpeg', 'gif', 'png', 'tif'];
  6. export const audioFormat = ['mp3', 'wma'];
  7. export const videoFormat = ['mp4', 'flv', 'webm', 'mpeg', 'mpg'];
  8. export const documentFormat = ['txt', 'doc', 'docx', 'pdf', 'ppt', 'pptx', 'xls', 'xlsx'];
  9. export const compressFormat = ['zip', 'rar', '7z'];
  10. export const allowFormat = pictureFormat.concat(audioFormat, videoFormat, documentFormat, compressFormat); // 所有允许的文件格式
  11. export let accept = `.${allowFormat.join(',.')}`;
  12. // 文件状态列表
  13. export const fileStatusList = [
  14. {
  15. name: '文件格式有误',
  16. type: 'error',
  17. icon: 'error-circle-filled'
  18. },
  19. {
  20. name: '待上传',
  21. type: 'wait',
  22. icon: 'time-filled'
  23. },
  24. {
  25. name: '上传中',
  26. type: 'uploading',
  27. icon: 'loading-blue'
  28. },
  29. {
  30. name: '上传成功',
  31. type: 'success',
  32. icon: 'check-circle-filled',
  33. id: ''
  34. }
  35. ];
  36. // 是否为允许的文件格式
  37. export function allowFileFormat(suffix) {
  38. return allowFormat.includes(suffix);
  39. }
  40. /**
  41. * 上传文件
  42. * @param {ref} file <input type="file" /> 的 refs
  43. * @param {Object} curTemplateData 当前模板数据
  44. */
  45. export function useUploadFile(file, curTemplateData) {
  46. let files = ref(curTemplateData['_files']);
  47. let file_id_list = computed(() => {
  48. return files.value
  49. .filter(({ status: { type } }) => type === fileStatusList[3].type)
  50. .map(({ status: { id } }) => id);
  51. });
  52. watch(
  53. () => file_id_list.value,
  54. () => {
  55. curTemplateData.file_id_list = file_id_list.value;
  56. },
  57. { immediate: true }
  58. );
  59. // 打开选择文件
  60. function uploadFile() {
  61. file.value.value = null;
  62. file.value.click();
  63. }
  64. // 添加到文件列表
  65. function pushFiles(fileList) {
  66. for (const el of fileList) {
  67. files.value.push({
  68. file: el,
  69. status: allowFileFormat(getFileType(el.name)) ? fileStatusList[1] : fileStatusList[0]
  70. });
  71. }
  72. }
  73. function dropFiles(data) {
  74. pushFiles(data.files);
  75. }
  76. function handleFiles({ target }) {
  77. pushFiles(target.files);
  78. }
  79. // 删除文件
  80. function deleteFile(i) {
  81. files.value.splice(i, 1);
  82. }
  83. // 上传文件和中断处理
  84. let controllerFn = ref(null); // 中断上传函数
  85. let isBreak = ref(false); // 是否中断
  86. let fileNum = 0; // 当前上传的文件索引
  87. let uploading = ref(false); // 是否上传中
  88. async function* handleUpload() {
  89. for (fileNum; fileNum < files.value.length; fileNum++) {
  90. if (isBreak.value) return;
  91. let { status, file } = files.value[fileNum];
  92. if (status.type !== fileStatusList[1].type) continue;
  93. let formData = new FormData();
  94. formData.append(file.name, file, file.name);
  95. const { request, progress, controller } = fileUploadAbort('Mid', formData);
  96. const stop = watchEffect(() => {
  97. files.value[fileNum].status = Object.assign({}, fileStatusList[2], { name: `上传${progress.value}%...` });
  98. });
  99. controllerFn.value = controller;
  100. yield request;
  101. stop();
  102. }
  103. }
  104. async function upload() {
  105. if (uploading.value) {
  106. return Message.warning('上传文件中');
  107. }
  108. if (files.value.length <= 0) {
  109. return Message.warning('请先选择文件');
  110. }
  111. if (!files.value.some(({ status: { type } }) => type === fileStatusList[1].type)) {
  112. return Message.warning('没有需要上传的文件');
  113. }
  114. fileNum = 0;
  115. isBreak.value = false;
  116. uploading.value = true;
  117. for await (let data of handleUpload()) {
  118. if ('file_info_list' in data) {
  119. files.value[fileNum].status = { ...fileStatusList[3], id: data.file_info_list?.[0].file_id };
  120. }
  121. }
  122. fileNum = 0;
  123. controllerFn.value = null;
  124. uploading.value = false;
  125. }
  126. // 中断上传
  127. function breakUpload() {
  128. if (!controllerFn.value) {
  129. return Message.warning('没有上传中的文件');
  130. }
  131. isBreak.value = true;
  132. controllerFn.value.abort();
  133. uploading.value = false;
  134. files.value[fileNum].status = fileStatusList[1];
  135. }
  136. return {
  137. files,
  138. uploadFile,
  139. handleFiles,
  140. dropFiles,
  141. deleteFile,
  142. upload,
  143. breakUpload
  144. };
  145. }
  146. /**
  147. * 获取文件图标
  148. * @param {string} type 文件类型
  149. */
  150. export function getFileImage(type) {
  151. if (type === 'txt') {
  152. return require('@/assets/file/txt-bc.png');
  153. }
  154. if (type === 'pdf') {
  155. return require('@/assets/file/pdf-bc.png');
  156. }
  157. if (/^xlsx?$/.test(type)) {
  158. return require('@/assets/file/execl-bc.png');
  159. }
  160. if (/^pptx?$/.test(type)) {
  161. return require('@/assets/file/ppt-bc.png');
  162. }
  163. if (/^docx?$/.test(type)) {
  164. return require('@/assets/file/word-bc.png');
  165. }
  166. }