- 需求描述:客户有10万多册的纸质档案的数据,需要电子化,电子化后可以通过查看界面查看基本的文本信息以及pdf和图片的信息
- 前端采用的技术为vue2.0,网上搜索了好做方案,大多数建议采用vue-pdf插件时间,所以本案例采用vue+vue-pdf实现pdf在线预览
- 在前端vue项目中安装vue-pdf插件,切换到vue项目根目录,执行命令:npm install --save vue-pdf
- 插件安装完成后,在所需的界面导入vue-pdf插件(import pdf from ‘vue-pdf’),然后进行插件的注册(components: {sider,UploadList,pdf}),我自己对应的查看页面代码如下,供大家参考:
<template>
<div>
<!--
<i class="el-icon-circle-plus-outline" @click="dialogFormVisible = true"></i> 通过图标触发新增
<el-button type="primary" icon="el-icon-circle-plus-outline" @click="dialogFormVisible = true">新增</el-button> --> <!-- 通过按钮触发新增 -->
<el-dialog title="查看房屋档案信息":visible.sync="houseInfoVisible" :before-close="handleClose">
<el-form :model="dataForm" ref="dataForm" style="text-align: auto">
<div class="item-content c1">
<div class="item">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="售卖单位:" prop="saleUnit">
<el-input v-model="dataForm.saleUnit" style="width: 100%" maxlength="30" placeholder="请填写售卖单位" :disabled="true"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="楼盘名称:" prop="premName">
<el-input v-model="dataForm.premName" style="width: 100%" maxlength="30" placeholder="请填写楼盘名称" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="楼栋名称:" prop="buildName">
<el-input v-model="dataForm.buildName" style="width: 100%" maxlength="30" placeholder="请填写楼栋名称" :disabled="true"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="单元名称:" prop="unitName">
<el-input v-model="dataForm.unitName" style="width: 100%" maxlength="30" placeholder="请填单元名称" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="房号:" prop="houseNo">
<el-input v-model="dataForm.houseNo" style="width: 100%" maxlength="30" placeholder="请填写房号" :disabled="true"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="建筑面积(㎡):" prop="builtUpArea">
<el-input type="number" min="0" v-model="dataForm.builtUpArea" style="width: 100%" maxlength="30" v-input-format="{ min: 0, max: 100000000, precision: 2 }" placeholder="请填写建筑面积" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="套内面积(㎡):" prop="insideArea">
<el-input type="number" min="0" v-model="dataForm.insideArea" style="width: 100%" maxlength="30" v-input-format="{ min: 0, max: 100000000, precision: 2 }" placeholder="请填写套内面积" :disabled="true"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="公摊面积(㎡):" prop="sharedArea">
<el-input type="number" min="0" v-model="dataForm.sharedArea" style="width: 100%" maxlength="30" v-input-format="{ min: 0, max: 100000000, precision: 2 }" placeholder="请填公摊面积" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="成交价格(元):" prop="houseTotalPrice">
<el-input type="number" v-model="dataForm.houseTotalPrice" style="width: 100%" maxlength="30" v-input-format="{ min: 0, max: 100000000, precision: 2 }" placeholder="请填写房屋总价" :disabled="true"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="房屋间数:" prop="fwjs">
<el-input v-model="dataForm.fwjs" style="width: 100%" maxlength="30" placeholder="房屋件数" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="所在层数:" prop="szcs">
<el-input v-model="dataForm.szcs" style="width: 100%" maxlength="30" placeholder="请填写所在层数" :disabled="true"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="建筑结构:" prop="jzjg">
<el-input v-model="dataForm.jzjg" style="width: 100%" maxlength="30" placeholder="请填写建筑结构" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="房屋座落:" prop="housePosition">
<el-input v-model="dataForm.housePosition" style="width: 100%" maxlength="30" placeholder="请填写房屋座落" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="买受人:" prop="buyPerson">
<el-input v-model="dataForm.buyPerson" style="width: 100%" maxlength="30" placeholder="请填写买受人" :disabled="true"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="买受人证件号:" prop="certificateNo">
<el-input v-model="dataForm.certificateNo" style="width: 100%" maxlength="60" placeholder="请填写买受人证件号" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="法人代表:" prop="legalPerson">
<el-input v-model="dataForm.legalPerson" style="width: 100%" maxlength="30" placeholder="请填写法人代表" :disabled="true"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="法人证件号:" prop="legalPersonCertificateNo">
<el-input v-model="dataForm.legalPersonCertificateNo" style="width: 100%" maxlength="60" placeholder="请填写法人证件号" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="产别:" prop="productionType">
<el-input v-model="dataForm.productionType" style="width: 100%" maxlength="30" placeholder="请输入产别:公产/私产" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- <el-row :gutter="20">
<el-col :span="24">
<el-form-item label="合同扫附件:" prop="htAttentments">
<upload-list :file-list="dataForm.htAttentment" :close-visible="!detail" :upload-visible="!detail" :disabled="true"></upload-list>
</el-form-item>
</el-col>
</el-row> -->
</div>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<h3 style="text-align: left;">房屋档案附件列表</h3>
<div class="arrow" v-for="(item,index) in pdfs" :key="item.value" style="border-top:2px solid #000;">
<!-- <button @click="item.Sub">上一页</button>
{{item.currentPage}}/{{item.pageCount}}
<button @click="item.Add">下一页</button>
<pdf ref="pdf" style="width:800px"
:src="item.src"
:page="item.currentPage"
@num-pages="item.pageCount=$event"
@page-loaded="item.currentPage=$event"
@loaded="item.lr">
</pdf> -->
<pdf :src="item.url" :page="currentArr[index].currentPage" @num-pages="currentArr[index].pageCount=$event" @page-loaded="currentArr[index].currentPage=$event" @loaded="loadPdfHandler" style="height: auto;"></pdf>
<p style="text-align: left;">
<span style="font-weight:bold;color:#1E90FF;font-size: large;">{{currentArr[index].currentPage}}</span><span> / </span> <span style="font-weight:bold;font-size: large;">{{currentArr[index].pageCount}}</span>
</p>
<el-button-group style="text-align: center;">
<el-button style="font-size: large;" @click="changePdfPage(0,index)" class="turn" :class="{grey: currentArr[index].currentPage==1}" type="text" icon="el-icon-arrow-left">上一页</el-button>
<el-button style="font-size: large;margin-left:20px;" @click="changePdfPage(1,index)" class="turn" :class="{grey: currentArr[index].currentPage==currentArr[index].pageCount}" type="text">下一页<i class="el-icon-arrow-right el-icon--right"></i></el-button>
</el-button-group>
<el-button style="font-size: large;margin-left: 50px;" type="text" @click="downloadPdf(item.url)">{{item.name}}</el-button>
</div>
<div v-for="(item,index) in images" :key="item.value" style="border-top:2px solid #000 ;">
<ul style="width: 800px;">
<img v-bind:src="item.url" v-bind:alt="item.name" style="width: 100%;height: auto;">
<p><el-button style="font-size: large;" type="text" @click="downloadPdf(item.url)">{{item.name}}</el-button></p>
</ul>
</div>
<!-- <el-button @click="houseInfoVisible = false">取 消</el-button> -->
<el-button @click="dataFormCancel()">关 闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { isEmpty, isDouble } from '@/utils/validate'
import sider from '@/components/sider'
import UploadList from '@/components/upload-list'
import pdf from 'vue-pdf'
export default {
components: {sider,UploadList,pdf},
data () {
// var validateHtAttentments = (rule, value, callback) => {
// if (!this.dataForm.htAttentment || this.dataForm.htAttentment.length === 0) {
// return callback(new Error('请上传合同附件'));
// } else {
// return callback()
// }
// }
return {
houseInfoVisible: false,
pdfs:[],
currentArr:[],
images:[],
dataForm: {
htAttentment: []
},
detail: false,
formLabelWidth: '120px'
}
},
created() {
//this.initPdfPage()
},
methods: {
init(id){
this.dataForm = {
saleUnit:'',
premName:'',
buildName:'',
unitName:'',
houseNo:'',
builtUpArea:'',
insideArea:'',
sharedArea:'',
houseTotalPrice:'',
fwjs:'',
szcs:'',
jzjg:'',
housePosition:'',
buyPerson:'',
certificateNo:'',
legalPerson:'',
legalPersonCertificateNo:'',
productionType:'',
htAttentment:[]
}
this.dataForm.id = id || 0
this.$nextTick(() => {
this.visible = true
this.$refs['dataForm'].resetFields()
})
if(this.dataForm.id){
this.$http({
url: this.$http.adornUrl(`/sl/contractInfo/info/${this.dataForm.id}`),
method: 'get',
params: this.$http.adornParams()
}).then(({data}) => {
if (data && data.code === 0) {
this.dataForm = data.entity
this.pdfs = data.entity.pdfs
this.images = data.entity.images
this.initPdfPage()
} else {
this.$message.error(data.msg)
}
})
}
},
handleClose(done){
this.$confirm('确认关闭详情界面码?')
.then(_ => {
done();
})
.catch(_ => {})
//this.houseInfoVisible = true
},
dataFormCancel () {
this.houseInfoVisible = false
this.dataForm.htAttentment = []
},
onSubmit (formName) {
console.log("执行方法")
this.$refs[formName].validate((valid) => {
if (valid) {
this.$http({
url: this.$http.adornUrl(`/sl/contractInfo/${!this.dataForm.id ? 'save' : 'update'}`),
method: 'post',
data: this.$http.adornData(this.dataForm)
}).then(({data}) =>{
if(data && data.code === 0){
console.log('请求成功!')
this.houseInfoVisible = false;
this.$emit('refreshDataList')
}else{
console.log('请求失败')
}
})
}
})
},
initPdfPage(){
for (var i = 0; i < this.pdfs.length; i++) {
this.currentArr.push({
currentPage: 0, // pdf文件页码
pageCount: 0 // pdf文件总页数
})
}
},
changePdfPage (val, index) {
if (val === 0 && this.currentArr[index].currentPage > 1) {
this.currentArr[index].currentPage--
}
if (val === 1 && this.currentArr[index].currentPage < this.currentArr[index].pageCount) {
this.currentArr[index].currentPage++
}
},
// pdf加载时
loadPdfHandler (e) {
// this.currentPage = 1 // 加载的时候先加载第一页
for (var i = 0; i < this.currentArr.length; i++) {
this.currentArr[i].currentPage = 1
}
},
downloadPdf(url){
window.open(url);
}
}
}
</script>
<style scoped>
.el-icon-circle-plus-outline {
margin: 50px 0 0 20px;
font-size: 100px;
float: left;
cursor: pointer;
}
.mod-building-add-or-update {
background: #f1f4f5;
}
.button-content {
background: #fff;
border-top: 1px solid #e9e9e9;
height: 60px;
line-height: 60px;
padding-left: 20px;
text-align: center;
}
.item-content {
background: #fff;
}
.item-content .item-title {
height: 40px;
line-height: 40px;
border-bottom: 1px solid #e9e9e9;
}
.item-content .item-title span {
margin-left: 20px;
font-weight: bold;
}
.item-content .item {
padding: 10px;
}
.c2 {margin-top: 10px;}
.col14{ width: 50%; margin: 0 1% 0 0;}
.col34{ width: 65%;}
</style>
- 在date 的return中定义一个pdfs数据,接收后台返回的pdf集合
- 通过上面的方法,前端pdf主句已经接收到了后台返回的pdf集合,接下来就是展示的问题了
- 界面上已经引入并注册了vue-pdf插件,所以在界面上直接使用pdf标签即可
<div class="arrow" v-for="(item,index) in pdfs" :key="item.value" style="border-top:2px solid #000;">
<pdf :src="item.url" :page="currentArr[index].currentPage" @num-pages="currentArr[index].pageCount=$event" @page-loaded="currentArr[index].currentPage=$event" @loaded="loadPdfHandler" style="height: auto;"></pdf>
<p style="text-align: left;">
<span style="font-weight:bold;color:#1E90FF;font-size: large;">{{currentArr[index].currentPage}}</span><span> / </span> <span style="font-weight:bold;font-size: large;">{{currentArr[index].pageCount}}</span>
</p>
<el-button-group style="text-align: center;">
<el-button style="font-size: large;" @click="changePdfPage(0,index)" class="turn" :class="{grey: currentArr[index].currentPage==1}" type="text" icon="el-icon-arrow-left">上一页</el-button>
<el-button style="font-size: large;margin-left:20px;" @click="changePdfPage(1,index)" class="turn" :class="{grey: currentArr[index].currentPage==currentArr[index].pageCount}" type="text">下一页<i class="el-icon-arrow-right el-icon--right"></i></el-button>
</el-button-group>
<el-button style="font-size: large;margin-left: 50px;" type="text" @click="downloadPdf(item.url)">{{item.name}}</el-button>
</div>
- 在div中通过for循环遍历pdf数组,使用pdf标签进行展示,这种方式是默认展示pdf的首页,通过上一页和下一页进行切换,所以需要定义一个数组,来存房每个pdf的当前页和总页数:
- js中有四个方法需要重点说明一下:
initPdfPage(){
for (var i = 0; i < this.pdfs.length; i++) {
this.currentArr.push({
currentPage: 0, // pdf文件页码
pageCount: 0 // pdf文件总页数
})
}
},
changePdfPage (val, index) {
if (val === 0 && this.currentArr[index].currentPage > 1) {
this.currentArr[index].currentPage--
}
if (val === 1 && this.currentArr[index].currentPage < this.currentArr[index].pageCount) {
this.currentArr[index].currentPage++
}
},
// pdf加载时
loadPdfHandler (e) {
// this.currentPage = 1 // 加载的时候先加载第一页
for (var i = 0; i < this.currentArr.length; i++) {
this.currentArr[i].currentPage = 1
}
},
downloadPdf(url){
window.open(url);
}
- initPdfPage(),在成功获取到基本信息后执行,changePdfPage()点击上一页下一页时进行页数切换,loadPdfHandler(),设置pdf加载第一页,downloadPdf(),点击文件名称时下载该文件,实现后的最终效果如下: