import { PropType, computed, defineComponent, reactive, ref } from 'vue'; import styles from './index.module.less'; import { NButton, NSpace, NUpload, NUploadDragger, 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'; 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 : '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); state.push({ id: file.id, tempFiileBuffer: file.file, policy: data.policy, signature: data.signature, acl: 'public-read', key: fileName, KSSAccessKeyId: data.kssAccessKeyId, name: fileName }); // tempFiileBuffer.value = file.file; } 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) => { // console.log(options, 'onFinish'); onFinishAfter(options); }; const onFinishAfter = async (options: any) => { const item = state.find((c: any) => c.id == options.file.id); const url = ossUploadUrl + item.key; const type = formatUrlType(url); let coverImg = ''; if (type === 'IMG') { coverImg = url; } else if (type === 'SONG') { coverImg = PageEnum.SONG_DEFAULT_COVER; } else if (type === 'VIDEO') { // 获取视频封面图 coverImg = await getVideoCoverImg(item.tempFiileBuffer); } // emit('update:fileList', url); // emit('readFileInputEventAsArrayBuffer', item.tempFiileBuffer); // console.log(url, 'url onFinishAfter'); // emit('finished', { // coverImg, // content: url // }); uploadList.value.push({ coverImg, content: url, id: options.file.id, name: options.file.name ? options.file.name.slice(0, options.file.name.lastIndexOf('.')) : '' }); options.file.url = url; 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 policy(obj); const fileParams = { policy: data.policy, signature: data.signature, key: fileName, acl: 'public-read', KSSAccessKeyId: data.kssAccessKeyId, name: fileName } as any; const formData = new FormData(); for (const key in fileParams) { formData.append(key, fileParams[key]); } formData.append('file', imgBlob); await axios.post(ossUploadUrl, formData); const url = ossUploadUrl + fileName; return url; } 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 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 () => (
{ const item = state.find((c: any) => { return c.id == file.file.id; }); const { id, tempFiileBuffer, ...more } = item; return { ...more }; }} v-model:fileList={fileListRef.value} accept=".jpg,jpeg,.png,audio/mp3,video/mp4" 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格式文件,单次最多支持
上传10个文件

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