公司有一个想要实现的功能就是在小程序中要实时预览pdf文件,小程序只支持wx.downloadFile和wx.openDocument,所以不符合我的期望。然后就使用了pdfh5.js(版本号1.3.20),用webview嵌套网页做的。
<template>
<div class="pdf-container">
<div class="pdf-big-box">
<div ref="menuTab" id="menuTab"></div>
<div ref="pdfBox" id="pdfBox"></div>
</div>
<div class="btn-box">
<van-button class="refuse-btn" round type="primary" @click="conBackFun">返回</van-button>
<van-button class="immedite-btn" round type="primary" @click="immeditSigned">提交签署</van-button>
</div>
<!--签署方式-->
<van-popup
v-model="show"
closeable
round
position="bottom"
:style="{height:'5.1rem'}"
>
<div>
<div class="signed-hand-types">签署意愿验证</div>
<div class="ipt-box" style="padding-bottom:.48rem;">
<div class="phone-box">
<span>当前手机号:</span>
<span>{{ startSuPhone }}</span>
</div>
<div class="code-input">
<div>
<input class="sms-input" type="number" placeholder="请输入验证码" v-model="smsCode"/>
</div>
<div class="verify-code">
<button class="verify-btn" @click='getCode' :disabled='btnDisabled'>{{ btnValue }}</button>
</div>
</div>
</div>
<div class="sms-code-btn">
<button @click="smsConfirm">确定</button>
</div>
</div>
</van-popup>
</div>
</template>
<script>
import 'pdfh5/css/pdfh5.css';
import Pdfh5 from 'pdfh5';
import {Button, Popup} from 'vant';
import wx from 'weixin-js-sdk';
export default {
name: 'signedPdf',
data() {
return {
pdfh5: null,
contractId: '',
token: null,
signType: '',
signImgKey: '',
phone: '',
startSuPhone:'',
show: false,
handSignedList: [
{
id: 0,
name: '手写签名',
img: require('../../assets/img/handwrittenImg.png'),
checked: true,
},
{
id: 1,
name: '默认签章',
img: require('../../assets/img/defaultSignature.png'),
checked: false,
},
],
btnValue: '获取验证码',
btnDisabled: false,
second: 60,
smsCode: '',
}
},
components: {Button, Popup},
methods: {
getPdfList() {
this.$http.post('/contract/contractService/signaturePreviewForApp', {
contractId: this.contractId,
signType: this.signType,
signImgKey: this.signImgKey
}, {headers: {token: this.token}}).then(res => {
let data = res.data;
if (data.success) {
this.drawData(data.data);
}
})
},
drawData(arr) {
let that = this;
arr.forEach((item, index) => {
var pdfId = 'pdf-'
var pdfTabs = document.createElement('a');
var pdfTabsDiv = document.createElement('div');
var pdfTabsBorder = document.createElement('div');
var pdfCanvas = document.createElement('div');
pdfTabsDiv.className = 'pdf-a-divs';
pdfTabsBorder.className = 'border-div'
pdfTabsDiv.appendChild(pdfTabs);
pdfTabsDiv.appendChild(pdfTabsBorder);
pdfCanvas.id = pdfId + item.id;
pdfTabs.className = 'pdf-tabs';
pdfTabsDiv.setAttribute('new-id', pdfId + item.id)
pdfTabs.innerText = item.filesName;
this.$refs.pdfBox.appendChild(pdfCanvas);
this.$refs.menuTab.appendChild(pdfTabsDiv);
this.pdfh5 = new Pdfh5("#" + pdfId + item.id, {
pdfurl: item.filesUrl,
backTop: false,
maxZoom:1,
})
this.pdfh5.on("zoom", function (scale) {
})
this.pdfh5.on("ready", function () {
})
this.pdfh5.on("success", function (time) {
})
this.pdfh5.on("error", function (time) {
})
this.pdfh5.on("complete", function (status, msg, time) {
})
this.pdfh5.on("render", function (currentNum, time, currentPageDom) {
})
})
$("#menuTab .pdf-a-divs").eq(0).children('.border-div').addClass('border-div-active');
$("#menuTab .pdf-a-divs").eq(0).children('.pdf-tabs').addClass('tabMenu-active')
$(".pdf-a-divs").click(function () {
var hrefIId = $(this).attr('new-id');
$("html,body").animate({scrollTop:$("#" + hrefIId).offset().top + 10}, 100);
});
},
getUrlParam(name) {
if (!name) return null;
var after = window.location.search;
after = after.substr(1) || window.location.hash.split('?')[1];
if (!after) return null;
if (after.indexOf(name) === -1) return null;
var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
var r = decodeURIComponent(after).match(reg);
if (!r) return null;
return r[2];
},
immeditSigned() {
this.show = true;
},
conBackFun() {
this.$router.replace({
name: 'pdf',
query: {
isIdent: 'formSignedPdf',
id: this.contractId,
token: this.token,
phone: this.phone,
btnShow: 1,
}
})
},
targetHand(child, index) {
let that = this;
let checked = child.id
this.handSignedList.forEach(item => {
if (item.id == checked) {
item.checked = true
} else {
item.checked = false;
}
})
},
confirmSigned() {
let id = ''
this.handSignedList.forEach(item => {
if (item.checked) {
id = item.id
}
})
if (id == 0) {
wx.miniProgram.redirectTo({
url: `/pages/signPanel/signPanel?id=${this.contractId}&signType=1`
})
this.show = false;
} else {
wx.miniProgram.redirectTo({
url: `/pages/contractShallSigned/contractShallSigned?id=${this.contractId}&signType=2`
})
this.show = false;
}
},
getCode() {
var that = this;
this.$http.post('/login/loginService/sendVerifyCode', {
phone: this.phone,
type: 11
}, {headers: {token: this.token}}).then(res => {
let data = res.data;
if (data.success) {
this.$toast(data.msg);
that.timer();
} else {
this.$toast(data.msg);
}
})
},
timer() {
let promise = new Promise((resolve, reject) => {
let setTimer = setInterval(
() => {
var second = this.second - 1;
this.second = second;
this.btnValue = second + '秒'
this.btnDisabled = true
if (this.second <= 0) {
this.second = 60;
this.btnValue = '获取验证码';
this.btnDisabled = false;
resolve(setTimer)
}
}
, 1000)
})
promise.then((setTimer) => {
clearInterval(setTimer)
})
},
smsConfirm() {
let that = this;
let params = {
contractId: this.contractId,
code: this.smsCode
}
if (this.signType == 1) {
params.signType = 1;
params.signImgKey = this.signImgKey
} else {
params.signType = 2;
}
if (this.smsCode) {
this.$http.post('xxxx你的url地址', params, {headers: {token: this.token}}).then(res => {
let data = res.data;
if (data.success) {
wx.miniProgram.redirectTo({
url: `/pages/signedStatus/signedStatus?status=1&id=${that.contractId}`
})
} else {
this.$toast(data.msg);
}
})
}
},
},
mounted() {
if (this.$route.query.signType == 2) {
this.contractId = this.$route.query.id
this.signType = this.$route.query.signType
this.token = this.$route.query.token;
this.phone = this.$route.query.phone;
let startPhone = '' + this.$route.query.phone;
this.startSuPhone = startPhone.substr(0,3) + '****' + startPhone.substr(7);
this.getPdfList();
} else {
this.contractId = this.getUrlParam('id');
this.token = this.getUrlParam('token');
this.phone = this.getUrlParam('phone');
let startPhone = '' + this.getUrlParam('phone');
this.startSuPhone = startPhone.substr(0,3) + '****' + startPhone.substr(7);
this.signImgKey = this.getUrlParam('signImgKey');
this.signType = this.getUrlParam('signType');
this.getPdfList();
}
window.addEventListener('scroll',()=>{
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var listss = document.getElementById('pdfBox');
var navList = $("#menuTab>div");
let BoxList = $("#pdfBox .pdfjs");
Array.from(BoxList).forEach((item,index) =>{
if(scrollTop > item.offsetTop && scrollTop < (item.clientHeight + item.offsetTop)){
navList[index].childNodes[0].className = 'pdf-tabs tabMenu-active'
navList[index].childNodes[1].className = 'border-div border-div-active'
}else{
navList[index].childNodes[0].className = 'pdf-tabs'
navList[index].childNodes[1].className = 'border-div'
}
if(scrollTop >= 0 && scrollTop <= BoxList[0].clientHeight){
navList[0].childNodes[0].className = 'pdf-tabs tabMenu-active'
navList[0].childNodes[1].className = 'border-div border-div-active'
}
})
})
}
}
</script>
<style lang="scss" scoped>
.pdf-container {
.pdf-big-box {
padding-bottom: 1.56rem;
background-color: #f5f5f5;
}
font-size: .32rem;
height: 100%;
::v-deep .pdf-tabs {
text-decoration: none;
padding:0rem .24rem;
color: #81878E;
font-size: .28rem;
margin-bottom: .1rem;
}
::v-deep .tabMenu-active {
color: #007BFF;
font-size: .32rem;
font-weight: 700;
}
::v-deep .pinch-zoom-container {
height: auto !important;
}
.btn-box {
position: fixed;
width: 100%;
box-sizing: border-box;
padding: .32rem;
background: rgba(255,255,255,1);
box-shadow: 0px -4px 12px 0px rgba(0,0,0,0.09);
display: flex;
justify-content: space-between;
bottom: 0px;
.refuse-btn {
border-color: #007BFF;
background-color: #fff;
color: #007BFF;
padding: .26rem 1.34rem;
font-size: .32rem;
}
.immedite-btn {
color: #fff;
background-color: #007BFF;
padding: .26rem 1.02rem;
font-size: .32rem;
border-color: transparent;
}
}
}
::v-deep .pdfjs .loadingBar .progress .glimmer{
background: #007BFF!important;
}
#menuTab {
padding: .24rem;
font-size: .32rem;
position: fixed;
width: 100%;
box-sizing: border-box;
background-color: #fff;
z-index: 9;
overflow-x: scroll;
white-space: nowrap;
display: flex;
}
::v-deep .pdf-a-divs{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
::v-deep .border-div{
width: .5rem;
height: .06rem;
}
::v-deep .border-div-active{
background-color: #007BFF;
}
.pdfjs {
overflow: auto;
}
#pdfBox {
padding-top: 1.12rem;
overflow: scroll;
height: 100%;
}
.signed-hand-types {
font-size: .36rem;
color: #212121;
text-align: center;
padding-top: .32rem;
}
.code-input {
display: flex;
padding-bottom: .24rem;
border-bottom: 1px solid #ccc;
justify-content: space-between;
align-items: center;
margin-top: .64rem;
font-size: .32rem;
.sms-input {
border: none;
}
.verify-btn {
color: #007BFF;
background: transparent;
border: transparent;
font-size: .24rem;
}
}
.sms-code-btn {
padding: 0rem .8rem;
}
.sms-code-btn button {
background-color: #007BFF;
border-radius: .46rem;
color: #fff;
padding: .26rem;
width: 100%;
border: transparent;
}
.ipt-box {
padding: .8rem;
}
.phone-box {
color: #56595B;
font-size: .32rem;
}
.signed-content {
padding: .48rem .32rem;
}
.signed-child {
box-sizing: border-box;
padding: .32rem;
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid #AAB3BD;
border-radius: .24rem;
margin-bottom: .32rem;
}
.signed-han-img-box {
display: flex;
}
.han-img {
width: 1.66rem;
height: 1.10rem;
}
.han-img img {
width: 100%;
height: 100%;
}
.signature-text {
margin-left: .32rem;
color: #212121;
font-size: .32rem;
}
.check-img {
width: .44rem;
height: .44rem;
border-radius: 100%;
}
.check-img-default {
border: 2px solid #ccc;
}
.check-img img {
width: 100%;
height: 100%;
}
.default-active {
color: #81878E;
}
.refuse-confirm-btn-box {
padding: 0rem .32rem;
}
.confirm-btn-box {
padding: 0rem .32rem;
}
.refuse-confirm-btn-box button {
background-color: #007BFF;
border-radius: .46rem;
color: #fff;
margin-top: .48rem;
}
.confirm-btn-box button {
background-color: #007BFF;
border-radius: 0.46rem;
color: #fff;
padding: .26rem 0rem;
width: 100%;
border-color: transparent;
}
</style>