利用 Element Plus 组件库优化图片上传流程

敲重点!!!以下不一定适用于每个人,请大家先看清楚前后端的实现逻辑

业务需求

上传图片,回显,删除,放大查看等

实现逻辑

这里由于后端考虑到上传后可能并未使用的情况,把普通的直接上传流程改为了以下流程(最后有代码):

步骤一

先调取接口创建一个临时的文件目录,得到一个临时tempDirId。

步骤二

选择图片调上传图片接口,并将第一步得到的tempDirId作为参数传给服务端。

步骤三

通过第二步拿到fileId,前端自己存储,最后数据保存时 将tempDirId和fileId一并提交给服务端。

如果有和我业务实现一致的朋友们,抄代码啦~

<template>
  <el-upload
    ref="uploadRef"
    v-loading="state.loading"
    action=""
    :accept="state.fileAccept"
    list-type="picture-card"
    :on-preview="handlePreview"
    :on-change="handleUpload"
    :show-file-list="true"
    :auto-upload="true"
    :on-remove="handleRemove"
    :http-request="fileUpload"
    :file-list="fileListData"
    :limit="limit"
    class="single-upload"
  >
    <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
  </el-upload>
  <el-dialog v-model="state.dialogVisible">
    <img class="w100" w-full :src="state.dialogImageUrl" alt="Preview Image" />
  </el-dialog>
</template>
<script setup>
import { reactive, ref } from "vue";
import { Plus } from "@element-plus/icons-vue";
import { fileCreate, fileUploadImgCreate } from "@/api/common";
import { showMessage } from "@/utils/message";

const props = defineProps({
  // 用于回显数据列表
  fileListData: {
    type: Array,
    default: () => [],
  },
  limit: {
    type: Number,
    default: 1,
  },
  fileSize: {
    type: Number,
    default: 20,
  },
  index: {
    type: [Number, String],
    default: 0,
  },
  modelValue: {
    type: String,
    default: "",
  },
  checkType: {
    type: String,
    default: "",
  },
  tip: {
    type: String,
    default: "",
  },
});
const emit = defineEmits(["uploadSuccess", "update:modelValue"]);
const state = reactive({
  loading: false,
  fileAccept: ".jpg,.jpeg,.png,.JPG,.JPEG",
  fileList: [],
  formData: null,
  dialogImageUrl: "",
  dialogVisible: false,
  tempDirId: null, //临时id
});
watch(
  () => props.fileListData,
  (n, o) => {
    state.fileList = n;
  }
);
watch(
  () => state.fileList,
  (n, o) => {
    const uploadCards = document.querySelectorAll(".single-upload .el-upload--picture-card");
    uploadCards[props.index].style.display = n.length > 0 ? "none" : "inline-flex";
  },
  { deep: true }
);
watch(
  () => props.modelValue,
  newVal => {
    if (newVal) {
      state.fileList = newVal.split(",").map(item => {
        return {
          url: item,
        };
      });
      return;
    }
    state.fileList = [];
  },
  { immediate: true }
);
const handlePreview = file => {
  state.dialogVisible = true;
  state.dialogImageUrl = file.url;
};
const handleRemove = (file, fileList) => {
  state.fileList = fileList;
  emit("update:modelValue", "");
};
const fileUpload = () => {};
let uploadRef = ref(null);

const validateFile = (file, fileList) => {
  const isLimit = file.size / 1024 / 1024 < props.fileSize;
  const imageTypeList = ["image/jpeg", "image/jpg", "image/png"];
  const isImage = imageTypeList.includes(file.raw.type);
  if (!isImage) {
    showMessage("上传图片只能是 JPG 或 PNG 或 JPGE 格式!", "error");
    fileList.splice(fileList.length - 1, 1);
    return false;
  }
  if (!isLimit) {
    showMessage("上传图片大小不能超过 " + props.fileSize + "MB!", "error");
    fileList.splice(fileList.length - 1, 1);
    return false;
  }
  return true;
};
const handleUpload = async (file, fileList) => {
  const isValid = validateFile(file, fileList);
  if (isValid) {
    try {
      const { result: tempDirId } = await fileCreate();//步骤一的接口
      state.tempDirId = tempDirId;
      state.loading = true;
      state.formData = createFormData(file.raw, state.tempDirId);
      const { result } = await fileUploadImgCreate(state.formData);//步骤二的接口
      state.fileList = fileList;
      emit("uploadSuccess", { ...result, tempDirId });
      emit("update:modelValue", result.absoluteUrl);
      setTimeout(() => {
        state.loading = false;
      }, 500);
      showMessage("图片上传成功!");
    } catch (error) {
      // console.error(error);
      showMessage("图片上传失败!", "error");
      state.loading = false;
    }
  }
};

const createFormData = (file, tempDirId) => {
  const formData = new FormData();
  formData.append("image", file);
  formData.append("tempDirId", tempDirId);
  return formData;
};
defineExpose({
  state,
});
</script>

由于本次业务使用不算复杂,所以并未把允许的图片格式等作为动态值判断,大家可以根据自己的实际情况做一些优化。
以上可以直接作为组件使用,到这儿,就搞定啦~~

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值