首页 > 其他分享 >AntDesign上传组件upload二次封装+全局上传hook使用

AntDesign上传组件upload二次封装+全局上传hook使用

时间:2024-07-05 10:31:15浏览次数:14  
标签:const type upload file props AntDesign 上传

文章目录


前言

在项目中,ant-design是我们常用的UI库之一,今天就来二次封装常用的组件a-upload批量上传组件,让它用起来更方便。

a-upload组件二次封装

1. 功能分析

(1)自定义展示区,可按UI规范自定义展示
(2)上传失败,过滤成功的文件,重新赋值展示,不展示失败的文件
(3)上传之前的校验通过配置,在组件内统一管理
(4)通过传入defaultValue prop,进行初始化数据显示
(5)通过传入beforeChange prop,可以根据外部promise上传文件返回的结果,做一些处理

2. 代码+详细注释

// @/components/uploads/index.tsx
<template>
  <a-upload v-model:file-list="state.fileList" :accept="accept" list-type="picture" class="avatar-uploader" multiple :max-count="3" :before-upload="beforeUpload" :customRequest="handlerUploadFile" @change="handlerChange" @remove="handlerRemove">
    <a-button>
      <UploadOutlined />
      选择附件
    </a-button>
    <template #itemRender="{ file, actions }">
      <div class="cd-upload-list">
        <LoadingOutlined class="cd-upload-list-loading" v-if="file.status === 'uploading'" />
        <template v-else>
          <a class="cd-upload-list-item" :href="file?.response || file?.url" target="_blank">
            <img v-if="isImage(file?.response)" class="cd-upload-list-img" :src="file?.response || file?.url" alt="" />
            <FileOutlined v-else class="cd-upload-list-icon" />
            <span class="cd-upload-list-name">{{ file.name }}</span>
          </a>
        </template>
        <a class="cd-upload-list-remove" href="javascript:;" @click="actions.remove"> <DeleteOutlined /></a>
      </div>
    </template>
  </a-upload>
</template>
<script lang="ts" setup>
import { reactive, ref, Ref, watch, PropType } from "vue";
import { message } from "ant-design-vue";
import { UploadOutlined, DeleteOutlined, FileOutlined, LoadingOutlined } from "@ant-design/icons-vue";
import type { UploadProps, UploadChangeParam } from "ant-design-vue";
import type { UploadRequestOption } from "ant-design-vue/es/vc-upload/interface";
/**
 * 类型声明
 */
type ProgressProps = UploadProps["progress"];
type uploadFunProps<T> = Omit<UploadRequestOption<T>, "onSuccess"> &
  Omit<UploadRequestOption<T>, "onError"> & {
    onSuccess: any;
    one rror: any;
  };
/**
 * @param data 文件地址
 * 是否是图片
 */
const isImage = (data: string | undefined) => {
  if (!data) return false;
  const fileExtensions = [".png", ".jpg", ".jpeg"];
  return fileExtensions.some((extension) => data.endsWith(extension));
};
/**
 * props
 */
const props = defineProps({
  val: {
    type: Array,
    default: () => [],
  },
  accept: {
    type: String,
    default: ".doc,.docx,.xlsx,.xls,.pdf,.jpg,.png,.jpeg",
  },
  max: {
    type: Number,
    default: 1,
  },
  size: {
    type: Number,
    default: 2,
  },
  defaultValue: {
    type: Array,
    default: () => [],
  },
  format: Function,
  text: {
    type: String,
    default: "",
  },
  params: {
    type: Object,
    default: {},
  },
  beforeChange: {
    type: Function as PropType<(options: any) => Promise<any>>,
  },
});
/**
 * emit
 */
const emit = defineEmits(["update:val", "upload", "remove"]);
/**
 * state
 */
