1、安装vue-pdf插件,swiper插件、clipboard

npm install vue-pdf -s
npm install swiper -S
npm install clipborad -S

 

2、使用,标题头提取的组件,slot占位

<template>
    <div class="pagepdf">
        <page-title :headerSetting="headerSetting">
          <!-- header_left就插槽名,不用默认就用slot -->
          <div slot="header_left" class="header_ico">
            <img class="goBackIcon" :src="goBackIcon" alt="" />
          </div>
          <div slot="header_center">pdf</div>
          <!-- header_right就插槽名,不用默认就用slot -->
          <div slot="header_right" class="header_right copyDom" @click="copy(url)">
              复制连接
          </div>
        </page-title>

        <div class="tools" v-show="lists.length>0">
            <div class="swiper-button-prev mr10">上一页</div>
            <div class="page">{{currentId}}/{{pageTotalNum}} </div>
            <div class="swiper-button-next mr10">下一页</div>
        </div>
        <div class="">
            <div id="tabApp1" class="swiper-container" style="visibility: hidden;">
                <div class="swiper-wrapper" ref="swiperWrapper0">
                    <div class="swiper-slide" v-for="(item, index) in lists" :class="{ active: currentId == item.id }"
                        :key="index">
                    </div>
                </div>
            </div>
        </div>
        <div id="tabContain" class="tabContain swiper-container" v-show="lists.length>0">
            <div class="swiper-wrapper">

                <div class="swiper-slide" v-for="(item, index) in lists" :key="index">
                    <div>
                        <pdf  :id="'pdfPreview'+index
                        " :src="pdfSrc" :page="index+1" class="pdf" ref="wrapper1" @progress="loadedRatio = $event"
                            @num-pages="pageTotalNum=$event" @error="pdfError($event)" @link-clicked="page = $event">

                        </pdf>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    import ClipboardJS from "clipboard";
    import "swiper/dist/css/swiper.min.css";
    import Swiper from "swiper";
    import pdf from "vue-pdf";
    export default {
        components: {
            pdf,
            pageTitle: (resolve) => require(["@/components/title"], resolve),
        },
        data() {
            return {
                titleName: 'pdf',
                url:'https://aaeasy-file.newbanker.cn/pic/testforyuhan/裴士杰的专属报告_2021-11-02_11_17_21.pdf',
                vuePdf: null,
                numPages: 1, //  pdf 文件总页数
                pageNum: 1,
                pageTotalNum: '',
                page: 1,
                pageRotate: '',
                scale: 100,
                // swiper
                mySwiper: null, //swiper实例
                swiperWidth: 0, //swiper可视宽度
                maxTranslate: "", //最大的滑动距离
                maxWidth: "",
                slide: {
                    offsetLeft: 0,
                    clientWidth: 0,
                },
                slideLeft: 0,
                slideWidth: 0,
                slideCenter: 0,
                nowTlanslate: 0,
                pageSwiper: {},
                currentId: 1,
                lists: [],
                isHide: true,
                // 头部浮层
                headerSetting: {
                  backgroundColor: "transparent",
                },
                goBackIcon: require("@/assets/imgs/goback.png"),
                pdfSrc:'',
            }
        },
        mounted() {
            let that = this;
            that.initPdf(that.url);
            that.mySwiper = new Swiper("#tabApp1", {
                freeMode: true,
                freeModeMomentumRatio: 0.5,
                slidesPerView: "auto",
                resistanceRatio: 0.7,
                setWrapperSize: true,
                observer: true,
                observeParents: true,
                loop: true,
                on: {
                    tap: function(swiper) {
                        // if (this.currentId <= this.pageTotalNum) {
                        that.swiperWidth = that.$refs.swiperWrapper0.clientWidth;
                        that.maxTranslate = that.mySwiper.maxTranslate();
                        that.maxWidth = -that.maxTranslate + that.swiperWidth / 2;

                        if ((that.currentId) == that.lists[this.clickedIndex].id) {
                            return;
                        }
                        that.currentId = that.lists[this.clickedIndex].id;
                        that.slide = this.slides[this.clickedIndex];
                        that.slideLeft = that.slide.offsetLeft;
                        that.slideWidth = that.slide.clientWidth;
                        that.slideCenter = that.slideLeft + that.slideWidth / 2;
                        that.mySwiper.setTransition(300);
                        if (that.slideCenter < that.swiperWidth / 2) {
                            that.mySwiper.setTranslate(0);
                        } else if (that.slideCenter > that.maxWidth) {
                            that.mySwiper.setTranslate(that.maxTranslate);
                        } else {
                            var nowTlanslate = that.slideCenter - that.swiperWidth / 2;
                            that.mySwiper.setTranslate(-nowTlanslate);
                        }
                        that.pageSwiper.slideTo(this.clickedIndex, 200, false);
                    },
                },
            });
            //swiper里边内容
            that.pageSwiper = new Swiper("#tabContain", {
                autoplay: false,
                direction: "horizontal", // 切换选项
                resistanceRatio: 0,
                paginationClickable: true,
                watchSlidesProgress: true,
                setWrapperSize: true,
                observer: true,
                observeParents: true,
                loop: true,
                navigation: {
                    nextEl: '.swiper-button-next',
                    prevEl: '.swiper-button-prev',
                },
                on: {
                    slideChangeTransitionEnd: function() {},
                    slideChange: function() {
                        that.swiperWidth = that.$refs.swiperWrapper0.clientWidth;
                        that.maxTranslate = that.mySwiper.maxTranslate();
                        that.maxWidth = -that.maxTranslate + that.swiperWidth / 2;
                        that.currentId = this.activeIndex + 1;
                        that.slide = that.mySwiper.slides[that.currentId];
                        that.slideLeft = that.slide.offsetLeft;
                        that.slideWidth = that.slide.clientWidth;
                        that.slideCenter = that.slideLeft + that.slideWidth / 2;
                        that.mySwiper.setTransition(300);
                        if (that.slideCenter < that.swiperWidth / 2) {
                            that.mySwiper.setTranslate(0);
                        } else if (that.slideCenter > that.maxWidth) {
                            that.mySwiper.setTranslate(that.maxTranslate);
                        } else {
                            var nowTlanslate = that.slideCenter - that.swiperWidth / 2;
                            that.mySwiper.setTranslate(-nowTlanslate);
                        }
                    },
                },
            });
        },
        watch: {
            'lists': {
                handler(newVal) {
                    if (newVal) {
                        this.isHide = false;

                    }
                },
                deep: true,
            },
        },
        methods: {
            initPdf(url) {
                this.pdfSrc = pdf.createLoadingTask(url)
                this.pdfSrc.then(pdf => {
                    this.pageTotalNum = pdf.numPages
                    let arr = [];
                    if (this.pageTotalNum > 0) {
                        for (let i = 1; i <= this.pageTotalNum; i++) {
                            let obj = {}
                            obj.id = i;
                            obj.name = 'name' + i;
                            arr.push(obj)
                        }
                        this.lists = arr;
                    }
                })
            },
            // 页面加载回调函数,其中e为当前页数
            pageLoaded(e) {
                this.curPageNum = e;
            },
            // 其他的一些回调函数。
            pdfError(error) {
                console.error(error);
            },
            copy(val) {
                if (val) {
                    var clipboard = new ClipboardJS(".copyDom", {
                        text: (trigger) => {
                            return val
                        }
                    });
                    clipboard.on("success", e => {
                        //复制成功
                        this.$commonJS.toastI('pdf地址复制成功');
                        console.log(val)
                        // 释放内存
                        clipboard.destroy();
                    });
                    clipboard.on("error", e => {
                        // 不支持复制
                        console.log("该浏览器不支持自动复制");
                        this.$commonJS.toastI('复制失败');
                        // 释放内存
                        clipboard.destroy();
                    });
                }
            },

        }
    }
