Vue3自定义组件实现图片预览下载

示例

代码

  • ImgPreview.vue
<template>
	<div class="preview" @click="onClick">
		<div class="preview-img">
			<div class="opt-box">
				<CloudDownloadOutlined :style="{fontSize: '44px', color: '#0d71ff'}" title="下载" @click="handleDownload"/>
				<CloseOutlined :style="{fontSize: '44px', color: '#0d71ff'}" title="关闭" @click="onClick"/>
			</div>
			<img :src="src" alt="预览图片" />
		</div>
	</div>
</template>
<script setup>
import { CloseOutlined, CloudDownloadOutlined } from '@ant-design/icons-vue'

const props = defineProps({
	src: {
		type: String,
		default: '',
		required: true
	},
	srcName: {
		type: String,
		default: '',
		required: true
	},
	onDownload: {
		type: Function, default: () => {
		}, required: true
	},
	onClick: {
		type: Function, default: () => {
		}, required: true
	},
	onKeydown: {
		type: Function, default: () => {
		}, required: true
	}
})
const {onDownload, src, srcName} = props
const handleDownload = (e) => {
	e.stopPropagation()
	onDownload({attachmentUrl: src, attachmentName: srcName})
}
</script>
<style lang="scss" scoped>
.preview {
	width: 100%;
	height: 100%;
	background: rgba(0, 0, 0, 0.5);
	position: fixed;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	z-index: 9999;
	overflow: scroll;
	cursor: pointer;
	display: flex;
	align-items: center;
}

.preview-img {
	padding: 20px;
	display: inline-block;
	margin: auto;
	position: relative;

	img {
		max-width: 100%;
		max-height: 100%;
	}

	.opt-box {
		position: absolute;
		top: 34px;
		right: 40px;

		span {
			margin-left: 14px;
		}
	}
}
</style>
  • 使用
		<ImgPreview
			v-if="previewVisible"
			:src="previewUrl"
			:srcName="previewName"
			:onClick="closeImgPreview"
			:onDownload="onDownLoad"
		/>


const previewVisible = ref(false)
const previewUrl = ref('')
const previewName = ref('')
const onPreview = ({ attachmentUrl,attachmentName }) => {
	if(isEmpty(attachmentUrl)) return
	previewVisible.value = true
	previewUrl.value = attachmentUrl
	previewName.value = attachmentName
}

const closeImgPreview = () => {
	previewVisible.value = false;
}

const onDownLoad = ({ attachmentUrl,attachmentName }) => {
	if(isEmpty(attachmentUrl)) {return}
	let param = {
		name: attachmentName.split('.')[0],
		extName: attachmentName.split('.')[1],
		address: attachmentUrl,
	}
	doDownload(param)
	// window.open(attachmentUrl, '_blank')
}

// 文件下载
export function doDownload(item) {
	let aUrl = item.address;
	let extNameIcon = item.extName;
	let extName = item.name;
	if (extName.includes(".")) {
		extName = extName.split(".")[0];
	}
	let xml = new XMLHttpRequest();
	xml.open("GET", aUrl, true);
	xml.responseType = "blob";
	xml.onload = () => {
		let url = window.URL.createObjectURL(xml.response);
		let a = document.createElement("a");
		a.href = url;
		a.download = `${extName}.${extNameIcon}`;
		a.style.display = "none";
		a.click();
	};
	xml.send();
}

posted @ 2024-12-13 18:30  Felix_Openmind  阅读(16)  评论(0编辑  收藏  举报