type PreviewState = {
  fileList: UploadProps["fileList"];
  loading: boolean;
  imageUrl: string;
  dataList: any[];
};
const state = reactive<PreviewState>({
  fileList: [],
  loading: false,
  imageUrl: "",
  // 数据文件
  dataList: [],
});
/**
 * 文件状态改变时的回调
 */
const handlerChange = ({ file, fileList }: UploadChangeParam) => {
  const status = file.status;
  if (status === "uploading") {
  }
  if (status === "done") {
  }
  // 上传失败,过滤成功的文件,重新赋值展示
  if (!status || status === "error") {
    const files = fileList.filter((item: any) => item.status === "done");
    state.fileList = files;
  }
};
/**
 * 上传之前检查文件
 * @param file 文件对象
 * @returns boolean
 */
const beforeUpload = (file: File) => {
  const type = file.type.split("/")[1];
  if (props.accept.indexOf(type) === -1) {
    message.error(`请上传${props.accept}格式文件`);
    return false;
  }
  const maxSize = file.size / 1024 / 1024 < props.size;
  if (!maxSize) {
    message.error(`图片大小须小于${props.size}MB`);
    return false;
  }
  return type && maxSize;
};
/**
 * 上传进度
 * @param progressEvent 进度对象
 */
const progress: ProgressProps = {};
/**
 * 上传
 */
const handlerUploadFile = (options: uploadFunProps<unknown>) => {
  props?.beforeChange &&
    props
      .beforeChange({ file: options.file, params: props.params })
      .then((res: any) => {
        message.success(`上传成功`);
        console.log("res777", res);
        if (res?.url) {
          options.onSuccess(res.url, options.file);
        }
      })
      .catch(() => {
        message.error(`上传失败`);
        options.onError();
      });
};
/**
 * 删除文件的回调
 * @param file 文件对象
 */
const handlerRemove = (file: File) => {
  emit("remove", file);
};

/**
 * 初始值
 */
const initValue = (list: string[]) => {
  const file = [] as any[];
  list.forEach((item: string) => {
    file.push({
      status: "done",
      url: item,
    });
  });
  // 更新
  state.fileList = file;
};
watch(
  () => props.defaultValue,
  (val: any) => {
    if (!val || (val && !val.length)) {
      return false;
    }
    initValue(val);
  },
  { immediate: true }
);
</script>
<style lang="scss" scoped>
.cd-upload-list {
  display: flex;
  justify-content: space-between;
  position: relative;
  height: 66px;
  padding: 8px;
  border: 1px solid #d9d9d9;
  border-radius: 8px;
  margin-top: 8px;
  .cd-upload-list-loading {
    font-size: 20px;
  }
  .cd-upload-list-item {
    display: flex;
    align-items: center;
    .cd-upload-list-img {
      width: 50px;
      height: 50px;
      margin-right: 10px;
    }
    .cd-upload-list-icon {
      font-size: 20px;
      margin-right: 10px;
    }
    .cd-upload-list-name {
    }
  }
  .cd-upload-list-remove {
    display: flex;
    align-items: center;
    font-size: 20px;
  }
}
</style>

3. 使用到的全局上传hook代码

/**
 * api
 */
import { uploadImage } from "@/api/index";
/**
 * 上传资源全局hook
 * @returns 
 */
export function useUploadImage() {
  const useUploadImageBeforeChange = ({ file, params }: { file: File; params: Record<string, any> }) => {
    return new Promise((resolve, reject) => {
      // 实例化表单对象
      const form = new FormData();
      // 表单添加 files 字段
      for (let key in params) {
        form.append(key, params[key]);
      }
      form.append("multipartFiles", file);
      uploadImage(form)
        .then((res: any) => {
          const result = res && res.length;
          resolve(result ? res[0] : null);
        })
        .catch(() => {
          reject();
        });
    });
  };
  return {
    useUploadImageBeforeChange,
  };
}

4. 使用方式

