<template> <!-- 公共图片上传 --> <div class="uploaderPage"> <!-- 上传图片 --> <van-uploader v-model="fileList" :after-read="afterRead" :max-count="maxCount" :max-size="50 * 1024 * 1024" @oversize="onOversize" :accept="acceptFormat" :disabled="isDisabled" :before-delete="deleBrfore" @delete="deleteFile" multiple > </van-uploader> <div v-if="acceptFormat == 'video/*'"> <!-- 显示视频列表 --> <div v-if="fileList.length > 0"> <p v-for="(item, index) in fileList" :key="index" class="van-ellipsis blueFont" @click="checkVideo(item.url)"> {{ item.file ? item.file.name : item.name }} </p> </div> <!-- 查看视频弹窗 --> <van-popup v-model:show="showVideo" class="uploadVideo"> <video v-if="showVideo" style="width: 100vw; height: auto" title="视频" :src="videoUrl" :autoPlay="true" ></video> </van-popup> </div> </div> </template> <script setup name="uploaderPage"> import { fileUpload } from '@/api/publicApi.js'; import { useStore } from '@/pinia/store.js'; import { getCurrentInstance } from 'vue'; import bus from '@/utils/utils'; const props = defineProps({ //最大上传数 maxCount: { type: Number, default: 1, }, //保存的文件数组 saveFileArr: { type: Array, default: () => [], }, // 文件格式 acceptFormat: { type: String, default: 'image/*', // video/* }, // 是否禁用文件上传 isDisabled: { type: Boolean, default: false, }, }); const pinias = useStore(); const { proxy } = getCurrentInstance(); const emit = defineEmits(); const fileList = ref([]); //文件列表 const maxCount = props.maxCount; //最大上传数 const acceptFormat = props.acceptFormat; //文件格式 const showVideo = ref(false); const videoUrl = ref(''); const isdisabled = ref(true); // 查看视频弹窗 function checkVideo(url) { videoUrl.value = url; showVideo.value = true; } // 上传图片2 const afterRead = (file) => { // console.log('file---', Array.isArray(file)); let fileArr = []; if (Array.isArray(file) == true) { // 多个上传 fileArr = file; } else { // 单个上传 fileArr.push(file); } uploadFileFun(fileArr); }; // 图片上传到服务器 function uploadFileFun(fileArr) { bus.emit('isdisabledVisible', isdisabled.value); fileArr.map((fileOBJ) => { fileOBJ.status = 'uploading'; fileOBJ.message = '上传中...'; bus.emit('fileOBJVisible', fileOBJ.message); let imgFile = null; if (fileOBJ.file.size / 1024 / 1024 > 500 && fileOBJ.file.type.includes('image')) { blobToBase64(fileOBJ.file, fileOBJ.file.name).then((res) => { imgFile = res; }); } else { imgFile = fileOBJ.file; } // 配置表单 let formData = new FormData(); let config = { headers: { 'Content-Type': 'multipart/form-data' }, }; formData.append('file', imgFile); fileUpload(formData, config).then((res) => { if (res && res.code == 200) { fileOBJ.status = 'done'; fileOBJ.message = '上传成功'; bus.emit('fileOBJVisible', fileOBJ.message); // 业务参数赋值 fileOBJ.url = res.data.url; fileOBJ.fileCloundInfo = res.data; emit('update:saveFileArr', fileList.value); //绑定的传值赋值 } else { fileOBJ.status = 'failed'; fileOBJ.message = '上传失败'; bus.emit('fileOBJVisible', fileOBJ.message); } }); }); } // 图片删除 const deleBrfore = async (file) => { return true; }; const deleteFile = () => { emit('update:saveFileArr', fileList.value); }; const blobToBase64 = async (blob, fileName) => { const reader = await new FileReader(); // 实例化一个reader文件 await reader.readAsDataURL(blob); // 添加二进制文件 return new Promise((resolve, reject) => { reader.onload = async (event) => { const base64 = await event.target.result; // 获取到它的base64文件 const scale = 0.6; // 设置缩放比例 (0-1) let file = await compressImg(base64, scale, fileName); resolve(file); }; }); }; // 压缩大小 const compressImg = (base64, scale, fileName) => { // 处理缩放,转换格式 // 用canvas来压缩 const img = new Image(); img.src = base64; return new Promise((resolve, reject) => { img.onload = async () => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.setAttribute('width', img.width * scale); canvas.setAttribute('height', img.height * scale); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); // 转成base64 文件 base64 = canvas.toDataURL('image/jpeg', 0.8); //0到1之间的取值,主要用来选定图片的质量,默认值是0.92,超出范围也会选择默认值 const arr = base64.split(','); const mime = arr[0].match(/:(.*?);/)[1]; const bytes = atob(arr[1]); const bytesLength = bytes.length; const u8arr = new Uint8Array(bytesLength); for (let i = 0; i < bytes.length; i++) { u8arr[i] = bytes.charCodeAt(i); } const file = await new File([u8arr], fileName, { type: mime }); resolve(file); }; }); }; function onOversize() { proxy.showFailToast('上传的文件最大为50M'); } onMounted(() => { // console.log('修改时图片回显--', props.saveFileArr); // 修改时图片回显 fileList.value = []; props.saveFileArr.map((item) => { let params = { name: item.name, status: 'success', url: item.url, }; fileList.value.push(params); }); }); onBeforeUnmount(() => { fileList.value = []; }); </script> <style lang="less"> /* 添加这段样式后,Primary Button 会变成红色 */ :root:root { --van-uploader-size: 150px; } .van-uploader__file-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .uploaderPage { width: 100%; .blueFont { color: #0c60e1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } </style>