<template>
|
<div class="pdf-preview-container" v-loading="loading">
|
<!-- 控制工具栏 -->
|
<div class="pdf-controls">
|
<el-button-group>
|
<el-button
|
size="mini"
|
@click="prevPage"
|
:disabled="currentPage <= 1"
|
icon="el-icon-arrow-left"
|
>
|
上一页
|
</el-button>
|
<el-button size="mini" disabled>
|
第 {{ currentPage }} 页 / 共 {{ totalPages }} 页
|
</el-button>
|
<el-button
|
size="mini"
|
@click="nextPage"
|
:disabled="currentPage >= totalPages"
|
icon="el-icon-arrow-right"
|
>
|
下一页
|
</el-button>
|
</el-button-group>
|
|
<el-button-group class="zoom-controls">
|
<el-button size="mini" @click="zoomOut" :disabled="scale <= 50">
|
<i class="el-icon-zoom-out"></i> 缩小
|
</el-button>
|
<el-button size="mini" disabled>{{ scale }}%</el-button>
|
<el-button size="mini" @click="zoomIn" :disabled="scale >= 200">
|
<i class="el-icon-zoom-in"></i> 放大
|
</el-button>
|
<el-button size="mini" @click="resetZoom">
|
<i class="el-icon-refresh-left"></i> 重置
|
</el-button>
|
</el-button-group>
|
|
<el-button size="mini" type="success" @click="handleDownload" icon="el-icon-download">
|
下载
|
</el-button>
|
</div>
|
|
<!-- PDF渲染区域 -->
|
<div class="pdf-render-area">
|
<pdf
|
ref="pdf"
|
:src="pdfUrl"
|
:page="currentPage"
|
@num-pages="totalPages = $event"
|
@page-loaded="currentPage = $event"
|
@loaded="loadPdfHandler"
|
@error="pdfErrorHandler"
|
:style="{
|
width: scale + '%',
|
transform: 'scale(' + scale / 100 + ')',
|
transformOrigin: '0 0'
|
}"
|
></pdf>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import pdf from 'vue-pdf'
|
|
export default {
|
name: 'PdfPreview',
|
components: {
|
pdf
|
},
|
props: {
|
pdfUrl: {
|
type: String,
|
required: true
|
},
|
fileName: {
|
type: String,
|
default: ''
|
}
|
},
|
data() {
|
return {
|
loading: false,
|
currentPage: 1,
|
totalPages: 0,
|
scale: 100
|
}
|
},
|
methods: {
|
loadPdfHandler() {
|
this.loading = false;
|
},
|
|
pdfErrorHandler(error) {
|
console.error('PDF加载失败:', error);
|
this.loading = false;
|
this.$message.error('PDF文件加载失败,请尝试下载后查看');
|
},
|
|
prevPage() {
|
if (this.currentPage > 1) {
|
this.currentPage--;
|
}
|
},
|
|
nextPage() {
|
if (this.currentPage < this.totalPages) {
|
this.currentPage++;
|
}
|
},
|
|
zoomIn() {
|
if (this.scale >= 200) {
|
this.$message.info("已放大到最大比例");
|
return;
|
}
|
this.scale += 10;
|
},
|
|
zoomOut() {
|
if (this.scale <= 50) {
|
this.$message.info("已缩小到最小比例");
|
return;
|
}
|
this.scale -= 10;
|
},
|
|
resetZoom() {
|
this.scale = 100;
|
},
|
|
handleDownload() {
|
const link = document.createElement('a');
|
link.href = this.pdfUrl;
|
link.download = this.fileName;
|
link.style.display = 'none';
|
document.body.appendChild(link);
|
link.click();
|
document.body.removeChild(link);
|
this.$message.success('开始下载文件');
|
}
|
},
|
mounted() {
|
this.loading = true;
|
},
|
watch: {
|
pdfUrl() {
|
this.loading = true;
|
this.currentPage = 1;
|
this.scale = 100;
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.pdf-preview-container {
|
height: 100%;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.pdf-controls {
|
padding: 15px 20px;
|
background: #f5f7fa;
|
border-bottom: 1px solid #ebeef5;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
flex-wrap: wrap;
|
gap: 10px;
|
}
|
|
.pdf-render-area {
|
flex: 1;
|
overflow: auto;
|
padding: 20px;
|
background: #f8f9fa;
|
display: flex;
|
justify-content: center;
|
align-items: flex-start;
|
}
|
|
.zoom-controls {
|
margin: 0 15px;
|
}
|
|
@media (max-width: 768px) {
|
.pdf-controls {
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.zoom-controls {
|
margin: 10px 0;
|
}
|
}
|
</style>
|