import { PropType, computed, defineComponent, reactive, ref } from 'vue'; import styles from './index.module.less'; import { NButton, NSpace, NUpload, NUploadDragger, UploadCustomRequestOptions, UploadFileInfo, useMessage } from 'naive-ui'; import iconUploadAdd from '../../../images/icon-upload-add.png'; import { NaturalTypeEnum, PageEnum } from '/src/enums/pageEnum'; import { policy } from '/src/components/upload-file/api'; import { formatUrlType } from '../upload-modal'; import axios from 'axios'; import { getUploadSign, onFileUpload, onOnlyFileUpload, ossSwitch } from '/src/helpers/oss-file-upload'; export default defineComponent({ name: 'save-modal', props: { fileList: { type: String, default: '' }, imageList: { type: Array, default: () => [] }, accept: { // 支持类型 type: String, default: '.jpg,.png,.jpeg,.gif' }, showType: { type: String as PropType<'default' | 'custom'>, default: 'default' }, showFileList: { type: Boolean, default: true }, max: { type: Number as PropType, default: 1 }, multiple: { type: Boolean as PropType, default: false }, disabled: { type: Boolean as PropType, default: false }, bucketName: { type: String, default: 'gyt' }, directoryDnd: { type: Boolean as PropType, default: false }, path: { type: String, default: '' }, fileName: { type: String, default: '' } }, emits: ['close', 'confrim'], setup(props, { emit }) { const ossUploadUrl = `https://${props.bucketName}.ks3-cn-beijing.ksyuncs.com/`; const message = useMessage(); const visiable = ref(false); const btnLoading = ref(false); const tempFiileBuffer = ref(); const uploadRef = ref(); const state = reactive([]) as any; const fileListRef = ref([]); const uploadList = ref([] as any); const onBeforeUpload = async (options: any) => { const file = options.file; // 文件大小 let isLt2M = true; const type = file.type.includes('image') ? NaturalTypeEnum.IMG : file.type.includes('audio') ? NaturalTypeEnum.SONG : file.type.includes('video') ? NaturalTypeEnum.VIDEO : file.type.includes('vnd.openxmlformats-officedocument.presentationml.presentation') || file.type.includes('vnd.ms-powerpoint') ? NaturalTypeEnum.PPT : 'other'; console.log(type, 'type'); if (type === 'other') { message.error(`文件格式不支持`); return false; } const size = type === 'IMG' ? 2 : type === 'SONG' ? 20 : 500; if (size) { isLt2M = file.file.size / 1024 / 1024 < size; if (!isLt2M) { const typeStr = type === 'IMG' ? '图片' : type === 'SONG' ? '音频' : '视频'; message.error(`${typeStr}大小不能超过${size}M`); return false; } } if (!isLt2M) { return isLt2M; } // 是否裁切 // if (props.cropper && type === 'IMG') { // getBase64(file.file, (imageUrl: any) => { // const target = Object.assign({}, props.options, { // img: imageUrl, // name: file.file.name // 上传文件名 // }); // visiable.value = true; // setTimeout(() => { // CropperModal.value?.edit(target); // }, 100); // }); // return false; // } try { btnLoading.value = true; const name = file.file.name; const suffix = name.slice(name.lastIndexOf('.')); const fileName = `${props.path}${Date.now() + file.id + suffix}`; const obj = { filename: fileName, bucketName: props.bucketName, postData: { filename: fileName, acl: 'public-read', key: fileName, unknowValueField: [] } }; // const { data } = await policy(obj); const { data } = await getUploadSign(obj); state.push({ id: file.id, tempFiileBuffer: file.file, policy: data.policy, signature: data.signature, acl: 'public-read', key: fileName, KSSAccessKeyId: data.kssAccessKeyId, name: fileName }); } catch { // // message.error('上传失败') btnLoading.value = false; return false; } return true; }; // const getBase64 = async (img: any, callback: any) => { // const reader = new FileReader(); // reader.addEventListener('load', () => callback(reader.result)); // reader.readAsDataURL(img); // }; const onFinish = (options: any) => { onFinishAfter(options); }; const onFinishAfter = async (options: any) => { console.log(options, 'onFinishAfter'); const item = state.find((c: any) => c.id == options.file.id); const type = formatUrlType(options.file.url); let coverImg = ''; if (type === 'IMG') { coverImg = options.file.url; } else if (type === 'SONG') { coverImg = PageEnum.SONG_DEFAULT_COVER; } else if (type === 'PPT') { coverImg = PageEnum.PPT_DEFAULT_COVER; } else if (type === 'VIDEO') { // 获取视频封面图 coverImg = await getVideoCoverImg(item.tempFiileBuffer); } uploadList.value.push({ coverImg, content: options.file.url, id: options.file.id, name: options.file.name ? options.file.name.slice(0, options.file.name.lastIndexOf('.')) : '' }); visiable.value = false; btnLoading.value = false; }; const getVideoMsg = (file: any) => { return new Promise(resolve => { // let dataURL = ''; const videoElement = document.createElement('video'); videoElement.currentTime = 1; videoElement.src = URL.createObjectURL(file); videoElement.addEventListener('loadeddata', function () { const canvas: any = document.createElement('canvas'), width = videoElement.videoWidth, //canvas的尺寸和图片一样 height = videoElement.videoHeight; canvas.width = width; canvas.height = height; canvas.getContext('2d').drawImage(videoElement, 0, 0, width, height); //绘制canvas // dataURL = canvas.toDataURL('image/jpeg'); //转换为base64 // console.log(canvas); canvas.toBlob((blob: any) => { // console.log(blob); resolve(blob); }); }); }); }; const getVideoCoverImg = async (file: any) => { try { btnLoading.value = true; const imgBlob: any = await getVideoMsg(file || tempFiileBuffer.value); const fileName = `${props.path}${Date.now() + '.png'}`; const obj = { filename: fileName, bucketName: props.bucketName, postData: { filename: fileName, acl: 'public-read', key: fileName, unknowValueField: [] } }; const { data } = await getUploadSign(obj); const fileParams = { policy: data.policy, signature: data.signature, key: fileName, acl: 'public-read', KSSAccessKeyId: data.kssAccessKeyId, name: fileName, file: imgBlob } as any; const res = await onOnlyFileUpload(ossUploadUrl, fileParams); return res; } finally { btnLoading.value = false; } }; const onRemove = async (file: any) => { const index = uploadList.value.findIndex( (update: any) => update.id === file.file.id ); uploadList.value.splice(index, 1); btnLoading.value = false; return true; }; const uploadStatus = computed(() => { let status = false; fileListRef.value.forEach((file: any) => { if (file.status !== 'finished') { status = true; } }); return status || fileListRef.value.length <= 0; }); const onCustomRequest = ({ file, // data, // headers, // withCredentials, action, onFinish, onError, onProgress }: UploadCustomRequestOptions) => { const item = state.find((c: any) => { return c.id == file.id; }); item.file = file; onFileUpload({ file, action, data: item, onProgress, onFinish, onError }); }; const onSubmit = async () => { const list: any = []; fileListRef.value.forEach((file: any) => { const item = uploadList.value.find( (child: any) => child.id === file.id ); if (item) { list.push(item); } }); emit('confrim', list); }; return () => (
{ // return { ...more }; // }} customRequest={onCustomRequest} v-model:fileList={fileListRef.value} accept=".jpg,jpeg,.png,audio/mp3,video/mp4,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation" multiple={true} max={10} // disabled={props.disabled} showFileList={true} showPreviewButton onBeforeUpload={(options: any) => onBeforeUpload(options)} onFinish={(options: any) => { onFinish(options); }} onRemove={(options: any) => onRemove(options)}>

点击或者拖动文件到该区域来上传

仅支持JPG、PNG、MP3、MP4、PPT格式文件,单次最多支持
上传10个文件

emit('close')}> 取消 确定
); } });