</script>
<style scoped lang="less">
    .mr10,
    .page {
        width: 1.5rem;
        height: .5rem;
        background: #409EFF;
        border-radius: .05rem;
        display: inline-block;
        line-height: .5rem;
        text-align: center;
        position: relative;
        color: #fff;
        flex: 1;
        margin: 0.5rem 0.6rem 0;
        &.swiper-button-prev {margin-left:.2rem;}
        &.swiper-button-next{margin-right:.2rem;}
    }

    .title {
        text-align: center;
        margin-bottom: 0.5rem;
    }

    .title {
        text-align: center;
        margin-bottom: 0.5rem;
    }

    //  swiper
    .tabContain {

        .vs {
            border: 1px solid #fdd;
            margin: 0 0.3rem;
            overflow: hidden;
            min-height: 2.9rem;
        }
    }

    .tab {
        overflow: hidden;
        position: relative;
        margin-left: 0.3rem;
        height: 0.7rem;

        &::after {
            position: absolute;
            content: "";
            left: 0;
            bottom: 0;
            right: 0;
            height: 1px;
            background: #e6e6e6;
        }

        #tabApp {
            width: 100%;
            overflow: hidden;

            .swiper-slide {
                width: auto;
                flex-shrink: 0;
                font-size: 0.32rem;
                font-family: PingFangSC, PingFangSC-Regular;
                font-weight: 400;
                color: #333333;
                line-height: 0.48rem;
                padding: 0.1rem 0.15rem;

                &.active {
                    font-size: 0.34rem;
                    font-family: PingFangSC, PingFangSC-Medium;
                    font-weight: bold;
                    color: #000000;
                }

                span {
                    transition: all 0.3s ease;
                    display: block;
                }

                &:first-child {
                    padding-left: 0;
                }
            }
        }
    }

    .w100 {
        width: 100%;
    }

    .swiper-slide {
        .pdf {
            width:100%;
        }
    }

    .swiper-slide.active {
        font-size: 0.34rem;
        font-family: PingFangSC, PingFangSC-Medium;
        font-weight: bold;
        color: #000000;
    }

    .loading {
        width: 100%;
        height: 100%;
        background: rgba(255, 255, 255, 0.1);
        top: 0;
        left: 0;
        position: fixed;
        z-index: 100;
    }

    /deep/.pageTitle .pTitle .right {
        width: 1.6rem;

    }
    .header_right {
        color: #2351ba;

    }
    .tools {
        display: flex;
    }
    .pagepdf {
      height: 100vh;
      width: 100%;
      margin-top:1rem;
    }
    .header_ico {
      width: 0.64rem;
      img {
        width: 100%;
      }
    }
