element UI 上传图片组件

211 阅读1分钟

<template>
	<div class="single-image-uploader-item">
		<el-upload
			class="single-image-uploader"
			accept="image/jpeg, image/png"
			action="string"
			:show-file-list="false"
			:http-request="uploadImage"
			:before-upload="beforeAvatarUpload"
		>
			<template v-if="image">
				<img :src="image" class="single-image" />
				<a href="javascript:;" class="btn-delete" @click="clearFiles">
					<i class="el-icon-delete"></i>
				</a>
			</template>
			<i
				v-else
				class="el-icon-plus single-image-uploader-icon"
				v-loading="uploadLoading"
			></i>
			<div slot="tip" class="el-upload__tip" style="line-height:1em;margin-top:0;">
				只能上传JPG/PNG格式的图片,且不超过{{ size }}MB{{ format }}
			</div>
		</el-upload>
	</div>
</template>

<script>
import axios from 'axios';
export default {
	data() {
		return {
			uploadLoading: false,
			image: this.value
		};
	},
	props: {
		value: {
			type: String,
			default: ''
		},
		format: {
			type: String,
			default: ''
		},
		size: {
			type: Number,
			default: 2
		},
		field: {
			type: String,
			default: 'file'
		},
		action: {
			type: String,
			default: '/api/file/upload-one'
		},
		fileType: {
			type: String,
			default: 'COLLEGE'
		},
		otherId: {
			type: String,
			default: ''
		}
	},
	methods: {
		beforeAvatarUpload(file) {
			const typeCheck = file.type === 'image/jpeg' || file.type === 'image/png';
			const sizeCheck = file.size / 1024 / 1024 <= this.size;

			if (!typeCheck) {
				this.$message.error('上传图片只能是 JPG/PNG 格式!');
			}
			if (!sizeCheck) {
				this.$message.error(`上传图片大小不能超过${this.size}MB!`);
			}
			this.uploadLoading = true;
			return typeCheck && sizeCheck;
		},
		uploadImage(params) {
			let formdata = new FormData();
			formdata.set(this.field, params.file);
			formdata.set('fileType', this.fileType);
			if (this.otherId) {
				formdata.set('otherId', this.otherId);
			}
			axios
				.post(this.action, formdata)
				.then(res => {
					if (!res.data.code) {
						this.image = res.data.data.fileUrls[0];
					} else {
						this.image = null;
					}
					this.uploadLoading = false;
				})
				.catch(res => {
					this.uploadLoading = false;
					this.$message.error(res.data.msg);
				});
		},
		clearFiles(e) {
			e.stopPropagation();
			this.image = null;
		}
	},
	watch: {
		value(newVal) {
			this.image = newVal;
		},
		image(newVal) {
			this.$emit('input', newVal);
		}
	}
};
</script>

<style lang="scss">
.single-image-uploader-item {
	.single-image-uploader .el-upload {
		border: 1px dashed #d9d9d9;
		border-radius: 6px;
		cursor: pointer;
		position: relative;
		overflow: hidden;
	}
	.single-image-uploader .el-upload:hover {
		border-color: #409eff;
	}
	.single-image-uploader-icon {
		font-size: 28px;
		color: #8c939d;
		width: 178px;
		height: 178px;
		line-height: 178px;
		text-align: center;
	}
	.single-image {
		width: 178px;
		height: 178px;
		object-fit: cover;
		display: block;
	}
	.btn-delete {
		position: absolute;
		top: 0;
		right: 0;
		height: 40px;
		width: 40px;
		line-height: 40px;
		font-size: 20px;
		color: #fff;
		text-shadow: 0 0 10px #000;
	}
	.single-image-uploader .el-loading-spinner {
		top: 10px;
		margin-top: 0;
	}
	.el-icon-plus:before {
		color: #1875f0;
	}
}
</style>