Files
SaaS-lib/lib/component/form/upload-file/upload-fileV2.vue
xuziqiang d0155dbe3c push
2024-05-15 17:29:42 +08:00

350 lines
9.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- @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>