Newer
Older
KaiFengWechat / src / views / components / uploadFile.vue
@鲁yixuan 鲁yixuan on 12 Jul 6 KB update
<template>
  <!-- 公共图片上传 -->
  <div class="uploaderPage">
    <!-- 上传图片 -->
    <van-uploader
      v-model="fileList"
      :before-read="beforeRead"
      @delete="deletePic"
      :max-count="maxCount"
      :max-size="50 * 1024 * 1024"
      @oversize="onOversize"
      :accept="acceptFormat"
      :disabled="isDisabled"
    >
    </van-uploader>
    <div v-if="acceptFormat == 'video/*'">
      <!-- 显示视频列表 -->
      <div v-if="uploadList.length > 0">
        <p v-for="item in uploadList" :key="item.name" class="van-ellipsis blueFont" @click="checkVideo(item.url)">
          {{ item.originalName }}
        </p>
      </div>
      <!-- 查看视频弹窗 -->
      <!-- <van-popup v-model:show="showVideo" position="center" closeable class="uploadVideo" :style="{ width: '100%' }">
          <vue3VideoPlay width="100%" title="视频" :src="videoUrl" :autoPlay="true" />
        </van-popup> -->
    </div>
  </div>
</template>

<script setup name="uploaderPage">
import { onMounted, ref, onBeforeUnmount } from 'vue';
import { fileUpload, fileDelete } from '@/api/publicApi.js';
import { useStore } from '@/pinia/store.js';
import { getCurrentInstance } from 'vue';
// import 'vue3-video-play/dist/style.css';
// import vue3VideoPlay from 'vue3-video-play';

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 uploadList = ref([]);
const maxCount = props.maxCount; //最大上传数
const showVideo = ref(false);
const videoUrl = ref('');

// 查看视频弹窗
function checkVideo(url) {
  videoUrl.value = url;
  console.log(videoUrl.value, '  videoUrl.value');
  showVideo.value = true;
}
// 开始上传图片
const beforeRead = async (file) => {
  // console.log(file, '原本上传的文件--');
  // 压缩图片,大于500kb就压缩
  let imgFile = null;
  if (file.size / 1024 > 500 && file.type.includes('image')) {
    imgFile = await blobToBase64(file, file.name);
  } else {
    imgFile = file;
  }
  // console.log(imgFile, '压缩后的图片文件获取');
  pinias.showLoading();
  let formData = new FormData();
  let config = {
    headers: { 'Content-Type': 'multipart/form-data' },
  };
  formData.append('file', imgFile);
  let res = await fileUpload(formData, config);
  if (res && res.code == 200) {
    uploadList.value.push(res.data);
    console.log(uploadList.value, '  uploadList.value');

    emit('update:saveFileArr', uploadList.value); //绑定的传值赋值
    proxy.showSuccessToast('上传成功');
  } else {
    fileList.value = [];
    let param = {
      id: imgFile.id,
      name: imgFile.name,
      status: 'error',
    };
    fileList.value.push(param);
    proxy.showFailToast('上传失败');
  }
  pinias.hideLoading();
};
// 图片删除
const deletePic = (file) => {
  console.log('图片删除--', file);
  let fileIndex = null;
  uploadList.value.map((item, index) => {
    if (file.file.name == (item.originalName || item.name)) {
      fileIndex = index;
    }
  });
  // id为空时做逻辑删除,不调用删除接口
  let id = uploadList.value[fileIndex].id;
  if (!!!id) {
    uploadList.value.splice(fileIndex, 1);
  } else {
    let ids = [];
    ids.push(id);
    fileDelete(ids).then((res) => {
      uploadList.value.splice(fileIndex, 1);
      proxy.showSuccessToast('删除成功');
    });
  }
  emit('update:saveFileArr', uploadList.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 = [];
  uploadList.value = [];
  props.saveFileArr.map((item) => {
    let params = {
      id: item.id,
      name: item.name,
      originalName: item.originalName,
      file: { name: item.originalName },
      status: 'success',
      url: item.url,
    };
    fileList.value.push(params);
    uploadList.value.push(params);
    console.log(uploadList.value, '  uploadList.value1111');
  });
});
onBeforeUnmount(() => {
  fileList.value = [];
});
</script>
<style lang="less">
.uploaderPage {
  width: 100%;
  .blueFont {
    color: #0c60e1;
  }
}
</style>