<template> <div> <p v-if="getUrlOrName && showFile && getUrlOrName('url', tempData)"> <a download="" target="_blank" :href="getUrlOrName('url', tempData)">{{ getUrlOrName("name", tempData) }}</a> <span class="close"> <ns-icon name="close" @click="remove" /> </span> </p> <div class="clearfix container"> <!--:multiple="showCount != 1"--> <!--:showUploadList="false"--> <a-upload :before-upload="beforeUpload" :customRequest="selfUpload" :showUploadList="false" > <a-button> <upload-outlined /> 上传文件 </a-button> <div class="upload-tips"> <!--上传提示信息--> <p v-if="acceptType && acceptType.length > 0"> 支持扩展名:{{ acceptType.join(" ") }} </p> <p v-if="fixedFileName && fixedFileName.length > 0"> 仅支持文件:{{ fixedFileName.join(" ") }} </p> </div> </a-upload> </div> <!-- 提示 --> <div class="err-msg"> <p :style="{ color: 'red' }" v-if="error">{{ error }}</p> </div> <p v-if="!error" :style="{ color: uploadResult === '上传成功' ? '#51b97b' : '#323232' }" > {{ fileName }} {{ uploadResult }} </p> <!-- 提示 --> </div> </template> <script lang="ts"> import { UploadOutlined, LoadingOutlined, EyeOutlined, DeleteOutlined, } from "@ant-design/icons-vue"; import { defineComponent, ref, computed, reactive } from "vue"; // import {http} from '/nerv-lib/util/http'; import { NsMessage } from "../../message"; import { NSAxios } from "/nerv-lib/util/http/axios"; import { get, isArray } from "lodash-es"; interface FileItem { uid: string; type: string; size: number; name?: string; status?: string; response?: string; percent?: number; url?: string; preview?: string; originFileObj?: any; } interface FileInfo { file: FileItem; fileList: FileItem[]; } // 转base64 function getBase64(file: File) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve(reader.result); reader.onerror = (error) => reject(error); }); } export interface sizeItem { fileType: Array<string>; maxSize: number; errorTip?: string; } export default defineComponent({ name: "NsUploadFile", components: { UploadOutlined, LoadingOutlined, DeleteOutlined, EyeOutlined, }, props: { // 上传的地址 url: { type: String, require: true, }, // 上传的图片大小 maxSize: { type: Number || Array as PropType<Array<sizeItem>>, // [ { 'maxSize':512488000,'fileType': ['jpg', 'png'] } ] default: 524288000, }, // 上传的图片类型 fileType: { type: Array, }, // 固定限制的文件名称 fixedFileName: { type: Array, }, //随file添加固定传参 params: { type: [Object], }, // 展示图片数量 showCount: { type: Number, default: 1, }, // 上传文件类型,0-证书,1-图片,2-身份证件 uploadType: { type: Number, default: 1, }, //是否显示下载附件 showFile: { type: Boolean, default: false, }, //传入数据数据源 dataSouce: { type: Object, }, //处理传入数据用于触发change事件 setDataSouce: { type: Function, }, //获取下载链接 getUrlOrName: { type: Function, }, }, emits: ["change"], setup(props, { emit }) { function createHttp() { /** todo 临时去除超时时间 */ return new NSAxios({ headers: { "Content-Type": "application/json;charset=UTF-8" }, withCredentials: true, }); } const uploadHttp = createHttp(); const previewVisible = ref<boolean>(false); const error = ref<string>(""); const uploadResult = ref<string>(""); const previewImage = ref<string | undefined>(""); const fileName = ref<string | undefined>(""); const fileList = ref<FileItem[]>([]); const currentImg = ref<string[]>([]); const maskShow = ref<boolean[]>([]); let data = reactive({}); let tempData = ref({}); if (props.dataSouce && props.setDataSouce) { tempData.value = props.setDataSouce(JSON.parse(JSON.stringify(props.dataSouce))); emit("change", { data: tempData.value }); } const acceptType = computed(() => props.fileType.map((item: String) => { return item; }) ); const beforeUpload = (file: FileItem) => { if (!file) { return; } fileName.value = file.name; /** 1.判断类型和大小 */ error.value = ""; uploadResult.value = ""; // 文件类型 const type = file.name.substring(file.name.lastIndexOf(".") + 1).toLowerCase(); if (acceptType.value && acceptType.value.length > 0) { // 限定文件类型 if (acceptType.value.includes(type)) { error.value = ""; } else { error.value = `请选择${props.fileType.join(",")}文件`; return false; } } else if (props.fixedFileName) { // 固定文件名称 const fixedFileName = props.fixedFileName; if (fixedFileName && fixedFileName.includes(file.name)) { error.value = ""; } else { console.log(props.fixedFileName.join(",")); error.value = `请选择${props.fixedFileName.join(",")}的文件`; return false; } } // 文件大小 let valid = true; error.value = ""; if (isArray(props.maxSize)) { props.maxSize.some((el) => { if (el.fileType.includes(type)) { valid = file.size <= el.maxSize; error.value = valid ? "" : el["errorTip"] || ` 请选择${el.maxSize / 1024 / 1024}M内的文件`; return true; } }); } else if (file.size > props.maxSize) { error.value = ` 请选择${props.maxSize / 1024 / 1024}M内的文件`; valid = false; } if (!valid) return valid; return error.value == ""; }; const selfUpload = async ({ file }) => { currentImg.value.unshift(await getBase64(file)); const params = { // uploadType: props.uploadType, }; const formData = new FormData(); formData.append("file", file); const config = { headers: { "Content-Type": "multipart/form-data", }, params: params, }; Object.keys(props.params).map((item) => { formData.append(item, props.params[item]); }); uploadResult.value = "上传中..."; uploadHttp .post(props.url, formData, config) .then((res) => { error.value = ""; uploadResult.value = "上传成功"; data = res; tempData.value = res.data; console.log(data); emit("change", data); }) .catch(() => { uploadResult.value = ""; error.value = `${file.name} 上传失败,请重试`; NsMessage.error("上传失败,请重试"); }); }; const handlePreview = async (index: number) => { previewImage.value = (await getBase64( fileList.value[index].originFileObj )) as string; previewVisible.value = true; }; const deleteImg = (index: number) => { currentImg.value.splice(index, 1); fileList.value.splice(index, 1); }; const handleCancel = () => { previewVisible.value = false; }; const mouseEnter = (index: number) => { maskShow.value[index] = true; }; const mouseLeave = (index: number) => { maskShow.value[index] = false; }; const remove = () => { Object.keys(tempData.value).map((key) => { tempData.value[key] = ""; }); emit("change", { data: tempData.value }); }; const doWnload = (url) => { let a = document.createElement("a"); document.body.appendChild(a); a.href = encodeURI(url); //设置下载的文件名 // a.download = fileName.value; //触发a标签的点击事件,进行下载 a.click(); }; return { previewVisible, previewImage, fileList, error, uploadResult, fileName, currentImg, maskShow, data, tempData, acceptType, selfUpload, handleCancel, handlePreview, beforeUpload, mouseEnter, mouseLeave, deleteImg, doWnload, remove, }; }, }); </script> <style lang="less" scoped> .close { cursor: pointer; } </style>