避免反复造轮子系列之头像上传组件(VUE3+JS+ant)

46 阅读1分钟
	<div class="main">
		<a-upload
			v-model:file-list="fileList"
			name="file"
			list-type="picture-card"
			class="avatar-uploader"
			:action="action"
			:headers="headers"
			@change="handleChange"
			@preview="handlePreview"
			@remove="handelRemove"
			:maxCount="props.maxCount"
			:disabled="props.disabled"
		>
			<img v-if="imageUrl" :src="imageUrl" alt="avatar" style="width: 102px; height: 102px" />
			<div v-else>
				<loading-outlined v-if="loading"></loading-outlined>
				<plus-outlined v-else></plus-outlined>
				<div class="ant-upload-text">上传头像</div>
			</div>
		</a-upload>
		<a-modal :visible="previewVisible" :title="previewTitle" :footer="null" @cancel="handleCancel">
			<img alt="example" style="width: 100%" :src="previewImage" />
		</a-modal>
	</div>
</template>

<script setup name="loginPage">
	function getBase64(file) {
		return new Promise((resolve, reject) => {
			const reader = new FileReader()
			reader.readAsDataURL(file)
			reader.onload = () => resolve(reader.result)
			reader.onerror = (error) => reject(error)
		})
	}
	import sysConfig from '@/config/index'
	import tool from '@/utils/tool'
	import { ref, reactive } from 'vue'
	import { message } from 'ant-design-vue'
	const props = defineProps({
		disabled: {
			type: Boolean,
			default: false
		},
		maxCount: {
			type: Number,
			default: 1
		},
		showUploadList: {
			type: Boolean,
			default: true
		},
		text: {
			type: String,
			default: '点击上传'
		}
	})

	const previewVisible = ref(false)
	const previewImage = ref('')
	const previewTitle = ref('')
	const action = `/dev/file/uploadMinioReturnUrl`
	const fileList = ref([])
	const loading = ref(false)
	const imageUrl = ref('')
	const headers = {
		authorization: 'authorization-text',
		token: tool.data.get('TOKEN')
	}

	const emit = defineEmits(['uploadSuccess'])

	const handleCancel = () => {
		previewVisible.value = false
		previewTitle.value = ''
	}
	const handlePreview = async (file) => {
		if (!file.url && !file.preview) {
			file.preview = await getBase64(file.originFileObj)
		}
		previewImage.value = file.url || file.preview
		previewVisible.value = true
		previewTitle.value = file.name || file.url.substring(file.url.lastIndexOf('/') + 1)
	}
	const handelRemove = (file) => {
		let urlArr = []
		fileList.value = []
		imageUrl.value = null
		loading.value = false
		emit('uploadSuccess', urlArr)
	}
	const handleChange = (file) => {
		if (file.file.status === 'uploading') {
			loading.value = true
			return
		}
		if (file.file.status == 'done') {
			message.success('上传成功')
			let urlArr = []
			fileList.value = file.fileList
			file.fileList.forEach((item) => {
				urlArr.push(item.response.data)
			})
			imageUrl.value = urlArr
			emit('uploadSuccess', urlArr)
		} else if (file.file.status == 'error') {
			message.error('上传失败,请重试')
		}
	}
	defineExpose({
		...toRefs({ fileList, imageUrl })
	})
</script>

<style scoped lang="less">
	.avatar-uploader > .ant-upload {
		width: 102px;
		height: 102px;
	}
	/deep/ .ant-upload-list {
		display: flex;
	}
</style>