1、下载插件
javascript
npm install vue-pdf-embed vue3-pdfjs
vue3-pdfjs:获取PDF文件总页数
2、页面引入并使用
javascript
<template>
<div class="vuePdfEmbed">
<div class="wraper" v-if="flagCover">
<div class="articleTitle">
{{ reportDetail.title }}
</div>
<div class="articleTagBox">
<div>{{ reportDetail.createTime }}</div>
</div>
<div class="articleDetailCover">
<el-image :src="reportDetail.cover" alt="" lazy class="articleDetailCoverImg" />
</div>
<div class="articleIntroduce">
{{ reportDetail.summary }}
</div>
</div>
<VuePdfEmbed
:source="state.source"
:style="scaleFun"
class="vue-pdf-embed"
:page="state.pageNum"
lazy
/>
<div class="page-tool" v-if="!bottomVisible">
<div class="page-tool-item" @click="lastPage">上一页</div>
<div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
<div class="page-tool-item" @click="nextPage">下一页</div>
</div>
<!-- 购买提示 -->
<div class="bottomVisible" v-if="bottomVisible">
<div class="lock-box">
<img src="./img/lock.png" alt="" class="lock-box-img" />
<div>购买后可继续阅读本文档</div>
</div>
<div class="buy-box">
<div class="fixedBoxL">
<div class="fixedBoxLT">购买全文</div>
<div class="fixedBoxLB">单篇需付费¥{{ apperMoney }}</div>
</div>
<div class="fixedBoxR" @click="goBuyReport">
立即购买<el-icon><ArrowRightBold /></el-icon>
</div>
</div>
</div>
<!-- 弹框提示 -->
<el-dialog v-model="dialogVisible">
<div class="dialog-box">
<div class="dialog-text-box">
<div class="dialog-title">购买后可继续阅读本文档</div>
<div class="dialog-info">单篇付费只需{{ apperMoney }}元</div>
</div>
<div class="dialog-text-box">
<div class="dialog-btn" @click="goBuyReport">立即购买</div>
<div class="dialog-close" @click="handleClose">我再想想</div>
</div>
</div>
<div class="dialog-close-box" @click="handleClose"></div>
</el-dialog>
</div>
</template>
<script setup>
import {
LaunchApp,
detector,
ua,
copy,
supportLink,
isAndroid,
isIos,
inWeixin,
inQQ,
inWeibo,
inBaidu,
} from "web-launch-app";
import { getReportDetailApi } from "@/http/api";
import { ElMessage } from "element-plus";
import { useRoute, useRouter } from "vue-router";
import { reactive, onMounted, ref, onUnmounted } from "vue";
import VuePdfEmbed from "vue-pdf-embed";
import { createLoadingTask } from "vue3-pdfjs"; // 获得总页数
import { ArrowRightBold } from "@element-plus/icons-vue";
const route = useRoute();
const pdfurl = ref("");
const state = reactive({
source: pdfurl, //预览pdf文件地址
pageNum: 1, //当前页面
scale: 1, // 缩放比例
numPages: 0, // 总页数
});
const scaleFun = reactive({
transform: "scale(" + state.scale + ")",
});
// 获取上一页
function lastPage() {
if (state.pageNum > 1) {
state.pageNum--;
}
}
// 获取下一页
function nextPage() {
if (state.pageNum < state.numPages) {
state.pageNum++;
}
}
onMounted(() => {
getReportDetail();
});
// 获取pdf文件
// let flag = ref(false); // 下载按钮的显隐
let flagCover = ref(false); // 封面显隐
let apperMoney = ref(); // 价格
let bottomVisible = ref(false);
const reportDetail = ref({});
function getReportDetail() {
getReportDetailApi(route.query.id).then((res) => {
if (res.code == 200) {
document.title = res.data.title;
if (res.data.isFree == 1 && res.data.isPurchase == 2) {
// 付费 且 已解锁
pdfurl.value = res.data.fileUrl;
// flag.value = true;
// 加载异步任务
const loadingTask = createLoadingTask(state.source);
// 载入pdf后获取页数
loadingTask.promise.then((pdf) => {
state.numPages = pdf.numPages;
});
} else if (res.data.isFree == 0) {
// 免费
pdfurl.value = res.data.fileUrl;
// flag.value = true;
// 加载异步任务
const loadingTask = createLoadingTask(state.source);
// 载入pdf后获取页数
loadingTask.promise.then((pdf) => {
state.numPages = pdf.numPages;
});
} else if (res.data.isFree == 1 && res.data.isPurchase == 1) {
// 付费 且 未解锁
// 展示封面图 且 立即购买
reportDetail.value = res.data;
// flag.value = false;
if (route.query.type == "ios") {
apperMoney.value = res.data.appearIosAmount;
} else {
// 安卓现价
apperMoney.value = res.data.appearAmount;
}
bottomVisible.value = true;
flagCover.value = true;
timer = setInterval(() => {
dialogVisible.value = true;
}, 2000);
}
} else {
ElMessage({
message: res.msg,
type: "error",
plain: true,
});
}
});
}
// 弹框
const dialogVisible = ref(false);
let timer;
function handleClose() {
dialogVisible.value = false;
clearInterval(timer);
}
onUnmounted(() => {
clearInterval(timer);
});
// 立即购买
function goBuyReport() {
if (isAndroid) {
androidCscFinanceNews.clickBuyReport(Number(route.query.id));
} else if (isIos) {
window.webkit.messageHandlers.clickBuyReport.postMessage([Number(route.query.id)]);
}
}
</script>
<style>
.vuePdfEmbed {
flex: 1;
display: flex;
height: 100%;
flex-direction: column;
}
.vuePdfEmbed {
flex: 1;
display: flex;
height: 100%;
flex-direction: column;
}
.vuePdfEmbed {
.page-tool {
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
padding-left: 15px;
padding-right: 15px;
display: flex;
align-items: center;
background: rgb(66, 66, 66);
color: white;
border-radius: 19px;
z-index: 100;
cursor: pointer;
width: 320px;
align-items: center;
margin: auto;
justify-content: space-around;
}
.page-tool-item {
padding: 8px 15px;
padding-left: 10px;
cursor: pointer;
}
}
.el-dialog {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
margin: 0;
width: 270px;
height: 270px;
background-image: url("./img/dialog.png");
background-size: contain;
background-color: transparent;
box-shadow: none;
}
.el-dialog__headerbtn {
display: none;
}
.dialog-box {
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 100%;
height: 60%;
display: flex;
justify-content: space-around;
flex-direction: column;
align-items: center;
}
.dialog-text-box {
display: flex;
flex-direction: column;
align-items: center;
}
.dialog-title {
font-weight: 500;
font-size: 20px;
color: #8b2507;
line-height: 28px;
}
.dialog-info {
font-weight: 400;
font-size: 16px;
color: #ad705e;
line-height: 23px;
}
.dialog-btn {
width: 154px;
height: 47px;
background: linear-gradient(360deg, #ff330a 0%, #fc4707 100%);
box-shadow: 0px 2px 0px 0px #ffa073, inset 1px 5px 9px 0px rgba(255, 255, 255, 0.67);
font-weight: 500;
font-size: 17px;
color: #ffffff;
line-height: 47px;
text-align: center;
border-radius: 80px;
}
.dialog-close {
font-weight: 400;
font-size: 12px;
color: rgba(0, 0, 0, 0.4);
line-height: 40px;
}
.dialog-close-box {
position: absolute;
left: 50%;
bottom: -60px;
transform: translateX(-50%);
width: 36px;
height: 36px;
background-image: url("./img/close.png");
background-size: cover;
}
.lock-box {
display: flex;
justify-content: center;
align-items: center;
height: 178px;
background: linear-gradient(180deg, rgba(253, 250, 243, 0.97) 0%, #fef2e6 100%);
border-radius: 4px 4px 4px 4px;
text-align: center;
line-height: 178px;
font-weight: 400;
font-size: 14px;
color: #784122;
}
.lock-box-img {
display: block;
width: 13px;
height: 16px;
margin-right: 9px;
}
.buy-box {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 60px;
background-image: url("./img/bottom.png");
background-size: cover;
margin-top: -12px;
padding: 0 30px;
}
.fixedBoxL {
padding-top: 10px;
}
.fixedBoxLT {
font-size: 14px;
line-height: 20px;
color: rgba(255, 255, 255, 0.9);
font-weight: 400;
}
.fixedBoxLB {
font-size: 10px;
line-height: 12px;
color: rgba(255, 255, 255, 0.6);
font-weight: 400;
}
.fixedBoxR {
display: flex;
align-items: center;
font-size: 16px;
line-height: 20px;
color: rgba(255, 255, 255, 0.9);
font-weight: 500;
}
.bottomVisible {
position: fixed;
width: 100%;
bottom: 0;
z-index: 2;
}
.articleTitle {
font-size: 24px;
color: rgba(0, 0, 0, 0.9);
line-height: 32px;
font-weight: 500;
}
.articleTagBox {
display: flex;
margin-top: 12px;
margin-bottom: 20px;
font-size: 12px;
line-height: 20px;
color: rgba(106, 106, 106, 1);
}
.articleDetailCover {
margin-bottom: 12px;
}
.el-image__inner {
border-radius: 4px;
}
.articleDetailCoverImg {
display: block;
width: 100%;
border-radius: 4px;
}
.articleIntroduce {
font-weight: 400;
font-size: 12px;
color: #6b6b6b;
line-height: 22px;
background: #f6f6f6;
border-radius: 4px 4px 4px 4px;
padding: 12px;
margin-bottom: 12px;
}
.vue-pdf-embed__page canvas {
width: 100% !important;
}
@media screen and (min-width: 500px) {
.bottomVisible {
position: relative;
}
}
</style>
重点代码: