185 lines
3.6 KiB
Vue
185 lines
3.6 KiB
Vue
|
|
<template>
|
||
|
|
<el-dialog
|
||
|
|
:title="title"
|
||
|
|
:visible.sync="dialogVisible"
|
||
|
|
:width="width"
|
||
|
|
:close-on-click-modal="false"
|
||
|
|
destroy-on-close
|
||
|
|
append-to-body
|
||
|
|
@close="handleClose"
|
||
|
|
>
|
||
|
|
<!-- 图片预览 -->
|
||
|
|
<div v-if="fileType === 'image'" class="preview-image">
|
||
|
|
<div class="image-controls">
|
||
|
|
<el-button type="primary" size="small" @click="zoomIn">放大</el-button>
|
||
|
|
<el-button type="primary" size="small" @click="zoomOut">缩小</el-button>
|
||
|
|
<el-button type="primary" size="small" @click="resetZoom">重置</el-button>
|
||
|
|
</div>
|
||
|
|
<div class="image-container" ref="imageContainer">
|
||
|
|
<img
|
||
|
|
:src="fileUrl"
|
||
|
|
:style="{ transform: `scale(${scale})` }"
|
||
|
|
class="preview-image-content"
|
||
|
|
@wheel="handleWheel"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- PDF预览 -->
|
||
|
|
<div v-else-if="fileType === 'pdf'" class="preview-pdf">
|
||
|
|
<iframe
|
||
|
|
:src="fileUrl"
|
||
|
|
class="preview-pdf-content"
|
||
|
|
frameborder="0"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<!-- 不支持的文件类型 -->
|
||
|
|
<div v-else class="preview-not-supported">
|
||
|
|
<el-empty description="暂不支持预览此文件类型"></el-empty>
|
||
|
|
</div>
|
||
|
|
</el-dialog>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
name: "FilePreview",
|
||
|
|
props: {
|
||
|
|
visible: {
|
||
|
|
type: Boolean,
|
||
|
|
default: false
|
||
|
|
},
|
||
|
|
fileUrl: {
|
||
|
|
type: String,
|
||
|
|
required: true
|
||
|
|
},
|
||
|
|
fileName: {
|
||
|
|
type: String,
|
||
|
|
default: "文件预览"
|
||
|
|
},
|
||
|
|
width: {
|
||
|
|
type: String,
|
||
|
|
default: "80%"
|
||
|
|
}
|
||
|
|
},
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
dialogVisible: false,
|
||
|
|
scale: 1
|
||
|
|
};
|
||
|
|
},
|
||
|
|
watch: {
|
||
|
|
visible: {
|
||
|
|
handler(val) {
|
||
|
|
this.dialogVisible = val;
|
||
|
|
},
|
||
|
|
immediate: true
|
||
|
|
},
|
||
|
|
dialogVisible(val) {
|
||
|
|
if (!val) {
|
||
|
|
this.$emit('update:visible', false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
computed: {
|
||
|
|
title() {
|
||
|
|
return this.fileName || "文件预览";
|
||
|
|
},
|
||
|
|
fileType() {
|
||
|
|
const fileName = this.fileName || '';
|
||
|
|
const ext = fileName.split('.').pop()?.toLowerCase();
|
||
|
|
if (['png', 'jpg', 'jpeg', 'bmp', 'webp'].includes(ext)) {
|
||
|
|
return 'image';
|
||
|
|
} else if (ext === 'pdf') {
|
||
|
|
return 'pdf';
|
||
|
|
} else {
|
||
|
|
return 'other';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
handleClose() {
|
||
|
|
this.$emit('update:visible', false);
|
||
|
|
},
|
||
|
|
// 放大图片
|
||
|
|
zoomIn() {
|
||
|
|
if (this.scale < 3) {
|
||
|
|
this.scale += 0.1;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// 缩小图片
|
||
|
|
zoomOut() {
|
||
|
|
if (this.scale > 0.1) {
|
||
|
|
this.scale -= 0.1;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
// 重置缩放
|
||
|
|
resetZoom() {
|
||
|
|
this.scale = 1;
|
||
|
|
},
|
||
|
|
// 鼠标滚轮缩放
|
||
|
|
handleWheel(event) {
|
||
|
|
event.preventDefault();
|
||
|
|
const delta = event.deltaY > 0 ? -0.1 : 0.1;
|
||
|
|
if ((this.scale > 0.1 || delta > 0) && (this.scale < 3 || delta < 0)) {
|
||
|
|
this.scale += delta;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.preview-image {
|
||
|
|
width: 100%;
|
||
|
|
height: 70vh;
|
||
|
|
background-color: #f5f7fa;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
}
|
||
|
|
|
||
|
|
.image-controls {
|
||
|
|
padding: 10px;
|
||
|
|
display: flex;
|
||
|
|
gap: 10px;
|
||
|
|
border-bottom: 1px solid #e4e7ed;
|
||
|
|
background-color: #ffffff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.image-container {
|
||
|
|
flex: 1;
|
||
|
|
overflow: auto;
|
||
|
|
display: flex;
|
||
|
|
justify-content: center;
|
||
|
|
align-items: flex-start;
|
||
|
|
padding: 20px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.preview-image-content {
|
||
|
|
transition: transform 0.3s ease;
|
||
|
|
cursor: zoom-in;
|
||
|
|
max-width: 100%;
|
||
|
|
max-height: 100%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.preview-image-content:hover {
|
||
|
|
cursor: zoom-in;
|
||
|
|
}
|
||
|
|
|
||
|
|
.preview-pdf {
|
||
|
|
width: 100%;
|
||
|
|
height: 70vh;
|
||
|
|
}
|
||
|
|
|
||
|
|
.preview-pdf-content {
|
||
|
|
width: 100%;
|
||
|
|
height: 100%;
|
||
|
|
}
|
||
|
|
|
||
|
|
.preview-not-supported {
|
||
|
|
display: flex;
|
||
|
|
justify-content: center;
|
||
|
|
align-items: center;
|
||
|
|
height: 400px;
|
||
|
|
}
|
||
|
|
</style>
|