<template>
|
<div class="attachment-preview-pane">
|
<div v-if="!file" class="attachment-preview-pane__tip">
|
请选择左侧文件预览
|
</div>
|
<template v-else>
|
<div v-if="fileType === 'image'" class="attachment-preview-pane__toolbar">
|
<el-button-group>
|
<el-button
|
size="mini"
|
icon="el-icon-zoom-out"
|
title="缩小"
|
@click="zoom(-0.2)"
|
/>
|
<el-button size="mini" class="attachment-preview-pane__scale">
|
{{ Math.round(scale * 100) }}%
|
</el-button>
|
<el-button
|
size="mini"
|
icon="el-icon-zoom-in"
|
title="放大"
|
@click="zoom(0.2)"
|
/>
|
</el-button-group>
|
<el-button-group>
|
<el-button
|
size="mini"
|
icon="el-icon-refresh-left"
|
title="向左旋转"
|
@click="rotate(-90)"
|
/>
|
<el-button
|
size="mini"
|
icon="el-icon-refresh-right"
|
title="向右旋转"
|
@click="rotate(90)"
|
/>
|
</el-button-group>
|
<el-button size="mini" icon="el-icon-refresh" @click="reset"
|
>重置</el-button
|
>
|
</div>
|
|
<div v-if="fileType === 'image'" class="attachment-preview-pane__wrap">
|
<img
|
:src="file.url"
|
class="attachment-preview-pane__image"
|
:style="{
|
transform: 'scale(' + scale + ') rotate(' + deg + 'deg)'
|
}"
|
alt="图片预览"
|
/>
|
</div>
|
<iframe
|
v-else-if="fileType === 'pdf'"
|
:src="file.url"
|
class="attachment-preview-pane__pdf"
|
title="PDF预览"
|
/>
|
<div v-else class="attachment-preview-pane__tip">
|
该文件类型暂不支持预览,请下载后查看
|
</div>
|
</template>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: "AttachmentPreviewPane",
|
props: {
|
file: {
|
type: Object,
|
default: null
|
}
|
},
|
data() {
|
return {
|
scale: 1,
|
deg: 0
|
};
|
},
|
computed: {
|
fileType() {
|
if (!this.file) {
|
return "other";
|
}
|
if (this.file.type) {
|
return this.file.type;
|
}
|
const ext = String(this.file.name || "")
|
.split(".")
|
.pop()
|
.toLowerCase();
|
if (ext === "pdf") {
|
return "pdf";
|
}
|
if (["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(ext)) {
|
return "image";
|
}
|
return "other";
|
}
|
},
|
watch: {
|
file() {
|
this.reset();
|
}
|
},
|
methods: {
|
zoom(delta) {
|
const next = Math.round((this.scale + delta) * 100) / 100;
|
this.scale = Math.min(5, Math.max(0.2, next));
|
},
|
rotate(deg) {
|
this.deg += deg;
|
},
|
reset() {
|
this.scale = 1;
|
this.deg = 0;
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.attachment-preview-pane {
|
width: 100%;
|
height: 100%;
|
min-height: 420px;
|
display: flex;
|
flex-direction: column;
|
align-items: stretch;
|
justify-content: flex-start;
|
}
|
.attachment-preview-pane__toolbar {
|
flex: 0 0 auto;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
gap: 8px;
|
padding: 4px 0 10px;
|
}
|
.attachment-preview-pane__scale {
|
min-width: 64px;
|
cursor: default;
|
}
|
.attachment-preview-pane__wrap {
|
flex: 1 1 auto;
|
min-height: 0;
|
overflow: auto;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
.attachment-preview-pane__image {
|
max-width: 100%;
|
max-height: 100%;
|
transition: transform 0.2s ease;
|
transform-origin: center center;
|
}
|
.attachment-preview-pane__pdf {
|
flex: 1 1 auto;
|
width: 100%;
|
min-height: 420px;
|
border: 0;
|
}
|
.attachment-preview-pane__tip {
|
color: #909399;
|
font-size: 14px;
|
text-align: center;
|
padding: 20px;
|
}
|
</style>
|