<!-- @format --> <template> <div> <p v-if="value && showFile"> <a download="" target="_blank" :href="value">{{ downloadName }}</a> <!-- <span class="close"> <ns-icon name="close" @click="remove" /> </span> --> </p> <div class="clearfix container"> <!--:multiple="showCount != 1"--> <!--:showUploadList="false"--> <a-upload :accept="acceptFileType.join()" :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, PropType } 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: 'NsUploadFileV2', 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, default: () => { return ['.jpg', '.png', '.jpeg']; }, }, //弹窗限制的类型 acceptFileType: { type: Array, default: () => { return ['jpg', 'png', 'jpeg']; }, }, // 固定限制的文件名称 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, }, //设置取值字段 valueField: { type: String, default: 'data.httpUrl', }, value: { type: String || Object, }, downloadName: { type: String || Object, default: '下载文件', }, }, emits: ['change'], setup(props, { attrs, 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({}); 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; if (attrs['fieldMap']) { emit('change', data); } else { emit('change', get(data, props.valueField)); } }) .catch((err) => { console.log('err', err); 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>