• vue里面使用pdfjs-dist+fabric实现pdf电子签章!!!


    2022.9.6

    一、需求

    最近领导提了一个新需求:仿照e签宝,实现pdf电子签章!

    最终实现效果图

    这是做出来的效果图,当然还有很多待修改
    在这里插入图片描述

    二、思路

    然后我就去看了下人家e签宝的操作界面,左侧是印章,右侧是pdf,然后拖拽印章到pdf上面,点击保存,下次打开时显示印章的位置。
    思路:我首先想到了拖拽、pdf预览、坐标;分工明确,前端来实现拖拽,pdf预览及把印章信息和坐标传给后端,后端只需要把信息和坐标保存下来就可以了。

    三、使用插件

    之前实现pdf预览就是通过window.open,打开一个窗口,显示pdf,功能很多,但是和需求不符,需要做的事是把pdf显示出来,同时可以可以拖拽印章到上面去,也不要放大与缩小及其他的功能。百度下了,说是用pdfjs-dist,这个pdf插件可以自定义很多的功能,但是实际用起来,发现好坑。。最后去百度了下,vue实现pdf电子签章, 看有没有现成的,然后还真找到了一个。js处理pdf展示、分页和签章等功能,下载到本地(只许查看index.html文件即可)后发现大佬用的不是vue-cli脚手架,是引用的cdn链接,然后就cv到项目里面了,跟着步骤,安装了pdfjs-dist插件(pdf插件)和fabric插件(专门处理印章的插件)这两个插件,但是项目本地运行后,报错了。。

    四、遇到的问题

    1.TypeError: Cannot read properties of undefined( reading 'Globalworkeroptions ')

    在这里插入图片描述
    百思不得其解啊,照着步骤来的啊,为啥呢,然后又回去看了下大佬的代码,发现他的pdf.js不是用的pdfjs-dist,而是引入的pdf的cdn链接
    在这里插入图片描述
    然后我就在项目的public/index.html下面引入这个链接
    在这里插入图片描述
    pdf路径则是使用的一个在线的pdf链接,https://www.gjtool.cn/pdfh5/git.pdf,发现可以打开了(样式做了些修改)
    在这里插入图片描述
    2.Dev Tools failed to load source map: Could not load content for https //mozilla github.ia/pdf js/build/pdf js map: Load canceled due to loadtimeout
    开始觉得似乎已经大功告成了,到时候和后端商量下返回数据的格式就完事了的,谁知道还是有问题的。。多次打开关闭pdf后,有时候pdf会不加载出来了。人麻了,然后看了下提示,加载超时了,取消加载。
    在这里插入图片描述
    明显是cdn链接的问题,那就把pdf.js文件下载到本地呗,本地加载快,应该不会出现加载超时的问题,结果还是有问题。
    在这里插入图片描述
    唉,真的是服了,使用cdn链接吧,会加载超时,下载到本地引用吧,又会报这么个莫名其妙的问题,然后今天浏览博客时,发现一个兄弟碰到了一样的问题,哈哈,发现还是引入pdf方式的问题

    /* 引用cdn链接,可以使用但会加载超时 */ 
    // let pdfjsLib = window["pdfjs-dist/build/pdf"];
    // pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://mozilla.github.io/pdf.js/build/pdf.worker.js';
    /* 下载到本地,看着官方文档引用,报个莫名其妙的错 */
    // import pdfjsLib from 'pdfjs-dist';
    // pdfjsLib.GlobalWorkerOptions.workerSrc='pdfjs-dist/build/pdf.worker.js';
    /* 下载到本地,照着大佬的方式引用,完美! */
    let pdfjsLib =require("pdfjs-dist/legacy/build/pdf.js");
    import workerSrc from "pdfjs-dist/legacy/build/pdf.worker.entry";
    pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这是大佬的博客链接pdf.js 使用攻略及错误集合

    不过这项目的电子签章有些与众不同,用户打开的pdf,是可以自定义的,即用户打开弹窗,在tinymac编辑器里面输入内容,然后切换tab,会立即生成一个pdf,接下来才是用户使用电子签章的过程

    以下是电子签章的主要代码,和大佬的index.html的代码差不多,就是做了点修改(ps:目前印章的位置和坐标保存,使用的得本地缓存,便于调试,后期会保存到接口里面!)

    代码部分

    首先 引入pdfjs-dist插件和fabric插件

    npm install pdfjs-dist
    
    • 1
    npm i fabric --save
    
    • 1

    2023年10月12日修改

    pdfjs-dist的安装版本尽量安装2.0的版本,如 npm install pdfjs-dist@2.16.105 --save,不然直接安装最新的pdfjs-dist版本可能出现pdf不显示的问题

    html部分

    <div id="elesign" class="elesign">
    	<el-row>
        <el-col :span="4" style="margin-top:1%;">
          <div class="left-title">我的印章</div>
          <draggable v-model="mainImagelist" :group="{ name: 'itext', pull: 'clone' }" :sort="false" @end="end">
            <transition-group type="transition">
              <li v-for="item in mainImagelist" :key="item" class="item" style="text-align:center;">
                <img :src="item" width="100%;" height="100%" class="imgstyle" />
              </li>
            </transition-group>
          </draggable>
        </el-col>
        <el-col :span="16" style="text-align:center;" class="pCenter">
          <div class="page">
            <!-- <el-button class="btn-outline-dark" @click="zoomIn">-</el-button>
            <span style="color:red;">{{(percentage*100).toFixed(0)+'%'}}</span>
            <el-button class="btn-outline-dark" @click="zoomOut">+</el-button> -->
            <el-button class="btn-outline-dark" @click="prevPage">上一页</el-button>
            <el-button class="btn-outline-dark" @click="nextPage">下一页</el-button>
            <el-button class="btn-outline-dark">{{ pageNum }}/{{ numPages }}</el-button>
            <el-input-number style="margin:0 5px;border-radius:5px;" class="btn-outline-dark"  v-model="pageNum" :min="1" :max="numPages" label="输入页码"></el-input-number>
            <el-button class="btn-outline-dark" @click="cutover">跳转</el-button>
          </div>
          <canvas id="the-canvas" />
          <!-- 盖章部分 -->
          <canvas id="ele-canvas"></canvas>
          <div class="ele-control" style="margin-bottom:2%;">
            <el-button class="btn-outline-dark" @click="removeSignature"> 删除签章</el-button>
            <el-button class="btn-outline-dark" @click="clearSignature"> 清除所有签章</el-button>
            <el-button class="btn-outline-dark" @click="submitSignature">提交所有签章信息</el-button>
          </div>
        </el-col>
        <el-col :span="4" style="margin-top:1%;">
          <div class="left-title">任务信息</div>
          <div style="text-align:center;">
            <div>
              <div class="right-item">
                <div class="right-item-title">文件主题</div>
                <div class="detail-item-desc">{{ taskInfo.title }}</div>
              </div>
              <div class="right-item">
                <div class="right-item-title">发起方</div>
                <div class="detail-item-desc">{{ taskInfo.uname }}</div>
              </div>
              <div class="right-item">
                <div class="right-item-title">截止时间</div>
                <div class="detail-item-desc">{{ taskInfo.endtime }}</div>
              </div>
            </div>
          </div>
        </el-col>
      </el-row>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    js部分

    import {fabric} from 'fabric';
    let pdfjsLib =require("pdfjs-dist/legacy/build/pdf.js");
    import workerSrc from "pdfjs-dist/legacy/build/pdf.worker.entry";
    pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;
    import draggable from "vuedraggable";
    export default {
      components: {draggable},
      data() {
        return {
          //pdf预览
          pdfUrl: '',
          pdfDoc: null,
          numPages: 1,
          pageNum: 1,
          scale: 2.2,
          pageRendering: false,
          pageNumPending: null,
          sealUrl: '',
          signUrl: '',
          canvas: null,
          ctx: null,
          canvasEle: null,
          whDatas: null,
          mainImagelist: [],
          taskInfo: {},
        }
      },
      computed: {
          hasSigna() {
            return this.canvasEle && this.canvasEle.getObjects()[0] ? true : false;
          },
      },
      created(){
        var that = this;
        that.mainImagelist = [require('./sign.png'),require('./seal.png')];
        that.taskInfo = {'title':'测试盖章', uname:'张三', endtime:'2021-09-01 17:59:59'};
      },
      methods: {
        //pdf预览
        // zoomIn() {
        //   console.log("缩小");
        //   if(this.scale<=0.5){
        //     this.$message.error("已经显示最小比例")
        //   }else{
        //     this.scale-=0.1;
        //     this.percentage-=0.1;
        //     this.renderPage(this.pageNum);
        //     this.renderFabric();
        //   }
        // },
        // zoomOut() {
        //   console.log("放大")
        //   if(this.scale>=2.2){
        //     this.$message.error('已经显示最大比例')
        //   }else{
        //     this.scale+=0.1;
        //     this.percentage+=0.1;
        //     this.renderPage(this.pageNum);
        //     this.renderFabric();
        //   }
        // },
        renderPage(num) {
          let _this = this;
          this.pageRendering = true;
          return this.pdfDoc.getPage(num).then((page) => {
            let viewport = page.getViewport({ scale: _this.scale });//设置视口大小
            _this.canvas.height = viewport.height;
            _this.canvas.width = viewport.width;
            
            // Render PDF page into canvas context
            let renderContext = {
              canvasContext: _this.ctx,
              viewport: viewport,
            };
            let renderTask = page.render(renderContext);
            // Wait for rendering to finish
            renderTask.promise.then(() => {
              _this.pageRendering = false;
              if (_this.pageNumPending !== null) {
                // New page rendering is pending
                this.renderPage(_this.pageNumPending);
                _this.pageNumPending = null;
              }
            });
          });
        },
        queueRenderPage(num) {
          if (this.pageRendering) {
            this.pageNumPending = num;
          } else {
            this.renderPage(num);
          }
        },
        prevPage() {
          this.confirmSignature();
          if (this.pageNum <= 1) {
            return;
          }
          this.pageNum--;
        },
        nextPage() {
          this.confirmSignature();
          if (this.pageNum >= this.numPages) {
            return;
          }
          this.pageNum++;
        },
        cutover() {
          this.confirmSignature();
        },
        //渲染pdf,到时还会盖章信息,在渲染时,同时显示出来,不应该在切换页码时才显示印章信息
        showpdf(pdfUrl) {
          let caches = JSON.parse(localStorage.getItem('signs')); //获取缓存字符串后转换为对象
          console.log(caches);
          if(caches == null) return false;
          let datas = caches[this.pageNum];
          if(datas != null && datas != undefined) {
            for (let index in datas) {
              this.addSeal(datas[index].sealUrl, datas[index].left, datas[index].top, datas[index].index);
            }
          }
          this.canvas = document.getElementById("the-canvas");
          this.ctx = this.canvas.getContext("2d");
          pdfjsLib.getDocument({url:pdfUrl, rangeChunkSize:65536, disableAutoFetch:false}).promise.then((pdfDoc_) => {
            this.pdfDoc = pdfDoc_;
            this.numPages = this.pdfDoc.numPages;
            this.renderPage(this.pageNum).then(() => {
              this.renderPdf({
                width: this.canvas.width,
                height: this.canvas.height,
              });
            });
            this.commonSign(this.pageNum, true);
          });
        },
        /**
       *  盖章部分开始
       */
        // 设置绘图区域宽高
        renderPdf(data) {
          this.whDatas = data;
          // document.querySelector("#elesign").style.width = data.width + "px";
        },
        // 生成绘图区域
        renderFabric() {
          let canvaEle = document.querySelector("#ele-canvas");
          let pCenter=document.querySelector(".pCenter");
          canvaEle.width = pCenter.clientWidth;
          // canvaEle.height = (this.whDatas.height)*(this.scale);
          canvaEle.height = this.whDatas.height;
    
          this.canvasEle = new fabric.Canvas(canvaEle);
          let container = document.querySelector(".canvas-container");
          container.style.position = "absolute";
          container.style.top = "50px";
          // container.style.left = "30%";
        },
        // 相关事件操作哟
        canvasEvents() {
          // 拖拽边界 不能将图片拖拽到绘图区域外
          this.canvasEle.on("object:moving", function (e) {
            var obj = e.target;
            // if object is too big ignore
            if(obj.currentHeight > obj.canvas.height || obj.currentWidth > obj.canvas.width){
              return;
            }
            obj.setCoords();
            // top-left  corner
            if(obj.getBoundingRect().top < 0 || obj.getBoundingRect().left < 0){
              obj.top = Math.max(obj.top, obj.top-obj.getBoundingRect().top);
              obj.left = Math.max(obj.left, obj.left-obj.getBoundingRect().left);
            }
            // bot-right corner
            if(obj.getBoundingRect().top+obj.getBoundingRect().height  > obj.canvas.height || obj.getBoundingRect().left+obj.getBoundingRect().width  > obj.canvas.width){
              obj.top = Math.min(obj.top, obj.canvas.height-obj.getBoundingRect().height+obj.top-obj.getBoundingRect().top);
              obj.left = Math.min(obj.left, obj.canvas.width-obj.getBoundingRect().width+obj.left-obj.getBoundingRect().left);
            }
          });
        },
        // 添加公章
        addSeal(sealUrl, left, top, index) {
          fabric.Image.fromURL(
            sealUrl,
            (oImg) => {
              oImg.set({
                left: left,
                top: top,
                // angle: 10,
                scaleX: 0.8,
                scaleY: 0.8,
                index:index,
              });
                // oImg.scale(0.5); //图片缩小一
              this.canvasEle.add(oImg);
            }
          );
        },
        // 删除签章
        removeSignature() {
          this.canvasEle.remove(this.canvasEle.getActiveObject())
        },
        //翻页展示盖章信息
        commonSign(pageNum, isFirst = false) {
          if(isFirst == false) this.canvasEle.remove(this.canvasEle.clear()); //清空页面所有签章
          let caches = JSON.parse(localStorage.getItem('signs')); //获取缓存字符串后转换为对象
          console.log(caches);
          if(caches == null) return false;
          let datas = caches[this.pageNum];
          if(datas != null && datas != undefined) {
            for (let index in datas) {
              this.addSeal(datas[index].sealUrl, datas[index].left, datas[index].top, datas[index].index);
            }
          }
        },
        //确认签章位置并保存到缓存
        confirmSignature() {
          let data = this.canvasEle.getObjects(); //获取当前页面内的所有签章信息
          let caches = JSON.parse(localStorage.getItem('signs')); //获取缓存字符串后转换为对象
    
          let signDatas = {}; //存储当前页的所有签章信息
          let i = 0;
          // let sealUrl = '';
          for(var val of data) {
            signDatas[i] =  {
              width: val.width,
              height: val.height,
              top: val.top,
              left: val.left,
              angle: val.angle,
              translateX: val.translateX,
              translateY: val.translateY,
              scaleX: val.scaleX,
              scaleY: val.scaleY,
              pageNum: this.pageNum,
              sealUrl: this.mainImagelist[val.index],
              index:val.index
            }
            i++;
          }
          if(caches == null) {
              caches = {};
              caches[this.pageNum] = signDatas;
          } else {
              caches[this.pageNum] = signDatas;
          }
          localStorage.setItem('signs', JSON.stringify(caches)); //对象转字符串后存储到缓存
        },
        //提交数据
        submitSignature() {
            this.confirmSignature();
            let caches = localStorage.getItem('signs');
            console.log(JSON.parse(caches));
            return false
        },
        //清空数据
        clearSignature() {
          this.canvasEle.remove(this.canvasEle.clear()); //清空页面所有签章
          localStorage.removeItem('signs'); //清除缓存
        },
        end(e){
       this.addSeal(this.mainImagelist[e.newDraggableIndex], e.originalEvent.layerX, e.originalEvent.layerY, e.newDraggableIndex)
        },
        //设置PDF预览区域高度
        setPdfArea(){
           this.pdfUrl = 'https://www.gjtool.cn/pdfh5/git.pdf';
           this.pdfurl=res.data.data.pdfurl;
           this.$nextTick(() => {
             this.showpdf(this.pdfUrl);//接口返回的应该还有盖章信息,不只是pdf
           });
        },
      },
      watch: {
        whDatas: {
          handler() {
            const loading = this.$loading({
              lock: true,
              text: 'Loading',
              spinner: 'el-icon-loading',
              background: 'rgba(0, 0, 0, 0.7)'
            });
            if (this.whDatas) {
              console.log(this.whDatas)
              loading.close();
              this.renderFabric();
              this.canvasEvents();
              let eleCanvas=document.querySelector("#ele-canvas");
              eleCanvas.style="border:1px solid #5ea6ef";
            }
          },
        },
        pageNum: function() {
          this.commonSign(this.pageNum);
          this.queueRenderPage(this.pageNum);
        }
      }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296

    css部分

    <style scoped>
    
    /*pdf部分*/
    
    .pCenter{
      overflow-x: hidden;
    }
    #the-canvas{
      margin-top:10px;
    }
    
    html:fullscreen {
        background: white;
    }
    .elesign {
        display: flex;
        flex: 1;
        flex-direction: column;
        position: relative;
        /* padding-left: 180px; */
        margin: auto;
        /* width:600px; */
    }
    .page {
        text-align:center;
        margin:0 auto;
        margin-top: 1%;
    }
    #ele-canvas {
        /* border: 1px solid #5ea6ef; */
        overflow: hidden;
    }
    .ele-control {
        text-align: center;
        margin-top: 3%;
    }
    #page-input {
        width: 7%;
    }
    
    @keyframes ani-demo-spin {
        from { transform: rotate(0deg);}
        50% { transform: rotate(180deg);}
        to { transform: rotate(360deg);}
    }
    /* .loadingclass{
        position: absolute;
        top:30%;
        left:49%;
        z-index: 99;
    } */
    .left {
        position: absolute;
        top: 42px;
        left: -5px;
        padding: 5px 5px;
        /*border: 1px solid #eee;*/
        /*border-radius: 4px;*/
    }
    .left-title {
        text-align:center;
        padding-bottom: 10px;
        border-bottom: 1px solid #eee;
    }
    li {
        list-style-type:none;
        padding: 10px;
    }
    .imgstyle{
        vertical-align: middle;
        width: 130px;
        border: solid 1px #e8eef2;
        background-image: url("tuo.png");
        background-repeat:no-repeat;
    }
    .right {
        position: absolute;
        top: 7px;
        right: -177px;
        margin-top: 34px;
        padding-top: 10px;
        padding-bottom: 20px;
        width: 152px;
        /*border: 1px solid #eee;*/
        /*border-radius: 4px;*/
    }
    .right-item {
        margin-bottom: 15px;
        margin-left: 10px;
    }
    .right-item-title {
        color: #777;
        height: 20px;
        line-height: 20px;
        font-size: 12px;
        font-weight: 400;
        text-align: left !important;
    }
    .detail-item-desc {
        color: #333;
        line-height: 20px;
        width: 100%;
        font-size: 12px;
        display: inline-block;
        text-align: left;
    }
    .btn-outline-dark {
        color: #0f1531;
        background-color: transparent;
        background-image: none;
        border:1px solid #3e4b5b;
    }
    
    .btn-outline-dark:hover {
        color: #fff;
        background-color: #3e4b5b;
        border-color: #3e4b5b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118

    2022.9.13修改
    使用的时候,发现在pdf第一页添加的印章,下次再打开时,不在显示,本地缓存的也是显示{},所以琢磨了下,应该是每次打开pdf页面重置了,代码做了以下修改

    在这里插入图片描述
    将选中部分改为以下代码
    在这里插入图片描述

  • 相关阅读:
    git查询和设置用户名及邮箱
    Bean 管理(工厂bean)
    407. 接雨水 II
    8.1 Spring知识点——从Spring配置文件讲起到Spring和SpringBoot的yaml和properities配置文件的区别
    Python中转换IP地址格式的方法
    如何将自己做好的服务进行容器化部署
    [Java SDK] [多线程] Java中线程的定制化通信
    VBA调用宏的方式总结大全
    Seal库官方示例(五):ckks_basics.cpp解析
    SpringCloud 从入门到入土
  • 原文地址:https://blog.csdn.net/blue__k/article/details/126723437