优化单图、多图、文件上传

This commit is contained in:
zjl 2024-12-23 10:11:31 +08:00
parent f8ba48fc07
commit b48fe03616
4 changed files with 167 additions and 96 deletions

View File

@ -72,7 +72,11 @@
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
import { notification } from 'ant-design-vue'; import { notification } from 'ant-design-vue';
import Cropper from '@/components/Upload/croppers.vue'; import Cropper from '@/components/Upload/croppers.vue';
import OSS from "ali-oss"; import OSS from 'ali-oss';
/**
* 定义参数
*/
interface UploadFileProps { interface UploadFileProps {
imageUrl?: string; // ==> imageUrl?: string; // ==>
uploadFileUrl?: string; // api api ==> uploadFileUrl?: string; // api api ==>
@ -89,7 +93,9 @@
cropperSize?: Object; cropperSize?: Object;
} }
// /**
* 接受父组件参数
*/
const props = withDefaults(defineProps<UploadFileProps>(), { const props = withDefaults(defineProps<UploadFileProps>(), {
imageUrl: '', imageUrl: '',
uploadFileUrl: '/admin/file/upload', uploadFileUrl: '/admin/file/upload',
@ -107,8 +113,11 @@
// id // id
const uuid = ref('id-' + generateUUID()); const uuid = ref('id-' + generateUUID());
const imgViewVisible = ref(false); const imgViewVisible = ref(false);
/**
* 执行图片预览
*/
const viewImg = () => { const viewImg = () => {
if (props.imageUrl.indexOf('.pdf') < 0) { if (props.imageUrl.indexOf('.pdf') < 0) {
imgViewVisible.value = true; imgViewVisible.value = true;
@ -133,6 +142,9 @@
(e: 'changeFileName', value: string): void; (e: 'changeFileName', value: string): void;
} }
/**
* 定义参数
*/
const fileName = ref(''); const fileName = ref('');
const oImg = ref(''); const oImg = ref('');
const cropperVisible = ref(false); const cropperVisible = ref(false);
@ -140,10 +152,18 @@
const loading = ref(false); const loading = ref(false);
const progress = ref(0); const progress = ref(0);
/**
* 裁剪上传
* @param fileChile 参数
*/
const cropperSuccess = (fileChile: any) => { const cropperSuccess = (fileChile: any) => {
actionFile(fileChile); actionFile(fileChile);
}; };
//
/**
* 本地接口上传
* @param fileChild 参数
*/
const actionFile = async (fileChild: any) => { const actionFile = async (fileChild: any) => {
loading.value = true; loading.value = true;
try { try {
@ -162,29 +182,36 @@
loading.value = false; loading.value = false;
} }
}; };
//oss
/**
* 阿里云OSS上传
* @param fileChild 参数
*/
const actionFiles = async (fileChild: any) => { const actionFiles = async (fileChild: any) => {
const configData = await getOssConfig() const configData = await getOssConfig();
let date = new Date(); let date = new Date();
let year = date.getFullYear(); let year = date.getFullYear();
let month: string | number = date.getMonth() + 1; let month: string | number = date.getMonth() + 1;
month = month < 10 ? ("0" + month) : month; month = month < 10 ? '0' + month : month;
let day: string | number = date.getDate(); let day: string | number = date.getDate();
day = day < 10 ? ("0" + day) : day; day = day < 10 ? '0' + day : day;
let h: string | number = date.getHours(); let h: string | number = date.getHours();
h = h < 10 ? ("0" + h) : h; h = h < 10 ? '0' + h : h;
let minute: string | number = date.getMinutes(); let minute: string | number = date.getMinutes();
minute = minute < 10 ? ("0" + minute) : minute; minute = minute < 10 ? '0' + minute : minute;
let second: string | number = date.getSeconds(); let second: string | number = date.getSeconds();
second = second < 10 ? ("0" + second) : second; second = second < 10 ? '0' + second : second;
let time = h + "" + minute + "" + second; let time = h + '' + minute + '' + second;
let filterFileName=time + "-" + fileChild.name let filterFileName = time + '-' + fileChild.name;
filterFileName=filterFileName.replace(/[\+\_\,\!\|\~\`\(\)\#\$\%\^\&\*\{\}\:\;\"\<\>\?]/g, '') filterFileName = filterFileName.replace(
let filePath = props.name + "/" + year + "/" + month + "/" + day + "/" + filterFileName; /[\+\_\,\!\|\~\`\(\)\#\$\%\^\&\*\{\}\:\;\"\<\>\?]/g,
loading.value=true '',
);
let filePath = props.name + '/' + year + '/' + month + '/' + day + '/' + filterFileName;
loading.value = true;
try { try {
const headers = { const headers = {
"Access-Control-Allow-Origin": "*" 'Access-Control-Allow-Origin': '*',
}; };
const client = new OSS({ const client = new OSS({
// yourRegionBucket1yourRegionoss-cn-hangzhou // yourRegionBucket1yourRegionoss-cn-hangzhou
@ -196,13 +223,13 @@
accessKeySecret: configData.oss_accessKeySecret, accessKeySecret: configData.oss_accessKeySecret,
// Bucket // Bucket
bucket: configData.oss_bucketName, bucket: configData.oss_bucketName,
timeout: 600000 timeout: 600000,
}); });
const res = await client.multipartUpload(filePath, fileChild, { const res = await client.multipartUpload(filePath, fileChild, {
headers: headers, headers: headers,
// //
progress: (p, cpt, res) => { progress: (p, cpt, res) => {
progress.value= parseFloat(parseFloat(p * 100).toFixed(2)) progress.value = parseFloat(parseFloat(p * 100).toFixed(2));
handleHttpUploadOptions.value.onProgress({ percent: progress.value }); handleHttpUploadOptions.value.onProgress({ percent: progress.value });
}, },
// //
@ -210,21 +237,23 @@
// 1 MB100 KB // 1 MB100 KB
partSize: 1024 * 1024, partSize: 1024 * 1024,
// headers, // headers,
mime: fileChild.type mime: fileChild.type,
}); });
emit('update:imageUrl', configData.oss_domain + res.name); emit('update:imageUrl', configData.oss_domain + res.name);
emit('changeFileName',fileChild.name) emit('changeFileName', fileChild.name);
} catch (error) { } catch (error) {
emit('update:imageUrl', ''); emit('update:imageUrl', '');
emit('changeFileName','') emit('changeFileName', '');
} finally { } finally {
progress.value=0 progress.value = 0;
loading.value=false loading.value = false;
}
} }
};
/**
* 执行文件上传
*/
const handleHttpUploadOptions = ref({}); const handleHttpUploadOptions = ref({});
const handleHttpUpload = async (options) => { const handleHttpUpload = async (options) => {
handleHttpUploadOptions.value = options; handleHttpUploadOptions.value = options;
if (props.cropper) { if (props.cropper) {

View File

@ -48,11 +48,13 @@
ZoomInOutlined, ZoomInOutlined,
} from '@ant-design/icons-vue'; } from '@ant-design/icons-vue';
import { notification } from 'ant-design-vue'; import { notification } from 'ant-design-vue';
import OSS from "ali-oss"; import OSS from 'ali-oss';
const uploadRef = ref(); const uploadRef = ref();
import { upload, getOssConfig } from '@/api/common'; import { upload, getOssConfig } from '@/api/common';
// /**
* 接受父组件参数
*/
const props = defineProps({ const props = defineProps({
zIndex: { zIndex: {
default: -1, default: -1,
@ -107,12 +109,14 @@
return props.disabled; return props.disabled;
}); });
let editIndex = ''; let editIndex = '';
const emit = defineEmits(['upload']); const emit = defineEmits(['upload']);
const progress = ref(0); const progress = ref(0);
const loading = ref(false); const loading = ref(false);
// /**
* 本地接口上传
* @param options 参数
*/
const handleHttpUpload = async (options) => { const handleHttpUpload = async (options) => {
loading.value = true; loading.value = true;
try { try {
@ -160,29 +164,32 @@
} }
}; };
//oss /**
* 阿里云OSS上传
* @param options 参数
*/
const handleHttpUploads = async (options: UploadRequestOptions) => { const handleHttpUploads = async (options: UploadRequestOptions) => {
const configData = await getOssConfig() const configData = await getOssConfig();
let date = new Date(); let date = new Date();
let year = date.getFullYear(); let year = date.getFullYear();
let month: string | number = date.getMonth() + 1; let month: string | number = date.getMonth() + 1;
month = month < 10 ? ("0" + month) : month; month = month < 10 ? '0' + month : month;
let day: string | number = date.getDate(); let day: string | number = date.getDate();
day = day < 10 ? ("0" + day) : day; day = day < 10 ? '0' + day : day;
let h: string | number = date.getHours(); let h: string | number = date.getHours();
h = h < 10 ? ("0" + h) : h; h = h < 10 ? '0' + h : h;
let minute: string | number = date.getMinutes(); let minute: string | number = date.getMinutes();
minute = minute < 10 ? ("0" + minute) : minute; minute = minute < 10 ? '0' + minute : minute;
let second: string | number = date.getSeconds(); let second: string | number = date.getSeconds();
second = second < 10 ? ("0" + second) : second; second = second < 10 ? '0' + second : second;
let time = h + "" + minute + "" + second; let time = h + '' + minute + '' + second;
let fileName = time + "-" + options.file.name let fileName = time + '-' + options.file.name;
fileName = fileName.replace(/[\+\_\,\!\|\~\`\(\)\#\$\%\^\&\*\{\}\:\;\"\<\>\?]/g, '') fileName = fileName.replace(/[\+\_\,\!\|\~\`\(\)\#\$\%\^\&\*\{\}\:\;\"\<\>\?]/g, '');
let filePath = props.name + "/" + year + "/" + month + "/" + day + "/" + fileName; let filePath = props.name + '/' + year + '/' + month + '/' + day + '/' + fileName;
loading.value = true; loading.value = true;
try { try {
const headers = { const headers = {
"Access-Control-Allow-Origin": "*" 'Access-Control-Allow-Origin': '*',
}; };
const client = new OSS({ const client = new OSS({
// yourRegionBucket1yourRegionoss-cn-hangzhou // yourRegionBucket1yourRegionoss-cn-hangzhou
@ -194,13 +201,13 @@
accessKeySecret: configData.oss_accessKeySecret, accessKeySecret: configData.oss_accessKeySecret,
// Bucket // Bucket
bucket: configData.oss_bucketName, bucket: configData.oss_bucketName,
timeout: 600000 timeout: 600000,
}); });
const res = await client.multipartUpload(filePath, options.file, { const res = await client.multipartUpload(filePath, options.file, {
headers: headers, headers: headers,
// //
progress: (p, cpt, res) => { progress: (p, cpt, res) => {
progress.value = parseFloat(parseFloat(p * 100).toFixed(2)) progress.value = parseFloat(parseFloat(p * 100).toFixed(2));
options.onProgress({ percent: parseFloat(parseFloat(p * 100).toFixed(2)) }); options.onProgress({ percent: parseFloat(parseFloat(p * 100).toFixed(2)) });
}, },
// //
@ -208,31 +215,31 @@
// 1 MB100 KB // 1 MB100 KB
partSize: 1024 * 1024, partSize: 1024 * 1024,
// headers, // headers,
mime: options.file.type mime: options.file.type,
}); });
// //
const fileUrl = configData.oss_domain + res.name; const fileUrl = configData.oss_domain + res.name;
if (props.multiple) { if (props.multiple) {
let list = JSON.parse(JSON.stringify(props.fileList)) let list = JSON.parse(JSON.stringify(props.fileList));
if (editIndex !== '') { if (editIndex !== '') {
list.splice(editIndex, 1, { list.splice(editIndex, 1, {
url: fileUrl, url: fileUrl,
name: options.file.name, name: options.file.name,
filePath: fileUrl, filePath: fileUrl,
fileName: options.file.name fileName: options.file.name,
}) });
editIndex = '' editIndex = '';
} else { } else {
list.push({ list.push({
url: fileUrl, url: fileUrl,
name: options.file.name, name: options.file.name,
filePath: fileUrl, filePath: fileUrl,
fileName: options.file.name fileName: options.file.name,
}) });
} }
emit('upload', list,props.zIndex) emit('upload', list, props.zIndex);
} else { } else {
emit("upload", fileUrl, options.file.name, props.zIndex); emit('upload', fileUrl, options.file.name, props.zIndex);
} }
} catch (error) { } catch (error) {
notification.error({ notification.error({
@ -247,19 +254,33 @@
} }
options.onError(error as any); options.onError(error as any);
} finally { } finally {
progress.value = 0 progress.value = 0;
loading.value = false; loading.value = false;
} }
}; };
/**
* 执行图片预览
* @param index 参数
*/
const onPreview = (index: any) => { const onPreview = (index: any) => {
window.open(props.fileList[index].filePath); window.open(props.fileList[index].filePath);
}; };
/**
* 执行编辑
* @param index 参数
*/
const handleEdit = (index: any) => { const handleEdit = (index: any) => {
editIndex = index; editIndex = index;
const dom = document.querySelector(`.ant-upload #${uuid.value}`); const dom = document.querySelector(`.ant-upload #${uuid.value}`);
dom && dom.dispatchEvent(new MouseEvent('click')); dom && dom.dispatchEvent(new MouseEvent('click'));
}; };
/**
* 执行删除
* @param index 参数
*/
const handleRemove = (index: any) => { const handleRemove = (index: any) => {
editIndex = index; editIndex = index;
if (props.multiple) { if (props.multiple) {
@ -274,6 +295,9 @@
} }
}; };
/**
* 设置最大允许上传张数
*/
const onExceed = () => { const onExceed = () => {
if (props.limit) { if (props.limit) {
notification.warning({ notification.warning({

View File

@ -60,11 +60,13 @@
import { notification } from 'ant-design-vue'; import { notification } from 'ant-design-vue';
import { generateUUID } from '@/utils/auth'; import { generateUUID } from '@/utils/auth';
import OSS from "ali-oss"; import OSS from 'ali-oss';
const uploadRef = ref(); const uploadRef = ref();
import { upload, getOssConfig } from '@/api/common'; import { upload, getOssConfig } from '@/api/common';
// /**
* 接受父组件参数
*/
const props = defineProps({ const props = defineProps({
zIndex: { zIndex: {
default: -1, default: -1,
@ -119,7 +121,6 @@
// id // id
const uuid = ref('id-' + generateUUID()); const uuid = ref('id-' + generateUUID());
const getCSSProperties = computed(() => { const getCSSProperties = computed(() => {
return { return {
width: `${props.width}px`, width: `${props.width}px`,
@ -133,7 +134,11 @@
const emit = defineEmits(['upload']); const emit = defineEmits(['upload']);
const loading = ref(false); const loading = ref(false);
//
/**
* 本地接口上传
* @param options 参数
*/
const handleHttpUpload = async (options) => { const handleHttpUpload = async (options) => {
if (!props.autoUpload) { if (!props.autoUpload) {
emit('upload', options); emit('upload', options);
@ -172,31 +177,36 @@
loading.value = false; loading.value = false;
} }
}; };
//oss
/**
* 阿里云OSS上传
* @param options 参数
*/
const handleHttpUploads = async (options: UploadRequestOptions) => { const handleHttpUploads = async (options: UploadRequestOptions) => {
if (!props.autoUpload) { if (!props.autoUpload) {
emit('upload', options); emit('upload', options);
return; return;
} }
const configData = await getOssConfig() const configData = await getOssConfig();
let date = new Date(); let date = new Date();
let year = date.getFullYear(); let year = date.getFullYear();
let month: string | number = date.getMonth() + 1; let month: string | number = date.getMonth() + 1;
month = month < 10 ? ("0" + month) : month; month = month < 10 ? '0' + month : month;
let day: string | number = date.getDate(); let day: string | number = date.getDate();
day = day < 10 ? ("0" + day) : day; day = day < 10 ? '0' + day : day;
let h: string | number = date.getHours(); let h: string | number = date.getHours();
h = h < 10 ? ("0" + h) : h; h = h < 10 ? '0' + h : h;
let minute: string | number = date.getMinutes(); let minute: string | number = date.getMinutes();
minute = minute < 10 ? ("0" + minute) : minute; minute = minute < 10 ? '0' + minute : minute;
let second: string | number = date.getSeconds(); let second: string | number = date.getSeconds();
second = second < 10 ? ("0" + second) : second; second = second < 10 ? '0' + second : second;
let time = h + "" + minute + "" + second; let time = h + '' + minute + '' + second;
let name = props.name + "/"+ year + "/" + month + "/" + day + "/" + time + "-" + options.file.name; let name =
props.name + '/' + year + '/' + month + '/' + day + '/' + time + '-' + options.file.name;
loading.value = true; loading.value = true;
try { try {
const headers = { const headers = {
"Access-Control-Allow-Origin": "*" 'Access-Control-Allow-Origin': '*',
}; };
const client = new OSS({ const client = new OSS({
// yourRegionBucket1yourRegionoss-cn-hangzhou // yourRegionBucket1yourRegionoss-cn-hangzhou
@ -208,7 +218,7 @@
accessKeySecret: configData.oss_accessKeySecret, accessKeySecret: configData.oss_accessKeySecret,
// Bucket // Bucket
bucket: configData.oss_bucketName, bucket: configData.oss_bucketName,
timeout: 600000 timeout: 600000,
}); });
const res = await client.multipartUpload(name, options.file, { const res = await client.multipartUpload(name, options.file, {
headers: headers, headers: headers,
@ -221,7 +231,7 @@
// 1 MB100 KB // 1 MB100 KB
partSize: 1024 * 1024, partSize: 1024 * 1024,
// headers, // headers,
mime: options.file.type mime: options.file.type,
}); });
if (props.multiple) { if (props.multiple) {
let list = JSON.parse(JSON.stringify(props.fileList)); let list = JSON.parse(JSON.stringify(props.fileList));
@ -233,7 +243,7 @@
}); });
emit('upload', list, props.zIndex); emit('upload', list, props.zIndex);
} else { } else {
emit("upload", configData.oss_domain + res.name,options.file.name, props.zIndex); emit('upload', configData.oss_domain + res.name, options.file.name, props.zIndex);
} }
} catch (error) { } catch (error) {
notification.error({ notification.error({
@ -251,11 +261,18 @@
} }
}; };
/**
* 执行游览
* @param uploadFile 文件
*/
const onPreview = (uploadFile) => { const onPreview = (uploadFile) => {
window.open(uploadFile?.url); window.open(uploadFile?.url);
}; };
/**
* 执行删除
* @param file 文件参数
*/
const handleRemove = (file: any) => { const handleRemove = (file: any) => {
if (props.multiple) { if (props.multiple) {
emit( emit(

View File

@ -53,7 +53,8 @@
@change-file-name="(name) => (formData.coverImgName = name)" @change-file-name="(name) => (formData.coverImgName = name)"
:fileType="['image/jpeg', 'image/png', 'image/jpg', 'image/gif']" :fileType="['image/jpeg', 'image/png', 'image/jpg', 'image/gif']"
name="article" name="article"
:fileSize="200" :fileSize="20"
:limit="5"
v-model:image-url="formData.cover" v-model:image-url="formData.cover"
> >
<template #tip>支持扩展名: jpg png jpeg;文件大小不超过200M</template> <template #tip>支持扩展名: jpg png jpeg;文件大小不超过200M</template>