123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- 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<number>,
- default: 1
- },
- multiple: {
- type: Boolean as PropType<boolean>,
- default: false
- },
- disabled: {
- type: Boolean as PropType<boolean>,
- default: false
- },
- bucketName: {
- type: String,
- default: 'gyt'
- },
- directoryDnd: {
- type: Boolean as PropType<boolean>,
- 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<boolean>(false);
- const btnLoading = ref<boolean>(false);
- const tempFiileBuffer = ref();
- const uploadRef = ref();
- const state = reactive([]) as any;
- const fileListRef = ref<UploadFileInfo[]>([]);
- 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 || btnLoading.value;
- });
- 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 () => (
- <div class={styles.saveModal}>
- <NUpload
- ref={uploadRef}
- action={ossUploadUrl}
- data={(file: any) => {
- 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)}>
- <NUploadDragger>
- <div class={styles.uploadBtn}>
- <div class={styles.iconUploadAdd} />
- <h3>点击或者拖动文件到该区域来上传</h3>
- <p>
- 仅支持JPG、PNG、MP3、MP4格式文件,单次最多支持
- <br />
- 上传10个文件
- </p>
- </div>
- </NUploadDragger>
- </NUpload>
- <NSpace class={styles.btnGroup} justify="center">
- <NButton round onClick={() => emit('close')}>
- 取消
- </NButton>
- <NButton
- round
- type="primary"
- disabled={uploadStatus.value}
- onClick={onSubmit}>
- 确定
- </NButton>
- </NSpace>
- </div>
- );
- }
- });
|