301 lines
8.0 KiB
JavaScript
301 lines
8.0 KiB
JavaScript
|
|
import request from '@/utils/request';
|
|||
|
|
import service from '@/utils/request';
|
|||
|
|
import { upImageFileInfo } from '@/api/commit.js';
|
|||
|
|
import { ElMessage } from 'element-plus';
|
|||
|
|
|
|||
|
|
// 上传单个文件
|
|||
|
|
export async function uploadSingleFile(file, options = {}) {
|
|||
|
|
try {
|
|||
|
|
// 获取文件对象,确保能够正确访问文件信息
|
|||
|
|
const fileObj = file.file || file;
|
|||
|
|
|
|||
|
|
// 创建临时文件对象用于显示
|
|||
|
|
const tempFile = {
|
|||
|
|
id: `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|||
|
|
originalName: fileObj.name,
|
|||
|
|
uploading: true
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
if (options.uploadedFiles) {
|
|||
|
|
options.uploadedFiles.push(tempFile);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const isImageFile = fileObj.type.startsWith('image/');
|
|||
|
|
// 只有图片文件才压缩
|
|||
|
|
let fileData = isImageFile && options.compressImage ? await options.compressImage(fileObj) : fileObj;
|
|||
|
|
|
|||
|
|
const data = new FormData();
|
|||
|
|
data.append("file", fileData);
|
|||
|
|
|
|||
|
|
// 更新UI状态
|
|||
|
|
if (file.status !== undefined) {
|
|||
|
|
file.status = "uploading";
|
|||
|
|
file.message = "上传中...";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const res = await upImageFileInfo(data);
|
|||
|
|
|
|||
|
|
// 更新文件状态
|
|||
|
|
if (options.uploadedFiles) {
|
|||
|
|
const fileIndex = options.uploadedFiles.findIndex(f => f.id === tempFile.id);
|
|||
|
|
if (fileIndex !== -1) {
|
|||
|
|
options.uploadedFiles[fileIndex] = {
|
|||
|
|
id: res.id || tempFile.id,
|
|||
|
|
originalName: fileObj.name,
|
|||
|
|
uploading: false,
|
|||
|
|
url: res.url,
|
|||
|
|
fileSize: fileObj.size
|
|||
|
|
};
|
|||
|
|
// 更新文件ID列表
|
|||
|
|
if (options.fjIds) {
|
|||
|
|
options.fjIds.push(res);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 更新文件状态
|
|||
|
|
if (file.status !== undefined) {
|
|||
|
|
file.status = "done";
|
|||
|
|
file.message = "上传成功";
|
|||
|
|
file.id = res.id || tempFile.id;
|
|||
|
|
file.url = res.url;
|
|||
|
|
file.originalName = fileObj.name;
|
|||
|
|
file.fileSize = fileObj.size;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ElMessage.success('文件上传成功');
|
|||
|
|
return res;
|
|||
|
|
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('文件上传失败:', error);
|
|||
|
|
ElMessage.error('文件上传失败');
|
|||
|
|
|
|||
|
|
// 更新文件状态
|
|||
|
|
if (file && file.status !== undefined) {
|
|||
|
|
file.status = "failed";
|
|||
|
|
file.message = "上传失败";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取可能的文件名用于查找
|
|||
|
|
const fileName = (file.file?.originalName || file.originalName || '');
|
|||
|
|
|
|||
|
|
// 移除上传失败的文件
|
|||
|
|
if (options.uploadedFiles) {
|
|||
|
|
const fileIndex = options.uploadedFiles.findIndex(f =>
|
|||
|
|
f.originalName === fileName && f.uploading
|
|||
|
|
);
|
|||
|
|
if (fileIndex !== -1) {
|
|||
|
|
options.uploadedFiles.splice(fileIndex, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 上传多个文件
|
|||
|
|
export async function uploadMultipleFiles(files, options = {}) {
|
|||
|
|
if (Array.isArray(files)) {
|
|||
|
|
// 多个文件上传
|
|||
|
|
const results = [];
|
|||
|
|
for (const file of files) {
|
|||
|
|
try {
|
|||
|
|
const result = await uploadSingleFile(file, options);
|
|||
|
|
results.push(result);
|
|||
|
|
} catch (error) {
|
|||
|
|
// 可以选择继续上传其他文件或者中断
|
|||
|
|
if (!options.continueOnError) {
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return results;
|
|||
|
|
} else {
|
|||
|
|
// 单个文件上传
|
|||
|
|
return [await uploadSingleFile(files, options)];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Element Plus 的 el-upload 上传函数
|
|||
|
|
// export function upImageFileInfo(data) {
|
|||
|
|
// return service({
|
|||
|
|
// url: '/mosty-api/mosty-base/minio/file/uploadObj',
|
|||
|
|
// method: 'post',
|
|||
|
|
// data
|
|||
|
|
// });
|
|||
|
|
// }
|
|||
|
|
|
|||
|
|
// 文件下载函数
|
|||
|
|
export function downloadFile(fileUrl, fileName = '') {
|
|||
|
|
return new Promise((resolve, reject) => {
|
|||
|
|
const token = localStorage.getItem('token');
|
|||
|
|
const xhr = new XMLHttpRequest();
|
|||
|
|
|
|||
|
|
xhr.open('GET', fileUrl, true);
|
|||
|
|
xhr.setRequestHeader('Authorization', token);
|
|||
|
|
xhr.responseType = 'blob';
|
|||
|
|
|
|||
|
|
xhr.onload = function () {
|
|||
|
|
if (this.status === 200) {
|
|||
|
|
const blob = this.response;
|
|||
|
|
const link = document.createElement('a');
|
|||
|
|
const url = window.URL.createObjectURL(blob);
|
|||
|
|
|
|||
|
|
link.href = url;
|
|||
|
|
link.download = fileName || 'download';
|
|||
|
|
document.body.appendChild(link);
|
|||
|
|
link.click();
|
|||
|
|
|
|||
|
|
// 清理
|
|||
|
|
setTimeout(() => {
|
|||
|
|
document.body.removeChild(link);
|
|||
|
|
window.URL.revokeObjectURL(url);
|
|||
|
|
}, 0);
|
|||
|
|
|
|||
|
|
resolve({ success: true });
|
|||
|
|
} else {
|
|||
|
|
ElMessage.error('文件下载失败');
|
|||
|
|
reject(new Error('下载失败'));
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
xhr.onerror = function () {
|
|||
|
|
ElMessage.error('网络错误,下载失败');
|
|||
|
|
reject(new Error('网络错误'));
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
xhr.send();
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 删除文件前确认
|
|||
|
|
export function beforeDelete(file) {
|
|||
|
|
return new Promise((resolve) => {
|
|||
|
|
// 创建一个简单的确认对话框
|
|||
|
|
const confirmed = window.confirm(`确定要删除文件"${file.originalName || file.name}"吗?`);
|
|||
|
|
resolve(confirmed);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 删除文件
|
|||
|
|
export async function deleteFile(file, options = {}) {
|
|||
|
|
try {
|
|||
|
|
// 显示确认对话框
|
|||
|
|
const confirm = await beforeDelete(file);
|
|||
|
|
|
|||
|
|
if (confirm) {
|
|||
|
|
const fileId = file.id;
|
|||
|
|
const url = options.url || '/mosty-api/mosty-base/minio/file/delete';
|
|||
|
|
const token = localStorage.getItem('token');
|
|||
|
|
|
|||
|
|
// 调用删除API
|
|||
|
|
const res = await request({
|
|||
|
|
url: url,
|
|||
|
|
method: 'post',
|
|||
|
|
data: { fileId },
|
|||
|
|
headers: {
|
|||
|
|
'Authorization': token
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (res.code === 10000 || res.status === 200) {
|
|||
|
|
// 从已上传文件列表中移除
|
|||
|
|
if (options.uploadedFiles) {
|
|||
|
|
const fileIndex = options.uploadedFiles.findIndex(f =>
|
|||
|
|
f.id === file.id || f.originalName === file.originalName
|
|||
|
|
);
|
|||
|
|
if (fileIndex !== -1) {
|
|||
|
|
options.uploadedFiles.splice(fileIndex, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 从fileList中移除
|
|||
|
|
if (options.fileList) {
|
|||
|
|
const listIndex = options.fileList.findIndex(f => f.id === file.id);
|
|||
|
|
if (listIndex !== -1) {
|
|||
|
|
options.fileList.splice(listIndex, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 从fjIds中移除
|
|||
|
|
if (options.fjIds) {
|
|||
|
|
const fjIndex = options.fjIds.findIndex(f => f.id === file.id);
|
|||
|
|
if (fjIndex !== -1) {
|
|||
|
|
options.fjIds.splice(fjIndex, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ElMessage.success('文件删除成功');
|
|||
|
|
return res;
|
|||
|
|
} else {
|
|||
|
|
ElMessage.error('文件删除失败');
|
|||
|
|
throw new Error('删除失败');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('文件删除失败:', error);
|
|||
|
|
ElMessage.error('文件删除失败');
|
|||
|
|
throw error;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 格式化文件大小
|
|||
|
|
export function formatFileSize(bytes) {
|
|||
|
|
if (bytes === 0) return '0 Bytes';
|
|||
|
|
const k = 1024;
|
|||
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|||
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|||
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// el-upload 组件配置生成器
|
|||
|
|
export function generateUploadConfig(options = {}) {
|
|||
|
|
const {
|
|||
|
|
limit = 3,
|
|||
|
|
accept = '',
|
|||
|
|
action = '/mosty-api/mosty-base/minio/image/upload/id',
|
|||
|
|
onSuccess = () => { },
|
|||
|
|
onRemove = () => { },
|
|||
|
|
onExceed = () => { },
|
|||
|
|
beforeRemove = () => { },
|
|||
|
|
beforeUpload = () => { }
|
|||
|
|
} = options;
|
|||
|
|
|
|||
|
|
// 获取token
|
|||
|
|
const getToken = () => {
|
|||
|
|
return localStorage.getItem('token');
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
headers: {
|
|||
|
|
'Authorization': getToken()
|
|||
|
|
},
|
|||
|
|
action: action,
|
|||
|
|
multiple: true,
|
|||
|
|
limit: limit,
|
|||
|
|
accept: accept,
|
|||
|
|
showFileList: true,
|
|||
|
|
onSuccess: (response, uploadFile, uploadFiles) => {
|
|||
|
|
ElMessage.success('上传成功');
|
|||
|
|
onSuccess(response, uploadFile, uploadFiles);
|
|||
|
|
},
|
|||
|
|
onRemove: (uploadFile, uploadFiles) => {
|
|||
|
|
onRemove(uploadFile, uploadFiles);
|
|||
|
|
},
|
|||
|
|
onExceed: (files, uploadFiles) => {
|
|||
|
|
ElMessage.warning(`最多只能上传 ${limit} 个文件`);
|
|||
|
|
onExceed(files, uploadFiles);
|
|||
|
|
},
|
|||
|
|
beforeRemove: (uploadFile, uploadFiles) => {
|
|||
|
|
const result = beforeRemove(uploadFile, uploadFiles);
|
|||
|
|
if (result === undefined) {
|
|||
|
|
return window.confirm(`确定移除 ${uploadFile.name}?`);
|
|||
|
|
}
|
|||
|
|
return result;
|
|||
|
|
},
|
|||
|
|
beforeUpload: (file) => {
|
|||
|
|
return beforeUpload(file);
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|