import { ref, watchEffect, computed, watch } from 'vue'; import { Message } from 'element-ui'; import { getFileType } from '@/utils/filter'; import { fileUploadAbort } from '@/api/app'; export const pictureFormat = ['webp', 'jpg', 'jpeg', 'gif', 'png', 'tif']; export const audioFormat = ['mp3', 'wma']; export const videoFormat = ['mp4', 'flv', 'webm', 'mpeg', 'mpg']; export const documentFormat = ['txt', 'doc', 'docx', 'pdf', 'ppt', 'pptx', 'xls', 'xlsx']; export const compressFormat = ['zip', 'rar', '7z']; export const allowFormat = pictureFormat.concat(audioFormat, videoFormat, documentFormat, compressFormat); // 所有允许的文件格式 export let accept = `.${allowFormat.join(',.')}`; // 文件状态列表 export const fileStatusList = [ { name: '文件格式有误', type: 'error', icon: 'error-circle-filled' }, { name: '待上传', type: 'wait', icon: 'time-filled' }, { name: '上传中', type: 'uploading', icon: 'loading-blue' }, { name: '上传成功', type: 'success', icon: 'check-circle-filled', id: '' } ]; // 是否为允许的文件格式 export function allowFileFormat(suffix) { return allowFormat.includes(suffix); } /** * 上传文件 * @param {ref} file 的 refs * @param {Object} curTemplateData 当前模板数据 */ export function useUploadFile(file, curTemplateData) { let files = ref(curTemplateData['_files']); let file_id_list = computed(() => { return files.value .filter(({ status: { type } }) => type === fileStatusList[3].type) .map(({ status: { id } }) => id); }); watch( () => file_id_list.value, () => { curTemplateData.file_id_list = file_id_list.value; }, { immediate: true } ); // 打开选择文件 function uploadFile() { file.value.value = null; file.value.click(); } // 添加到文件列表 function pushFiles(fileList) { for (const el of fileList) { files.value.push({ file: el, status: allowFileFormat(getFileType(el.name)) ? fileStatusList[1] : fileStatusList[0] }); } } function dropFiles(data) { pushFiles(data.files); } function handleFiles({ target }) { pushFiles(target.files); } // 删除文件 function deleteFile(i) { files.value.splice(i, 1); } // 上传文件和中断处理 let controllerFn = ref(null); // 中断上传函数 let isBreak = ref(false); // 是否中断 let fileNum = 0; // 当前上传的文件索引 let uploading = ref(false); // 是否上传中 async function* handleUpload() { for (fileNum; fileNum < files.value.length; fileNum++) { if (isBreak.value) return; let { status, file } = files.value[fileNum]; if (status.type !== fileStatusList[1].type) continue; let formData = new FormData(); formData.append(file.name, file, file.name); const { request, progress, controller } = fileUploadAbort('Mid', formData); const stop = watchEffect(() => { files.value[fileNum].status = Object.assign({}, fileStatusList[2], { name: `上传${progress.value}%...` }); }); controllerFn.value = controller; yield request; stop(); } } async function upload() { if (uploading.value) { return Message.warning('上传文件中'); } if (files.value.length <= 0) { return Message.warning('请先选择文件'); } if (!files.value.some(({ status: { type } }) => type === fileStatusList[1].type)) { return Message.warning('没有需要上传的文件'); } fileNum = 0; isBreak.value = false; uploading.value = true; for await (let data of handleUpload()) { if ('file_info_list' in data) { files.value[fileNum].status = { ...fileStatusList[3], id: data.file_info_list?.[0].file_id }; } } fileNum = 0; controllerFn.value = null; uploading.value = false; } // 中断上传 function breakUpload() { if (!controllerFn.value) { return Message.warning('没有上传中的文件'); } isBreak.value = true; controllerFn.value.abort(); uploading.value = false; files.value[fileNum].status = fileStatusList[1]; } return { files, uploadFile, handleFiles, dropFiles, deleteFile, upload, breakUpload }; } /** * 获取文件图标 * @param {string} type 文件类型 */ export function getFileImage(type) { if (type === 'txt') { return require('@/assets/file/txt-bc.png'); } if (type === 'pdf') { return require('@/assets/file/pdf-bc.png'); } if (/^xlsx?$/.test(type)) { return require('@/assets/file/execl-bc.png'); } if (/^pptx?$/.test(type)) { return require('@/assets/file/ppt-bc.png'); } if (/^docx?$/.test(type)) { return require('@/assets/file/word-bc.png'); } }