admin管理员组

文章数量:1648972

 Vue3+Vite项目,实现自定义pdf查看并实现禁用下载复制

 

npm install vue3-pdfjs

npm install vue-pdf-embed

 测试版本: vue3-pdfjs @1.1.4;  vue3-pdfjs @0.1.6;

配置main.js 

import VuePdf from 'vue3-pdfjs'
app.use(router).use(ElementPlus).use(VuePdf);

在components文件夹新建组件,命名为” pdfPreview.vue”

<template>
    <div class="pdf-preview">
        <vue-pdf-embed :source="props.pdfUrl" :style="scale" class="vue-pdf-embed" :page="state.pageNum" />
    </div>
    <div class="page-tool">
        <div class="page-tool-item" @click="lastPage">上一页</div>
        <div class="page-tool-item" @click="nextPage">下一页</div>
        <div class="page-tool-item noPointer">{{state.pageNum}} / {{state.numPages}}</div>
        <div class="page-tool-item" @click="pageZoomOut">放大</div>
        <div class="page-tool-item bite noPointer">{{biteNum}}%</div>
        <div class="page-tool-item" @click="pageZoomIn">缩小</div>

    </div>
</template>
<script setup lang="ts">
import { reactive, onMounted, computed,ref,watch } from "vue";
import VuePdfEmbed from "vue-pdf-embed";
import { createLoadingTask } from "vue3-pdfjs/esm";
import { ElMessage } from "element-plus";


const props = defineProps({
    pdfUrl: {
        type: String,
        required: true
    }
})

let getUrl = ref('')
watch(() => props.pdfUrl,
	(newValue, oldValue) => {
        setTimeout(function () {
            getUrl.value = newValue;
		    console.log('getUrl',getUrl.value)
            if (getUrl.value) {
                onloadPdf()
            }else{
                console.log('warning');
            }
        }, 0);
	},
	{ deep: true, immediate: true }
)

const state = reactive({
    source: props.pdfUrl, // 预览pdf文件地址
    pageNum: 1, // 当前页面
    scale: 1, // 缩放比例
    paddingTop:0,
    paddingLeft:0,
    numPages: 15, // 总页数
});

function onloadPdf(){
    const loadingTask = createLoadingTask(getUrl.value);
    loadingTask.promise.then((pdf:{numPages: number}) => {
        state.numPages = pdf.numPages;
    });
}

onMounted(() => {
    // console.log('getUrl',props.pdfUrl);
});
const scale = computed(() => `
    transform:scale(${state.scale});
    padding: ${state.paddingTop}px ${state.paddingLeft}px ${state.paddingTop}px ${state.paddingLeft}px;
`)

function lastPage() {
    if (state.pageNum > 1) {
        setTimeout(function() {
            state.pageNum -= 1;
        }, 200);
    }
}
function nextPage() {
    if (state.pageNum < state.numPages) {
        setTimeout(function() {
            state.pageNum += 1;
        }, 200);
    }
}
let biteNum = ref(100);
function pageZoomOut() {
    if (state.scale < 1.2) {
        state.scale += 0.1;
        state.paddingTop += 28;
        state.paddingLeft += 40;
        
    }else{
        ElMessage({
            message: '不能再放大了',
            type: "warning",
            duration:800
        });
    }
    biteNum.value = (state.scale *100)^0
}
function pageZoomIn() {
    if (state.scale > 0.8) {
        state.scale -= 0.1;
        state.paddingTop -= 28;
        state.paddingLeft -= 40;
    }else{
        ElMessage({
            message: '不能再缩小了',
            type: "warning",
            duration:800
        });
    }
    biteNum.value = (state.scale *100)^0

}
</script>
<style lang="css" scoped>

.pdf-preview {
    position: relative;
    height: 90vh;
    overflow-y: auto;
    box-sizing: border-box;
    display: flex;
}
.vue-pdf-embed {
    width: 98%;
}
.vue-pdf-embed>div{
    height: 90vh;
}
.vue-pdf-embed canvas{
    height: 90vh !important;
}
.page-tool {
    font-size: 14px;
    position: absolute;
    bottom: 35px;
    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;
    margin-left: 50%;
    transform: translateX(-50%);
}
.page-tool-item {
    padding: 8px 15px;
    padding-left: 10px;
    cursor: pointer;
}
.bite{
    width: fit-content;
    background-color: rgba(0, 0, 0, 0.5);
    color: #fff;
    padding: 8px !important;
}
.noPointer{
    cursor: default;
}
.pdf-preview::-webkit-scrollbar{
    width: 10px;
    height: 10px;
}
.pdf-preview::-webkit-scrollbar-thumb{
    background-color: rgba(255, 255, 219, 0.1) ;
    border: #666 solid 1px;
    border-radius: 4px;
}
</style>

 父组件引用,传入pdf地址

<div class="pdfShlle" v-if="(scanPdfStatus === true)" @contextmenu.prevent="openMenu($event)">
	<ul class="headerNav">
		<li>{{ pdfName }}</li>
		<el-button type="primary" style="position: absolute;right: 40px;top: 14px; "
			@click="backList()">返回</el-button>
	</ul>
	<div class="mode">
		<div class="PdfBox">
			<div>
				<PDFView :pdfUrl="pdfUrl"></PDFView>
			</div>
		</div>
	</div>
</div>
<script setup>
import { getCurrentInstance, ref } from "vue";
import { useRoute } from "vue-router";
import PDFView from "../pdfPreview.vue"
let pdfName = ref('');
let pdfUrl = ref(null);
</script>

<style scoped>

/* 查看pdf */
.pdfShlle {
	width: 100%;
	height: 100vh;
	position: fixed;
	z-index: 9;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background-color: #303030;
	padding: 0 40px;
	box-sizing: border-box;
	user-select: none;

}

.headerNav {
	width: 100%;
	height: 8vh;
	line-height: 8vh;
	background-color: #333;
	padding-left: 20px;
	box-sizing: border-box;
	font-size: 18px;
	color: #fff;
	letter-spacing: 2px;
}

.mode {
	width: 85%;
	margin: auto;
	height: 86vh;
	position: relative;
}

.PdfBox {
	width: 100%;
	height: 86vh;
}

.PdfBox>div {
	position: relative;
	height: 86vh;
	width: 100%
}
</style>

 

本文标签: 自定义项目vitePDFjs