// 引入组件,以及全局上传hook
import Upload from "@/components/upload/index.vue";
import { useUploadImage } from "@/hook/index";
const { useUploadImageBeforeChange } = useUploadImage();
// 使用
const defaultValue: string[] = ref(["http://xxx.pdf"]);
 <Upload :defaultValue="defaultValue" :size="5" :params="{ fileType: 'xxxxxx' }" :before-change="useUploadImageBeforeChange" />

5. 效果展示

(1)上传
在这里插入图片描述
(2)预览、删除
在这里插入图片描述


总结

接下来会继续分享ant-design常用组件二次封装使用,请持续关注。

标签:const,type,upload,file,props,AntDesign,上传
From: https://blog.csdn.net/weixin_43883615/article/details/140199118

相关文章

  • 文件上传
    基本概念文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果。客服......
  • net6 WebAPI大文件上传
    最近由于客户需要上传大文件,所以研究了一下文件上传的问题net6上传文件分为两种情况:buffering和streaming(缓存和流)Buffering:我们平时采用的通过IFormFile上传文件的方式就是Buffering,此方式会将文件全部缓存起来。这种方式简单,但对内存和硬盘空间造成负担。关于缓存,这里有个误......
  • 使用 Putty 的 PSFTP 上传文件到服务器(手工、bat批处理)
    一、手工方式上传1.建立连接:psftp.exe-iaws.ppk(自己的秘钥)2.使用用户名登录地址:[email protected]显示Remoteworkingdirectoryis/home/xxx此时已经建立了连接。3.上传文件putfilename默认传到/home/xxx目录下4.下载文件get/home/xxx/filename......
  • 【攻防世界】wzsc_文件上传
    wzsc_文件上传题目来源攻防世界NO.GFSJ0997题目描述经典上传页面用御剑扫出upload文件夹/upload路径下是上传的文件题解新建几个空文件,发现后缀为txt的文件可以上传,且在/upload下能看到php文件上传后在/upload下无法看到,怀疑是上传后立马被删除。先进行测试是否......
  • selenium16_文件上传
    inupt标签可以直接通过send_keys上传文件非input标签,AutoIt上传1.安装AutoIt2.AutoIt菜单介绍SciTEScriptEditor编辑器,用于编写AutoIt脚本AutoItWindowsInfo元素定位器,用于识别Windows控件信息RunScript执行AutoIt脚本CompileScriptto.exe将AutoIt生成可执行文件......
  • 【Python&网络通信】基于Bypy调用百度网盘api实现自动上传和下载网盘文件
    ​    网盘对于大家的生活工作可以说是息息相关,但是如果每天都重复去上传下载文件就会很浪费时间,所以有没有什么办法可以解放双手?那就是网盘接口,本文通过Bypy库实现百度网盘的自动上传和下载文件。原创作者:RS迷途小书童博客地址:https://blog.csdn.net/m0_56729804?t......
  • python编写使用xmlrpc上传wordpress网站文章的程序
    1、安装库        pipinstallpython-wordpress-xmlrpc,tkinter,xmlrpc,json2、发布文章url="http://域名/xmlrpc.php"username=用户名password=密码title=标题content=内容tags=标签categories=分类client=C......
  • 图片和表单数据同时上传
     //请求 exportfunctionaddcountorderitem(data){returnrequest({url:'/countoder/oderitem/add',method:'post',data:data,headers:{'Content-Type':'multipart/form-data'}/......
  • Django之文件上传
    前端 <!DOCTYPEhtml><html><body><h2>UploadFile</h2><formaction="http://127.0.0.1:5000/upload"method="post"enctype="multipart/form-data">Selectfiletoupload:<inputtype=&q......
  • C#通过HttpWebRequest上传文件(自测通过)
    C#通过HttpWebRequest进行文件上传,自己亲测没问题,如果需要请自取usingSystem;usingSystem.Collections.Generic;usingSystem.IO;usingSystem.Linq;usingSystem.Net;usingSystem.Reflection;usingSystem.Text;namespaceConsoleApp1{internalclassProgram......