</style>

View Code

 

3、title.vue标题头组件

<template>
  <div class="pageTitle">
    <div class="pTitle" :style="{ background: headerSetting.backgroundColor }">
      <div class="left" @click="goBack()">
        <!-- 以插槽形式对外开放,支持自定义。默认右边不展示 -->
        <slot name="header_left"><</slot>
      </div>
      <div class="center"><slot name="header_center"></slot></div>
      <div class="right">
        <!-- 以插槽形式对外开放,支持自定义。默认右边不展示 -->
        <slot name="header_right"></slot>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    headerSetting: {
      backgroundColor: "transparent", //背景色
      default: () => {
        return {
          backgroundColor: "transparent",
        };
      },
    },
  },
  methods: {
    goBack() {},
  },
};
</script>
<style scoped lang="less">
/* // 页面顶部header的样式文件 */

.pageTitle {
  z-index: 999;
  padding-top: 0;
  .pTitle {
    position: fixed;
    left: 0;
    top: 1.1rem;
    z-index: 9;
    color: rgb(51, 51, 51);
    font-size: 0.32rem;
    word-break: break-all;
    width: 100%;
    background: transparent;
    height: 0.88rem;
    line-height: 0.88rem;
    border-bottom: 0.5px solid #ddd;
    display: flex;
    &.noBorder {
      border: none;
    }

    .left {
      width: 1.38rem;
      height: 0.88rem;
      line-height: 0.88rem;
      text-align: center;
      & > .icon_fanhui3x {
        font-size: 0.88rem;
        font-weight: 1;
        margin-left: -0.2rem;
        width: 1.38rem;
        display: block;
        text-align: center;
      }
    }

    .center {
      color: #272727;
      text-align: center;
      flex: 1;
    }
    /* //单行省略号 */
    .ellipsis {
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }

    .right {
      width: 2rem;
      height: 0.88rem;
      line-height: 0.88rem;
      display: flex;
    }
  }
  .blank {
    width: 100%;
    height: 0.88rem;
  }
  .disableSelection {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
    -o-user-select: none;
    pointer-events: none;
  }

  .doubleLines {
    display: block;
    height: 0.44rem;
    line-height: 0.44rem;
  }
}
</style>

View Code