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); // 获取文件后缀名 function getFileExtension(filename: string) { return filename.slice(((filename.lastIndexOf('.') - 1) >>> 0) + 2); } // 判断是否是允许的文件类型 function isAllowedFileType(filename: string, allowedExtensions: any) { const extension = getFileExtension(filename).toLowerCase(); return allowedExtensions.includes(extension); } const onBeforeUpload = async (options: any) => { const file = options.file; // 文件大小 let isLt2M = true; const allowedExtensions = [ 'jpg', 'jpeg', 'png', 'mp4', 'ppt', 'pptx', 'mp3' ]; if (!isAllowedFileType(file.file.name, allowedExtensions)) { message.error('文件格式不支持'); return false; } 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'; 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, reject) => { // let dataURL = ''; const videoElement = document.createElement('video'); videoElement.setAttribute('crossOrigin', 'Anonymous'); // 处理跨域 videoElement.setAttribute('preload', 'auto'); // auto|metadata|none videoElement.muted = true; videoElement.autoplay = true; videoElement.src = URL.createObjectURL(file); // Listen for 'canplay' to ensure the video is ready for frame capture videoElement.addEventListener('loadedmetadata', () => { // 这里开始播放 videoElement.play(); setTimeout(() => { // 过500ms 暂停, 解决空白问题 videoElement.currentTime = 0; videoElement.pause(); // 创建canvas元素 const canvas: any = document.createElement('canvas'); canvas.width = videoElement.videoWidth; canvas.height = videoElement.videoHeight; // 将视频帧绘制到canvas上 // const ctx = canvas.getContext('2d'); // console.log(videoElement); // ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height); canvas .getContext('2d') .drawImage(videoElement, 0, 0, canvas.width, canvas.height); // 将canvas图像转换为base64格式的数据URI // const dataUrl = canvas.toDataURL('image/png'); // 返回base64格式的数据URI // resolve(dataUrl); canvas.toBlob((blob: any) => { resolve(blob); }); }, 500); }); // 如果视频加载出错,则返回错误信息 videoElement.addEventListener('error', (e: any) => { reject(e); }); // return new Promise((resolve, reject) => { // videoElement.addEventListener('loadedmetadata', () => { // // 这里开始播放 // videoElement.play() // setTimeout(() => { // // 过500ms 暂停, 解决空白问题 // videoElement.pause() // // 创建canvas元素 // const canvas = document.createElement('canvas'); // canvas.width = videoElement.videoWidth; // canvas.height = videoElement.videoHeight; // // 将视频帧绘制到canvas上 // const ctx = canvas.getContext('2d'); // console.log(videoElement); // ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height); // // 将canvas图像转换为base64格式的数据URI // const dataUrl = canvas.toDataURL('image/png'); // console.log(dataUrl); // thumbnail.src = dataUrl; // thumbnail.style.display = 'inline'; // // 返回base64格式的数据URI // resolve(dataUrl); // }, 500); // }); // // 如果视频加载出错,则返回错误信息 // videoElement.addEventListener('error', () => { // reject(`Failed to load video: ${videoUrl}`); // }); // }); // videoElement.addEventListener('canplay', function () { // console.log('Video can play'); // const canvas: any = document.createElement('canvas'), // width = videoElement.videoWidth, // height = videoElement.videoHeight; // canvas.width = width; // canvas.height = height; // canvas.getContext('2d').drawImage(videoElement, 0, 0, width, height); // canvas.toBlob((blob: any) => { // resolve(blob); // }); // }); // videoElement.addEventListener('error', function (e) { // console.error('Error loading video:', e); // reject(e); // }); }); }; 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')}> 取消 确定
); } });