Newer
Older
KaiFengH5 / src / views / components / uploadFile.vue
@zhangdeliang zhangdeliang 29 days ago 5 KB update
<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';

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('');

// 查看视频弹窗
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) {
  fileArr.map((fileOBJ) => {
    fileOBJ.status = 'uploading';
    fileOBJ.message = '上传中...';
    let imgFile = null;
    if (fileOBJ.file.size / 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 = '上传成功';
        // 业务参数赋值
        fileOBJ.url = res.data.url;
        fileOBJ.fileCloundInfo = res.data;
        emit('update:saveFileArr', fileList.value); //绑定的传值赋值
      } else {
        fileOBJ.status = 'failed';
        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>