You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
8.3 KiB

7 months ago
<template>
<div>
<div>
<a-upload
:before-upload="beforeUpload"
@change="handleChange"
:multiple="count != 1"
:customRequest="selfUpload"
:showUploadList="false"
>
<!-- {{ $attrs.value }} -->
<span style="color: #17be6b">{{ $attrs.value ? '证书文件' : fileName }}&nbsp;&nbsp;</span>
<span>上传pdf文件</span>
</a-upload>
<!-- 上传图片框/内置input /-->
</div>
<!-- 错误消息提示 -->
<div class="err-msg" v-if="!isJpgOrPngOrJpeg">
<p>{{ fileName }} 文件上传失败</p>
<p :style="{ color: 'red' }"> 请选择{{ fileType.join(',') }}123 </p>
</div>
<div class="err-msg" v-if="isJpgOrPngOrJpeg ? !isLt5M : ''">
<p>{{ fileName }} 文件上传失败</p>
<p :style="{ color: 'red' }"> 请选择{{ maxSize / 1024 / 1024 }} </p>
</div>
<!-- 错误消息提示 /-->
</div>
</template>
<script lang="ts">
import { defineComponent, ref, computed } from 'vue';
import { http } from '/nerv-lib/util/http';
import { NsMessage } from '../../message';
import { context } from 'ant-design-vue/es/vc-image/src/PreviewGroup';
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 default defineComponent({
name: 'NvUpload',
components: {},
props: {
// 上传的地址
url: {
type: String,
require: true,
},
// 上传的图片大小
// maxSize: {
// type: Number,
// / default: 5242880,
// },
// 上传的图片类型
fileType: {
type: Array,
default: () => {
return ['jpg', 'png', 'jpeg'];
},
},
// 展示图片数量
count: {
type: Number,
default: 1,
},
// 上传文件类型,0-证书,1-图片,2-身份证件
uploadType: {
type: Number,
default: 1,
},
},
emits: ['change'],
setup(props, { emit, attrs }) {
console.log(props, 'propslk');
const host = window.location.host;
const previewVisible = ref<boolean>(false);
const isLt5M = ref<boolean>(true);
const isJpgOrPngOrJpeg = ref<boolean>(true);
const previewImage = ref<string | undefined>('');
const fileName = ref<string | undefined>('');
const fileList = ref<FileItem[]>([]);
const currentImg = ref<string[]>([]);
const maskShow = ref<boolean[]>([]);
const fileUuid = ref<string>('');
// console.log(attrs.value, 'uuuuiiiii');
// fileName = `http://` + host + `/api/pension/pension/objs/CertificateFile/` + attrs.value;
const acceptType = computed(() =>
props.fileType.map((item: String) => {
return 'application/' + item;
})
);
const beforeUpload = (file: FileItem) => {
// 上传出错后,下次上传图片前,重置为true,让图片可以上传
isLt5M.value = true;
isJpgOrPngOrJpeg.value = true;
// 限制图片格式,服务器不支持gif图片
if (file.type === 'image/gif') {
NsMessage.warn('不支持gif图片');
return false;
}
console.log(file.type, acceptType.value, 'zhouzhuupload');
isJpgOrPngOrJpeg.value = acceptType.value.includes(file.type);
// 如果大于指定的大小,显示错误信息
// if (file.size > props.maxSize) {
// isLt5M.value = false;
// }
fileName.value = file.name;
return isLt5M.value && isJpgOrPngOrJpeg.value;
};
const handleChange = ({ fileList: newFileList }: FileInfo) => {
console.log(fileList, 'FileInfo');
// 单图上传
// if (props.count === 1) {
// // 删除图片时,newFileList.length = 0
// // 图片大小不符合规范时,!isLt5M.value为true
// if (!isLt5M.value || !isJpgOrPngOrJpeg.value || newFileList.length - 1 < 0) {
// // 让图片不显示,也不上传
// fileList.value = [];
// } else {
// // 添加\更换图片
// // newFileList[newFileList.length - 1]的目的是为了只显示最新一张图片
// fileList.value = [newFileList[newFileList.length - 1]];
// }
// } else {
// // 多图上传
// if (!isLt5M.value || !isJpgOrPngOrJpeg.value) {
// fileList.value = newFileList.slice(0, newFileList.length - 1);
// } else {
// fileList.value = newFileList;
// }
// }
};
const selfUpload = async ({ file }) => {
console.log(file, 'file');
const params = {
uploadType: props.uploadType,
};
const formData = new FormData();
formData.append('file', file);
formData.append('uploadType', props.uploadType);
const config = {
headers: {
'Content-Type': 'multipart/form-data',
},
params: params,
};
console.log('uploading....', props.url, formData, config);
http
.post(props.url, formData, config)
.then((res) => {
fileUuid.value = res.data.fileUuid;
emit('change', fileUuid.value);
})
.catch((e) => {
console.log(e, 'e');
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;
};
return {
previewVisible,
previewImage,
fileList,
isLt5M,
isJpgOrPngOrJpeg,
fileName,
currentImg,
maskShow,
fileUuid,
selfUpload,
handleCancel,
handlePreview,
handleChange,
beforeUpload,
mouseEnter,
mouseLeave,
deleteImg,
};
},
});
</script>
<style>
.ant-upload-picture-card-wrapper .ant-upload.ant-upload-select-picture-card {
margin: 0;
width: 80px;
height: 80px;
border: 1px solid #d9d9d9;
}
.ant-upload-picture-card-wrapper .ant-upload.ant-upload-select-picture-card:hover {
border-color: #d9d9d9;
}
.ant-upload-select-picture-card i {
font-size: 32px;
color: #999;
}
.ant-upload-select-picture-card .ant-upload-text {
color: #666;
font-size: 12px;
}
.ant-upload-picture-card-wrapper .ant-upload-list-picture-card-container {
width: 88px;
height: 80px;
}
.ant-upload-picture-card-wrapper .ant-upload-list-picture-card .ant-upload-list-item {
margin: 0;
padding: 0;
width: 80px;
height: 80px;
}
.title,
.err-msg {
text-align: left;
}
.err-msg p {
margin: 0;
}
.container {
display: flex;
}
.imgList {
display: flex;
}
.imgContainer {
margin-right: 16px;
border: 1px solid #d9d9d9;
position: relative;
}
.imgCover {
width: 80px;
height: 80px;
object-fit: contain;
}
.imgContainer .mask {
position: absolute;
top: 0;
left: 0;
width: 80px;
height: 80px;
background: rgba(0, 0, 0, 0.5);
text-align: center;
line-height: 80px;
}
.mask .anticon-eye {
color: white;
margin-right: 18px;
}
.mask .anticon-eye:hover {
color: #00acff;
margin-right: 18px;
}
.mask .anticon-delete {
color: white;
}
.mask .anticon-delete:hover {
color: #00acff;
}
</style>