askbot-dragon 1.8.34-beta → 1.8.36-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "askbot-dragon",
3
- "version": "1.8.34-beta",
3
+ "version": "1.8.36-beta",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "build": "vue-cli-service build",
@@ -256,6 +256,36 @@ function newInitWaterMark(elId, textValue) {
256
256
  })
257
257
  document.getElementById(elId).appendChild(oTemp);
258
258
  }
259
+ const getAllParams = (href) => {
260
+ let query = href.substring(href.indexOf("?") + 1);
261
+ let vars = query.split("&");
262
+ let obj = {};
263
+ for (let i = 0; i < vars.length; i++) {
264
+ let pair = vars[i].split("=");
265
+ // 将参数名和参数值分别作为对象的属性名和属性值
266
+ obj[pair[0]] = pair[1];
267
+ }
268
+ return obj;
269
+ }
270
+ export const setTimestamp = (url) => {
271
+ if(url.indexOf('?') !== -1) {
272
+ let newUrl = url.split('?')[0];
273
+ let params = getAllParams(url)
274
+ params['timestamp'] = new Date().getTime();
275
+ let count = 0;
276
+ for(let key in params) {
277
+ if(count === 0) {
278
+ newUrl += '?' + key + '=' + params[key];
279
+ } else {
280
+ newUrl += '&' + key + '=' + params[key];
281
+ }
282
+ count++;
283
+ }
284
+ return newUrl;
285
+ } else {
286
+ return url
287
+ }
288
+ }
259
289
  export {
260
290
  imageTypeObj,
261
291
  newInitWaterMark
@@ -81,6 +81,7 @@
81
81
  <!-- <div v-for="(item,index) in processAction" :key="index">
82
82
  <association-intention :msg="item" :msgType="item.type" :isOpen="isOpen"></association-intention>
83
83
  </div> -->
84
+ <pdf-view :split_paragraphs="splitParagraph" :ossPath="ossPath" :isPC="true" ></pdf-view>
84
85
  </div>
85
86
  </template>
86
87
  <script>
@@ -122,9 +123,11 @@ import WelcomeKnowledgeFile from "./welcomeKnowledgeFile";
122
123
  import WelcomeLlmCard from "./welcomeLlmCard";
123
124
  import welcomeSuggest from "./welcomeSuggest"
124
125
  import QwFeedback from './QwFeedback';
126
+ import PdfView from "./preview/pdfView";
125
127
  export default {
126
128
  name: 'ConversationContainer',
127
129
  components: {
130
+ PdfView,
128
131
  WelcomeLlmCard,
129
132
  WelcomeKnowledgeFile,
130
133
  // ActionAlert,
@@ -159,6 +162,572 @@ export default {
159
162
  },
160
163
  data() {
161
164
  return {
165
+ splitParagraph:[{
166
+ "paragraph": "AI 赋能累积超过 3000 家企业和组织  企业为什么要用 AI? 不用 AI,你正在被同行淘汰 AI 客服 东莞某制造业企业 用了 AI 客服。客户响 应时间从 30 分钟,减 AI 询盘 义乌贸易公司,用 AI 询盘,自动翻译产品 AI 质检 某头部物业管理集 团,用 AI 检查晨会是 否达标,规范。 少到 10 秒。订单转化 率提升了 30%。 客服人员从 3 人减少 到 1 个。 描述,海外询盘量增 加 50% 节省 300 万/年管理费 用。 不用 AI 的风险 人工成本高 人工客服 5000 月 薪,6 万年薪。 AI 客服,成本不超过 1 万一年。 效率跟不上 人工,一周 1 个招商 方案,还不满意。 AI,一周 6 个方案, 随便选。 错失机会 秒回复 客户早跑了 企业 AI 落地怎么做? 企业AI落地",
167
+ "edit_paragraph": null,
168
+ "original_paragraph": [
169
+ {
170
+ "text": "AI 赋能累积超过 3000 家企业和组织",
171
+ "title": {
172
+ "number": "35",
173
+ "level": 1,
174
+ "text": "AI 赋能累积超过 3000 家企业和组织"
175
+ },
176
+ "paragraph_id": "",
177
+ "images": [],
178
+ "page": 1,
179
+ "position": [
180
+ "91.5",
181
+ "419.37396240234375",
182
+ "318.358154296875",
183
+ "433.3689880371094"
184
+ ]
185
+ },
186
+ {
187
+ "text": "",
188
+ "title": null,
189
+ "paragraph_id": "",
190
+ "images": [
191
+ {
192
+ "id": "65",
193
+ "oss_image_url": "https://guoranwisdom.oss-cn-zhangjiakou.aliyuncs.com/ab0f90737c8b4f2d85ba2157e4473110/2025/12/25/10/53/24/694ca7050229e8779290cadf/page-1-image-65.png",
194
+ "ocr_image_text": null,
195
+ "is_deleted": null,
196
+ "position": null,
197
+ "page": 1
198
+ }
199
+ ],
200
+ "page": 1,
201
+ "position": [
202
+ "380.484375",
203
+ "359.2138977050781",
204
+ "535.1282958984375",
205
+ "371.2138977050781"
206
+ ]
207
+ },
208
+ {
209
+ "text": "企业为什么要用 AI?",
210
+ "title": null,
211
+ "paragraph_id": "",
212
+ "images": [],
213
+ "page": 1,
214
+ "position": [
215
+ "131.90625",
216
+ "531.6300048828125",
217
+ "463.5747985839844",
218
+ "567.6300048828125"
219
+ ]
220
+ },
221
+ {
222
+ "text": "不用 AI,你正在被同行淘汰",
223
+ "title": null,
224
+ "paragraph_id": "",
225
+ "images": [],
226
+ "page": 1,
227
+ "position": [
228
+ "187.828125",
229
+ "656.1900024414062",
230
+ "407.6615295410156",
231
+ "674.1900024414062"
232
+ ]
233
+ },
234
+ {
235
+ "text": "AI 客服",
236
+ "title": null,
237
+ "paragraph_id": "",
238
+ "images": [],
239
+ "page": 1,
240
+ "position": [
241
+ "109.7578125",
242
+ "710.3739624023438",
243
+ "154.717529296875",
244
+ "724.3689575195312"
245
+ ]
246
+ },
247
+ {
248
+ "text": "东莞某制造业企业",
249
+ "title": null,
250
+ "paragraph_id": "",
251
+ "images": [],
252
+ "page": 1,
253
+ "position": [
254
+ "63.0",
255
+ "735.1239624023438",
256
+ "174.9403076171875",
257
+ "749.1189575195312"
258
+ ]
259
+ },
260
+ {
261
+ "text": "用了 AI 客服。客户响",
262
+ "title": null,
263
+ "paragraph_id": "",
264
+ "images": [],
265
+ "page": 1,
266
+ "position": [
267
+ "63.0",
268
+ "759.8739624023438",
269
+ "194.99111938476562",
270
+ "773.8689575195312"
271
+ ]
272
+ },
273
+ {
274
+ "text": "应时间从 30 分钟,减",
275
+ "title": null,
276
+ "paragraph_id": "",
277
+ "images": [],
278
+ "page": 1,
279
+ "position": [
280
+ "63.0",
281
+ "782.3739624023438",
282
+ "199.00686645507812",
283
+ "796.3689575195312"
284
+ ]
285
+ },
286
+ {
287
+ "text": "AI 询盘",
288
+ "title": null,
289
+ "paragraph_id": "",
290
+ "images": [],
291
+ "page": 1,
292
+ "position": [
293
+ "275.25",
294
+ "710.3739624023438",
295
+ "320.209716796875",
296
+ "724.3689575195312"
297
+ ]
298
+ },
299
+ {
300
+ "text": "义乌贸易公司,用 AI",
301
+ "title": null,
302
+ "paragraph_id": "",
303
+ "images": [],
304
+ "page": 1,
305
+ "position": [
306
+ "228.4921875",
307
+ "735.1239624023438",
308
+ "360.4811096191406",
309
+ "749.1189575195312"
310
+ ]
311
+ },
312
+ {
313
+ "text": "询盘,自动翻译产品",
314
+ "title": null,
315
+ "paragraph_id": "",
316
+ "images": [],
317
+ "page": 1,
318
+ "position": [
319
+ "228.4921875",
320
+ "757.6239624023438",
321
+ "354.4246826171875",
322
+ "771.6189575195312"
323
+ ]
324
+ },
325
+ {
326
+ "text": "AI 质检",
327
+ "title": null,
328
+ "paragraph_id": "",
329
+ "images": [],
330
+ "page": 1,
331
+ "position": [
332
+ "440.7421875",
333
+ "710.3739624023438",
334
+ "485.701904296875",
335
+ "724.3689575195312"
336
+ ]
337
+ },
338
+ {
339
+ "text": "某头部物业管理集",
340
+ "title": null,
341
+ "paragraph_id": "",
342
+ "images": [],
343
+ "page": 1,
344
+ "position": [
345
+ "393.984375",
346
+ "735.1239624023438",
347
+ "505.9246826171875",
348
+ "749.1189575195312"
349
+ ]
350
+ },
351
+ {
352
+ "text": "团,用 AI 检查晨会是",
353
+ "title": null,
354
+ "paragraph_id": "",
355
+ "images": [],
356
+ "page": 1,
357
+ "position": [
358
+ "393.984375",
359
+ "757.6239624023438",
360
+ "525.9755249023438",
361
+ "771.6189575195312"
362
+ ]
363
+ },
364
+ {
365
+ "text": "否达标,规范。",
366
+ "title": null,
367
+ "paragraph_id": "",
368
+ "images": [],
369
+ "page": 1,
370
+ "position": [
371
+ "393.984375",
372
+ "780.8739624023438",
373
+ "491.9324951171875",
374
+ "794.8689575195312"
375
+ ]
376
+ },
377
+ {
378
+ "text": "少到 10 秒。订单转化",
379
+ "title": null,
380
+ "paragraph_id": "",
381
+ "images": [],
382
+ "page": 2,
383
+ "position": [
384
+ "63.0",
385
+ "40.62397766113281",
386
+ "199.00686645507812",
387
+ "54.61897659301758"
388
+ ]
389
+ },
390
+ {
391
+ "text": "率提升了 30%。",
392
+ "title": null,
393
+ "paragraph_id": "",
394
+ "images": [],
395
+ "page": 2,
396
+ "position": [
397
+ "63.0",
398
+ "63.12397766113281",
399
+ "166.7548828125",
400
+ "77.11897277832031"
401
+ ]
402
+ },
403
+ {
404
+ "text": "客服人员从 3 人减少",
405
+ "title": null,
406
+ "paragraph_id": "",
407
+ "images": [],
408
+ "page": 2,
409
+ "position": [
410
+ "63.0",
411
+ "87.87397766113281",
412
+ "190.05186462402344",
413
+ "101.86897277832031"
414
+ ]
415
+ },
416
+ {
417
+ "text": "到 1 个。",
418
+ "title": null,
419
+ "paragraph_id": "",
420
+ "images": [],
421
+ "page": 2,
422
+ "position": [
423
+ "63.0",
424
+ "111.12397766113281",
425
+ "120.09093475341797",
426
+ "125.11897277832031"
427
+ ]
428
+ },
429
+ {
430
+ "text": "描述,海外询盘量增",
431
+ "title": null,
432
+ "paragraph_id": "",
433
+ "images": [],
434
+ "page": 2,
435
+ "position": [
436
+ "228.4921875",
437
+ "40.62397766113281",
438
+ "354.4246826171875",
439
+ "54.61897659301758"
440
+ ]
441
+ },
442
+ {
443
+ "text": "加 50%",
444
+ "title": null,
445
+ "paragraph_id": "",
446
+ "images": [],
447
+ "page": 2,
448
+ "position": [
449
+ "228.4921875",
450
+ "63.12397766113281",
451
+ "276.278076171875",
452
+ "77.11897277832031"
453
+ ]
454
+ },
455
+ {
456
+ "text": "节省 300 万/年管理费",
457
+ "title": null,
458
+ "paragraph_id": "",
459
+ "images": [],
460
+ "page": 2,
461
+ "position": [
462
+ "393.984375",
463
+ "40.62397766113281",
464
+ "530.6068725585938",
465
+ "54.61897659301758"
466
+ ]
467
+ },
468
+ {
469
+ "text": "用。",
470
+ "title": null,
471
+ "paragraph_id": "",
472
+ "images": [],
473
+ "page": 2,
474
+ "position": [
475
+ "393.984375",
476
+ "63.12397766113281",
477
+ "421.9715576171875",
478
+ "77.11897277832031"
479
+ ]
480
+ },
481
+ {
482
+ "text": "不用 AI 的风险",
483
+ "title": null,
484
+ "paragraph_id": "",
485
+ "images": [],
486
+ "page": 2,
487
+ "position": [
488
+ "239.84765625",
489
+ "191.19000244140625",
490
+ "355.641357421875",
491
+ "209.19000244140625"
492
+ ]
493
+ },
494
+ {
495
+ "text": "人工成本高",
496
+ "title": null,
497
+ "paragraph_id": "",
498
+ "images": [],
499
+ "page": 2,
500
+ "position": [
501
+ "97.265625",
502
+ "245.3739776611328",
503
+ "167.2293701171875",
504
+ "259.3689880371094"
505
+ ]
506
+ },
507
+ {
508
+ "text": "人工客服 5000 月",
509
+ "title": null,
510
+ "paragraph_id": "",
511
+ "images": [],
512
+ "page": 2,
513
+ "position": [
514
+ "63.0",
515
+ "270.12396240234375",
516
+ "174.9403076171875",
517
+ "284.1189880371094"
518
+ ]
519
+ },
520
+ {
521
+ "text": "薪,6 万年薪。",
522
+ "title": null,
523
+ "paragraph_id": "",
524
+ "images": [],
525
+ "page": 2,
526
+ "position": [
527
+ "63.0",
528
+ "292.62396240234375",
529
+ "158.9892120361328",
530
+ "306.6189880371094"
531
+ ]
532
+ },
533
+ {
534
+ "text": "AI 客服,成本不超过",
535
+ "title": null,
536
+ "paragraph_id": "",
537
+ "images": [],
538
+ "page": 2,
539
+ "position": [
540
+ "63.0",
541
+ "317.37396240234375",
542
+ "194.9889373779297",
543
+ "331.3689880371094"
544
+ ]
545
+ },
546
+ {
547
+ "text": "1 万一年。",
548
+ "title": {
549
+ "number": "35.1",
550
+ "level": 2,
551
+ "text": "1 万一年。"
552
+ },
553
+ "paragraph_id": "",
554
+ "images": [],
555
+ "page": 2,
556
+ "position": [
557
+ "63.0",
558
+ "340.62396240234375",
559
+ "131.0048370361328",
560
+ "354.6189880371094"
561
+ ]
562
+ },
563
+ {
564
+ "text": "效率跟不上",
565
+ "title": null,
566
+ "paragraph_id": "",
567
+ "images": [],
568
+ "page": 2,
569
+ "position": [
570
+ "262.7578125",
571
+ "245.3739776611328",
572
+ "332.7215576171875",
573
+ "259.3689880371094"
574
+ ]
575
+ },
576
+ {
577
+ "text": "人工,一周 1 个招商",
578
+ "title": null,
579
+ "paragraph_id": "",
580
+ "images": [],
581
+ "page": 2,
582
+ "position": [
583
+ "228.4921875",
584
+ "270.12396240234375",
585
+ "355.5440673828125",
586
+ "284.1189880371094"
587
+ ]
588
+ },
589
+ {
590
+ "text": "方案,还不满意。",
591
+ "title": null,
592
+ "paragraph_id": "",
593
+ "images": [],
594
+ "page": 2,
595
+ "position": [
596
+ "228.4921875",
597
+ "292.62396240234375",
598
+ "340.4324951171875",
599
+ "306.6189880371094"
600
+ ]
601
+ },
602
+ {
603
+ "text": "AI,一周 6 个方案,",
604
+ "title": {
605
+ "number": "35.1.1",
606
+ "level": 3,
607
+ "text": "AI,一周 6 个方案,"
608
+ },
609
+ "paragraph_id": "",
610
+ "images": [],
611
+ "page": 2,
612
+ "position": [
613
+ "228.4921875",
614
+ "317.37396240234375",
615
+ "355.4461364746094",
616
+ "331.3689880371094"
617
+ ]
618
+ },
619
+ {
620
+ "text": "随便选。",
621
+ "title": null,
622
+ "paragraph_id": "",
623
+ "images": [],
624
+ "page": 2,
625
+ "position": [
626
+ "228.4921875",
627
+ "340.62396240234375",
628
+ "284.4637451171875",
629
+ "354.6189880371094"
630
+ ]
631
+ },
632
+ {
633
+ "text": "错失机会",
634
+ "title": null,
635
+ "paragraph_id": "",
636
+ "images": [],
637
+ "page": 2,
638
+ "position": [
639
+ "435.24609375",
640
+ "245.3739776611328",
641
+ "491.2176513671875",
642
+ "259.3689880371094"
643
+ ]
644
+ },
645
+ {
646
+ "text": "秒回复",
647
+ "title": null,
648
+ "paragraph_id": "",
649
+ "images": [],
650
+ "page": 2,
651
+ "position": [
652
+ "393.984375",
653
+ "292.62396240234375",
654
+ "435.9637451171875",
655
+ "306.6189880371094"
656
+ ]
657
+ },
658
+ {
659
+ "text": "客户早跑了",
660
+ "title": null,
661
+ "paragraph_id": "",
662
+ "images": [],
663
+ "page": 2,
664
+ "position": [
665
+ "393.984375",
666
+ "317.37396240234375",
667
+ "463.9481201171875",
668
+ "331.3689880371094"
669
+ ]
670
+ },
671
+ {
672
+ "text": "企业 AI 落地怎么做?",
673
+ "title": null,
674
+ "paragraph_id": "",
675
+ "images": [],
676
+ "page": 2,
677
+ "position": [
678
+ "127.9453125",
679
+ "446.1300048828125",
680
+ "467.5339050292969",
681
+ "482.1300048828125"
682
+ ]
683
+ },
684
+ {
685
+ "text": "企业AI落地",
686
+ "title": null,
687
+ "paragraph_id": "",
688
+ "images": [
689
+ {
690
+ "id": "152",
691
+ "oss_image_url": "https://guoranwisdom.oss-cn-zhangjiakou.aliyuncs.com/ab0f90737c8b4f2d85ba2157e4473110/2025/12/25/10/53/25/694ca7050229e8779290cadf/page-2-image-152.png",
692
+ "ocr_image_text": null,
693
+ "is_deleted": null,
694
+ "position": null,
695
+ "page": 2
696
+ }
697
+ ],
698
+ "page": 2,
699
+ "position": [
700
+ "153.8671875",
701
+ "563.7802124023438",
702
+ "333.6154479980469",
703
+ "600.1043090820312"
704
+ ]
705
+ }
706
+ ],
707
+ "images": [
708
+ {
709
+ "id": "65",
710
+ "oss_image_url": "https://guoranwisdom.oss-cn-zhangjiakou.aliyuncs.com/ab0f90737c8b4f2d85ba2157e4473110/2025/12/25/10/53/24/694ca7050229e8779290cadf/page-1-image-65.png",
711
+ "ocr_image_text": null,
712
+ "is_deleted": null,
713
+ "position": null,
714
+ "page": 1
715
+ },
716
+ {
717
+ "id": "152",
718
+ "oss_image_url": "https://guoranwisdom.oss-cn-zhangjiakou.aliyuncs.com/ab0f90737c8b4f2d85ba2157e4473110/2025/12/25/10/53/25/694ca7050229e8779290cadf/page-2-image-152.png",
719
+ "ocr_image_text": null,
720
+ "is_deleted": null,
721
+ "position": null,
722
+ "page": 2
723
+ }
724
+ ],
725
+ "html": null,
726
+ "html_result": null,
727
+ "page": null,
728
+ "paragraph_id": "7f3c8b9d-ab14-40e1-8975-b021447d3696"
729
+ }],
730
+ ossPath:"https://guoranwisdom.oss-cn-zhangjiakou.aliyuncs.com/ab0f90737c8b4f2d85ba2157e4473110/2025/12/25/10/52/de1dc26afbf782f49858056888d77db3/ede1dc26afbf782f.pdf?Expires=1766643431&OSSAccessKeyId=LTAI4Fr7hD1XCFb5zMNjMcGy&Signature=lzG%2BkN2WCAcG1UbZITWECiQSLng%3D",
162
731
  black: '',
163
732
  welcomeSuggest: {
164
733
  content: {
@@ -78,7 +78,7 @@ if(pdfjsLib) {
78
78
  pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
79
79
  }
80
80
  const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
81
- import { newInitWaterMark } from "../../assets/js/common.js";
81
+ import { newInitWaterMark,setTimestamp } from "../../assets/js/common.js";
82
82
  import Vue from 'vue';
83
83
  export default {
84
84
  name: "PdfViewer",
@@ -164,6 +164,7 @@ export default {
164
164
  },
165
165
  async initPdf() {
166
166
  if (!this.pdfFile) return;
167
+ this.pdfFile = setTimestamp(this.pdfFile)
167
168
  // this.pdf = await pdfjsLib.getDocument(this.pdfFile).promise;
168
169
  this.loadingTask = pdfjsLib.getDocument(this.pdfFile);
169
170
  await this.loadingTask.promise.then(async pdf => {
@@ -183,16 +184,23 @@ export default {
183
184
  this.searchHighlights = [];
184
185
  this.searchTermCount = 0;
185
186
  this.currentSearchIndex = 0;
186
- setTimeout(async () => {
187
- await this.setCanvasRef();
188
- },100)
187
+ // 确保 DOM 更新完成后再设置 canvas 引用
188
+ await this.$nextTick();
189
+ await this.setCanvasRef();
190
+ }).catch(error => {
191
+ console.error('PDF 加载失败:', error);
189
192
  })
190
193
 
191
194
  },
192
195
  async loadPdf() {
193
196
  if (!this.pdfFile) return;
194
197
  await this.initPdf();
195
- this.initObserver();
198
+ // 确保 canvas 引用设置完成后再初始化观察器
199
+ await this.$nextTick();
200
+ // 延迟初始化观察器,确保所有 canvas 都已准备好
201
+ setTimeout(() => {
202
+ this.initObserver();
203
+ }, 200);
196
204
  },
197
205
  initObserver(type) {
198
206
  if (this.observer) {
@@ -204,8 +212,8 @@ export default {
204
212
  if (entry.isIntersecting) {
205
213
  const index = Number(entry.target.getAttribute('data-index'));
206
214
  const page = this.pages[index];
207
- if (!page.loaded && !page.loading) {
208
- this.renderPage(page.pageNumber);
215
+ if (page && !page.loaded && !page.loading) {
216
+ this.renderPage(page.pageNumber);
209
217
  }
210
218
  this.updateCurrentPage();
211
219
  }
@@ -217,7 +225,9 @@ export default {
217
225
  threshold: 0.1,
218
226
  }
219
227
  );
220
- this.$nextTick( () => {
228
+ // 确保 canvas 引用都已设置好后再开始观察
229
+ this.$nextTick(() => {
230
+ // 增加延迟确保所有 canvas 引用都已设置
221
231
  setTimeout(() => {
222
232
  this.pages.forEach((page, index) => {
223
233
  const canvas = page.canvas;
@@ -226,7 +236,7 @@ export default {
226
236
  this.observer.observe(canvas);
227
237
  }
228
238
  });
229
- },300)
239
+ },500)
230
240
  if (type !== 'changeScale' && type !== 'onResize'){
231
241
  setTimeout(async () => {
232
242
  let currentPage = this.split_paragraphs.length > 0 ? this.split_paragraphs[0] : null;
@@ -250,78 +260,160 @@ export default {
250
260
  }
251
261
  },
252
262
  async renderPage(pageNumber) {
253
- if (!this.pdf || this.renderInProgress) return;
263
+ if (!this.pdf) return;
254
264
  const pageIndex = pageNumber - 1;
255
265
  const pageData = this.pages[pageIndex];
256
- if (pageData.loaded) return;
266
+ if (!pageData) return;
267
+ // 如果已经在加载或已加载,避免重复渲染
268
+ if (pageData.loaded || pageData.loading) return;
269
+
257
270
  this.pageNumber = pageNumber;
258
- const page = await this.pdf.getPage(pageNumber);
259
- let pdfWidth = page.getViewport({ scale: 1}).width
260
- const viewport = page.getViewport({ scale: this.calculateScale(pdfWidth) });
261
- this.viewport = viewport;
262
- const canvas = pageData.canvas;
263
- if (!canvas) return;
264
-
265
- const context = canvas.getContext("2d");
266
- this.context = context;
267
- const devicePixelRatio = window.devicePixelRatio || 1;
268
- canvas.width = (viewport.width) * devicePixelRatio;
269
- canvas.height = viewport.height * devicePixelRatio;
270
- canvas.style.width = `${viewport.width}px`;
271
- canvas.style.height = `${viewport.height}px`;
272
- context.scale(devicePixelRatio, devicePixelRatio);
273
-
274
- this.$set(pageData,'loading',true)
275
- this.renderInProgress = true;
276
- const renderTask = page.render({ canvasContext: context, viewport });
277
- // await renderTask.promise;
278
- let hasDoc = document.getElementById('textLayer' + pageNumber)
279
- if (hasDoc){
280
- hasDoc.parentNode.removeChild(hasDoc);
281
- // await renderTask.promise;
282
- // return
283
- }
284
- await renderTask.promise.then(() => {
285
- return page.getTextContent()
286
- }).then((textContent) => {
287
- const textDiv = document.createElement('div');
288
- textDiv.setAttribute('class', 'textLayer');
289
- textDiv.setAttribute('id', 'textLayer' + pageNumber);
290
- let textLayer = new TextLayerBuilder({
291
- textLayerDiv: textDiv,
292
- pageIndex: pageIndex,
271
+
272
+ try {
273
+ // 标记为加载中,防止重复渲染
274
+ this.$set(pageData, 'loading', true);
275
+
276
+ const page = await this.pdf.getPage(pageNumber);
277
+ let pdfWidth = page.getViewport({ scale: 1 }).width;
278
+ const viewport = page.getViewport({ scale: this.calculateScale(pdfWidth) });
279
+ this.viewport = viewport;
280
+
281
+ const canvas = pageData.canvas;
282
+ if (!canvas) {
283
+ console.warn(`页面 ${pageNumber} 的 canvas 引用不存在`);
284
+ this.$set(pageData, 'loading', false);
285
+ return;
286
+ }
287
+
288
+ const context = canvas.getContext("2d");
289
+ if (!context) {
290
+ console.warn(`页面 ${pageNumber} 无法获取 canvas context`);
291
+ this.$set(pageData, 'loading', false);
292
+ return;
293
+ }
294
+
295
+ this.context = context;
296
+
297
+ // 计算输出缩放比例(与 vuePdf 保持一致)
298
+ const outputScale = this.calculateScale(pdfWidth);
299
+
300
+ // 计算实际显示的尺寸
301
+ let domWidth = Math.floor(viewport.width);
302
+ let domHeight = Math.floor(viewport.height);
303
+
304
+ // 设置 canvas 尺寸(与 vuePdf 保持一致,使用 outputScale)
305
+ // 注意:vuePdf 不使用 devicePixelRatio,为了保持一致,我们也只使用 outputScale
306
+ canvas.width = Math.floor(viewport.width * outputScale);
307
+ canvas.height = Math.floor(viewport.height * outputScale);
308
+ canvas.style.width = `${domWidth}px`;
309
+ canvas.style.height = `${domHeight}px`;
310
+
311
+ // 创建 transform 矩阵(与 vuePdf 保持一致)
312
+ const transform = outputScale !== 1
313
+ ? [outputScale, 0, 0, outputScale, 0, 0]
314
+ : null;
315
+
316
+ // 清除旧的文本层
317
+ let hasDoc = document.getElementById('textLayer' + pageNumber);
318
+ if (hasDoc) {
319
+ hasDoc.parentNode.removeChild(hasDoc);
320
+ }
321
+
322
+ // 渲染 PDF 页面到 canvas(传入 transform 确保正确渲染)
323
+ const renderTask = page.render({
324
+ canvasContext: context,
293
325
  viewport: viewport,
326
+ transform: transform
294
327
  });
295
- textDiv.style.width = `${viewport.width}px`; // 根据 viewport 调整宽度
296
- textDiv.style.height = `${viewport.height}px`; // 根据 viewport 调整高度(可能需要根据实际文本内容调整)
297
- textDiv.style.overflow = 'hidden'; // 如果文本内容超出范围,则隐藏它
298
- textDiv.style.whiteSpace = 'pre-wrap'; // 保留空白符和换行符
299
- textDiv.style.position = 'absolute'; // 绝对定位以覆盖 canvas
300
- textDiv.style.top = '0';
301
- textDiv.style.left = '0';
302
- textDiv.style.fontSize = '20px'; // 设置字体大小(可能需要根据实际情况调整)
303
- textDiv.style.color = 'black'; // 设置文本颜色(可能需要根据实际情况调整)
304
- // textDiv.textContent = textContent; // 设置文本内容
305
- textLayer.setTextContent(textContent);
306
- textLayer.render()
307
- // 将文本 div 添加到覆盖层中
308
- let pagesDiv = document.getElementById('canvas-wrapper' + pageIndex);
309
- pagesDiv.appendChild(textDiv)
310
- })
311
- this.renderInProgress = false;
312
- this.$set(pageData,'loading',false)
313
- this.$set(pageData,'loaded',true)
314
-
315
- // 渲染已有高亮区域(静态highlights)
316
- this.renderHighlights(context, pageNumber, viewport);
317
- // 渲染搜索高亮区域
318
- this.renderSearchHighlights(context, pageNumber, viewport);
328
+ await renderTask.promise;
329
+
330
+ // 渲染文本层(必须在高亮渲染之前,确保文本层在最上层)
331
+ try {
332
+ const textContent = await page.getTextContent();
333
+ const textDiv = document.createElement('div');
334
+ textDiv.setAttribute('class', 'textLayer');
335
+ textDiv.setAttribute('id', 'textLayer' + pageNumber);
336
+ // 关键:TextLayerBuilder 也需要传入 transform,确保文本位置正确
337
+ let textLayer = new TextLayerBuilder({
338
+ textLayerDiv: textDiv,
339
+ pageIndex: pageIndex,
340
+ viewport: viewport,
341
+ transform: transform, // 添加 transform 参数
342
+ });
343
+ // 使用 domWidth 和 domHeight(与 vuePdf 保持一致)
344
+ textDiv.style.width = `${domWidth}px`;
345
+ textDiv.style.height = `${domHeight}px`;
346
+ // 使用 hidden 但确保尺寸正确(与 vuePdf 保持一致)
347
+ textDiv.style.overflow = 'hidden';
348
+ textDiv.style.whiteSpace = 'pre-wrap';
349
+ textDiv.style.position = 'absolute';
350
+ textDiv.style.top = '0';
351
+ textDiv.style.left = '0';
352
+ textDiv.style.fontSize = '20px';
353
+ textDiv.style.color = 'black';
354
+ textLayer.setTextContent(textContent);
355
+ textLayer.render();
356
+
357
+ // 渲染完成后,检查文本层实际内容高度,如果超出则调整
358
+ await this.$nextTick();
359
+ const textLayerSpans = textDiv.querySelectorAll('span');
360
+ if (textLayerSpans.length > 0) {
361
+ let maxBottom = 0;
362
+ textLayerSpans.forEach(span => {
363
+ const rect = span.getBoundingClientRect();
364
+ const parentRect = textDiv.getBoundingClientRect();
365
+ const relativeBottom = rect.bottom - parentRect.top;
366
+ if (relativeBottom > maxBottom) {
367
+ maxBottom = relativeBottom;
368
+ }
369
+ });
370
+ // 如果文本内容超出当前高度,增加文本层高度(增加一些边距)
371
+ if (maxBottom > domHeight) {
372
+ textDiv.style.height = `${Math.ceil(maxBottom + 10)}px`;
373
+ }
374
+ }
375
+
376
+ // 将文本 div 添加到覆盖层中
377
+ let pagesDiv = document.getElementById('canvas-wrapper' + pageIndex);
378
+ if (pagesDiv) {
379
+ pagesDiv.appendChild(textDiv);
380
+ }
381
+ } catch (textError) {
382
+ console.warn(`页面 ${pageNumber} 文本层渲染失败:`, textError);
383
+ // 文本层渲染失败不影响页面继续渲染
384
+ }
385
+
386
+ // 渲染已有高亮区域(静态highlights)
387
+ // 注意:高亮是在 canvas 上绘制的,不会覆盖文本层(文本层在 canvas 上方)
388
+ // 需要传入 outputScale,因为 canvas 使用了 transform 渲染
389
+ try {
390
+ this.renderHighlights(context, pageNumber, viewport, outputScale);
391
+ } catch (highlightError) {
392
+ console.warn(`页面 ${pageNumber} 高亮渲染失败:`, highlightError);
393
+ }
394
+
395
+ // 渲染搜索高亮区域
396
+ try {
397
+ this.renderSearchHighlights(context, pageNumber, viewport, outputScale);
398
+ } catch (searchHighlightError) {
399
+ console.warn(`页面 ${pageNumber} 搜索高亮渲染失败:`, searchHighlightError);
400
+ }
401
+
402
+ // 标记为已加载
403
+ this.$set(pageData, 'loading', false);
404
+ this.$set(pageData, 'loaded', true);
405
+ } catch (error) {
406
+ console.error(`页面 ${pageNumber} 渲染失败:`, error);
407
+ // 渲染失败时重置状态,允许重试
408
+ this.$set(pageData, 'loading', false);
409
+ this.$set(pageData, 'loaded', false);
410
+ }
319
411
  },
320
412
  calculateScale(pdfWidth) {
321
413
  const containerWidth = document.getElementById('pdfViewPage').clientWidth - 50;
322
414
  return (containerWidth / pdfWidth) * this.scale;
323
415
  },
324
- async renderHighlights(context, number,viewport) {
416
+ async renderHighlights(context, number, viewport, outputScale = 1) {
325
417
  const pageHighlights = this.highlights.filter(item => (item.page === number ))
326
418
  let highlights = this.mergedGroups(pageHighlights);
327
419
  this.mergedGroupsList = this.mergedGroupsList.concat(highlights)
@@ -335,36 +427,51 @@ export default {
335
427
  groups.push(position.slice(i, i + 4));
336
428
  }
337
429
  for (let i = 0;i<groups.length;i++){
338
- this.drawHighlight(context, viewport, groups[i], fillStyle, false);
430
+ this.drawHighlight(context, viewport, groups[i], fillStyle, false, outputScale);
339
431
  }
340
432
  });
341
433
  }
342
434
  },
343
- renderSearchHighlights(context, pageNumber, viewport) {
435
+ renderSearchHighlights(context, pageNumber, viewport, outputScale = 1) {
344
436
  const pageHighlights = this.searchHighlights.filter(h => h.pageNumber === pageNumber);
345
437
  pageHighlights.forEach(({ position }) => {
346
- this.drawHighlight(context, viewport, position, "rgba(255, 255, 0, 0.4)", true);
438
+ this.drawHighlight(context, viewport, position, "rgba(255, 255, 0, 0.4)", true, outputScale);
347
439
  });
348
440
  },
349
- drawHighlight(context, viewport, position, fillStyle, fromSearch = false) {
441
+ drawHighlight(context, viewport, position, fillStyle, fromSearch = false, outputScale = 1) {
350
442
  const [x1, y1, x2, y2] = position;
443
+ // 使用 viewport.scale 计算 PDF 坐标到 viewport 坐标的转换
351
444
  const scale = viewport.scale;
445
+ // PDF 页面的实际高度(未缩放)
352
446
  const pageHeight = viewport.height / viewport.scale;
353
447
 
354
- let canvasX1 = x1 * scale;
355
- let canvasX2 = x2 * scale;
356
- let canvasY1, canvasY2;
448
+ // 计算在 viewport 坐标系中的位置(PDF 坐标 → viewport 坐标)
449
+ let viewportX1 = x1 * scale;
450
+ let viewportX2 = x2 * scale;
451
+ let viewportY1, viewportY2;
357
452
 
358
453
  if (fromSearch) {
359
- // 搜索高亮:PDF坐标系(左下原点)
360
- canvasY1 = (pageHeight - y1) * scale;
361
- canvasY2 = (pageHeight - y2) * scale;
454
+ // 搜索高亮:PDF坐标系(左下原点),需要转换为顶部原点
455
+ viewportY1 = (pageHeight - y1) * scale;
456
+ viewportY2 = (pageHeight - y2) * scale;
362
457
  } else {
363
- // 静态 highlights 假设顶部坐标原点不需翻转
364
- canvasY1 = y1 * scale;
365
- canvasY2 = y2 * scale;
458
+ // 静态 highlights:顶部坐标原点,直接使用
459
+ viewportY1 = y1 * scale;
460
+ viewportY2 = y2 * scale;
366
461
  }
367
- // 清除当前路径(如果需要)
462
+
463
+ // 由于 canvas 使用了 transform 渲染,PDF.js 会在内部应用 transform
464
+ // 但 context 的坐标系统是 canvas 的实际尺寸(viewport.width * outputScale)
465
+ // 而 viewport 坐标是基于 viewport.width 的,所以需要转换为 canvas 坐标
466
+ // 注意:outputScale 和 viewport.scale 是相同的值,所以这里只需要乘以 outputScale
467
+ // 但实际上 viewport.scale 已经应用了,所以这里应该直接使用 viewport 坐标
468
+ // 但 canvas 的实际尺寸是 viewport.width * outputScale,所以需要缩放
469
+ let canvasX1 = viewportX1 * outputScale;
470
+ let canvasX2 = viewportX2 * outputScale;
471
+ let canvasY1 = viewportY1 * outputScale;
472
+ let canvasY2 = viewportY2 * outputScale;
473
+
474
+ // 清除当前路径
368
475
  context.beginPath();
369
476
 
370
477
  context.fillStyle = fillStyle;
@@ -384,11 +491,26 @@ export default {
384
491
  }
385
492
  },
386
493
  async setCanvasRef() {
387
- await this.pages.forEach((page, index) => {
388
- this.$set(this.pages[index],'canvas',this.$refs.canvases[index])
389
- // 注意:这里我们直接将 DOM 元素赋值给 page.canvas,
390
- // 但通常你可能想要对 DOM 元素进行进一步的处理或封装。
391
- });
494
+ // 等待 DOM 完全更新
495
+ await this.$nextTick();
496
+
497
+ if (!this.$refs.canvases || !Array.isArray(this.$refs.canvases)) {
498
+ console.warn('Canvas 引用未准备好,延迟重试');
499
+ // 如果 canvas 引用还没准备好,延迟重试
500
+ setTimeout(() => {
501
+ this.setCanvasRef();
502
+ }, 100);
503
+ return;
504
+ }
505
+
506
+ // 确保所有 canvas 引用都已设置
507
+ for (let index = 0; index < this.pages.length; index++) {
508
+ if (this.$refs.canvases && this.$refs.canvases[index]) {
509
+ this.$set(this.pages[index], 'canvas', this.$refs.canvases[index]);
510
+ } else {
511
+ console.warn(`页面 ${index + 1} 的 canvas 引用不存在`);
512
+ }
513
+ }
392
514
  },
393
515
  clearPages() {
394
516
  this.pages = [];
@@ -469,7 +591,8 @@ export default {
469
591
  },
470
592
  zoomIn() {
471
593
  this.updateCurrentPage();
472
- if (this.renderInProgress) return;
594
+ // 检查是否有页面正在加载
595
+ if (this.pages.some(p => p.loading)) return;
473
596
  const container = this.$refs.pdfContainer;
474
597
  const currentScroll = container.scrollTop;
475
598
  this.scale += 0.1;
@@ -477,7 +600,8 @@ export default {
477
600
  },
478
601
  zoomOut() {
479
602
  this.updateCurrentPage();
480
- if (this.renderInProgress) return;
603
+ // 检查是否有页面正在加载
604
+ if (this.pages.some(p => p.loading)) return;
481
605
  const container = this.$refs.pdfContainer;
482
606
  const currentScroll = container.scrollTop;
483
607
  this.scale = Math.max(this.scale - 0.1, 0.1);
@@ -522,7 +646,8 @@ export default {
522
646
  },
523
647
  async doSearch() {
524
648
  if (!this.pdf || !this.searchQuery) return;
525
- if (this.renderInProgress) return;
649
+ // 检查是否有页面正在加载
650
+ if (this.pages.some(p => p.loading)) return;
526
651
 
527
652
  this.searchHighlights = [];
528
653
  const numPages = this.numPages;
@@ -615,7 +740,8 @@ export default {
615
740
  onResize() {
616
741
  clearTimeout(this.resizeTimeout);
617
742
  this.resizeTimeout = setTimeout(() => {
618
- if (this.renderInProgress) return;
743
+ // 检查是否有页面正在加载
744
+ if (this.pages.some(p => p.loading)) return;
619
745
  const container = this.$refs.pdfContainer;
620
746
  const currentScroll = container.scrollTop;
621
747
  const pages = Vue.observable(this.pages)
@@ -0,0 +1,225 @@
1
+ <template>
2
+ <div class="vue-office-pdf">
3
+ <div class="vue-office-pdf-main" id="vue-office-pdf-main" ref="rootRef"></div>
4
+ </div>
5
+ </template>
6
+
7
+ <script>
8
+ import _ from "lodash";
9
+
10
+ const pdfjsLib = window['pdfjsLib']
11
+ if(pdfjsLib) {
12
+ pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
13
+ }
14
+ const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
15
+ import waterMark from "@/utils/common";
16
+ import { mapGetters } from 'vuex'
17
+ import { setTimestamp } from '@/assets/js/common'
18
+ export default {
19
+ name: "vuePdf",
20
+ data(){
21
+ return{
22
+ loadingTask:null,
23
+ transport:null,
24
+ numPages:0,
25
+ pdfDoc:null,
26
+ lazySize:3,
27
+ scale:1
28
+ }
29
+ },
30
+ props:{
31
+ src:{
32
+ type:String,
33
+ default:""
34
+ },
35
+ editType:{
36
+ type:String,
37
+ default:""
38
+ }
39
+ },
40
+ computed:{
41
+ ...mapGetters('knowledge', {
42
+ textWatermarkStr: 'getTextWatermarkStr'
43
+ }),
44
+ },
45
+ methods:{
46
+ async init(){
47
+ //将文件转换成blob解决pdfjs引起浏览器崩溃的问题测试
48
+ let src = this.src
49
+ if (this.editType !== 'copyNewVersion'){
50
+ // src += '?timestamp=' + new Date().getTime();
51
+ src = setTimestamp(src)
52
+ }
53
+ this.loadingTask = pdfjsLib.getDocument(src);
54
+ this.loadingTask.promise.then(async pdf => {
55
+ // 获取PDF的第一页
56
+ this.pdfDoc = pdf;
57
+ this.transport = pdf._transport;
58
+ // this.numPages = pdf._transport.numPages;
59
+ this.lazySize = pdf._transport.numPages;
60
+ this.numPages = Math.min(pdf._transport.numPages, this.lazySize);
61
+ setTimeout(() => {
62
+ this._renderPage(1);
63
+ })
64
+ })
65
+ },
66
+ async _renderPage(num){
67
+ await this.pdfDoc.getPage(num).then(async page => {
68
+ let pageMain = document.getElementById('vue-office-pdf-main');
69
+ const pageDom = document.createElement('div');
70
+ let id = 'pdf-canvas-' + num;
71
+ pageDom.setAttribute('id', id);
72
+ pageDom.setAttribute('class', 'pdf-page');
73
+
74
+ const canvas = document.createElement('canvas');
75
+ const context = canvas.getContext('2d');
76
+ let pdfWidth = page.getViewport({ scale: 1}).width
77
+ const viewport = page.getViewport({ scale: this.calculateScale(pdfWidth) });
78
+ // const viewport = page.getViewport({ scale: 2 })
79
+ let outputScale = this.calculateScale(pdfWidth);
80
+
81
+ canvas.width = Math.floor(viewport.width * outputScale);
82
+ canvas.height = Math.floor(viewport.height * outputScale);
83
+
84
+ let domWidth = Math.floor(viewport.width);
85
+ let domHeight = Math.floor(viewport.height);
86
+
87
+ let wrapperWidth = 0
88
+ if (document.getElementById('vue-office-pdf-main')){
89
+ wrapperWidth = document.getElementById('vue-office-pdf-main').clientWidth - 20
90
+ }
91
+
92
+ if (domWidth > wrapperWidth){
93
+ let scale = wrapperWidth / domWidth;
94
+ domWidth = Math.floor(wrapperWidth);
95
+ domHeight = Math.floor(viewport.height * scale);
96
+ }
97
+ // 根据缩放比例调整canvas大小
98
+
99
+ canvas.style.width = domWidth + 'px';
100
+ canvas.style.height = domHeight + 'px';
101
+
102
+ pageDom.style.width = domWidth + 'px';
103
+ pageDom.style.height = domHeight + 'px';
104
+ pageDom.style.position = 'relative';
105
+ pageDom.style.marginBottom = '10px'
106
+ pageDom.style.marginLeft = 'auto';
107
+ pageDom.style.marginRight = 'auto';
108
+ pageDom.style.backgroundColor = "#ffffff";
109
+ pageDom.style.boxShadow = "0px 0px 18px 0px rgba(29, 55, 129, 0.07)"
110
+ pageDom.appendChild(canvas);
111
+
112
+ const transform = outputScale !== 1
113
+ ? [outputScale, 0, 0, outputScale, 0, 0]
114
+ : null;
115
+
116
+ await page.render({
117
+ canvasContext: context,
118
+ transform:transform,
119
+ viewport:viewport
120
+ }).promise.then(() => {
121
+ return page.getTextContent()
122
+ }).then(async (textContent) => {
123
+ // // 渲染PDF页面到canvas上
124
+
125
+ // var textlayerDiv = document.createElement("div");
126
+ // textlayerDiv.setAttribute('class', 'textLayer');
127
+ // let textlayer = new TextLayerBuilder({
128
+ // textLayerDiv: textlayerDiv,
129
+ // viewport: viewport,
130
+ // });
131
+ //
132
+ // textlayer.setTextContent(textContent);
133
+ // textlayer.render();
134
+ // pageDom.appendChild(textlayerDiv);
135
+ //
136
+ // pageMain.appendChild(pageDom);
137
+
138
+ const textDiv = document.createElement('div');
139
+ textDiv.setAttribute('class', 'textLayer');
140
+ let textLayer = new TextLayerBuilder({
141
+ textLayerDiv: textDiv,
142
+ viewport: viewport,
143
+ transform:transform,
144
+ });
145
+ textDiv.style.width = domWidth + 'px'; // 根据 viewport 调整宽度
146
+ textDiv.style.height = domHeight + 'px'; // 根据 viewport 调整高度(可能需要根据实际文本内容调整)
147
+ textDiv.style.overflow = 'hidden'; // 如果文本内容超出范围,则隐藏它
148
+ textDiv.style.whiteSpace = 'pre-wrap'; // 保留空白符和换行符
149
+ textDiv.style.position = 'absolute'; // 绝对定位以覆盖 canvas
150
+ textDiv.style.top = '0';
151
+ textDiv.style.left = '0';
152
+ // textDiv.textContent = textContent; // 设置文本内容
153
+ textLayer.setTextContent(textContent);
154
+ textLayer.render()
155
+ // 将文本 div 添加到覆盖层中
156
+ pageDom.appendChild(textDiv);
157
+
158
+ pageMain.appendChild(pageDom);
159
+ if (this.textWatermarkStr){
160
+ if(sessionStorage.getItem('isWeChat') == true || sessionStorage.getItem('isWeChat') == 'true') {
161
+ let str = `<ww-open-data type="userName" openid=${this.textWatermarkStr}></ww-open-data>`
162
+ waterMark.newInitWaterMark(id,str)
163
+ } else {
164
+ waterMark.newInitWaterMark(id,this.textWatermarkStr)
165
+ }
166
+ }
167
+ });
168
+ // pageMain.appendChild(pageDom);
169
+ if (this.numPages > num){
170
+ this._renderPage(num + 1)
171
+ }
172
+ })
173
+ },
174
+ calculateScale(pdfWidth) {
175
+ const containerWidth = document.getElementById('vue-office-pdf-main').clientWidth;
176
+ return (containerWidth / pdfWidth) * this.scale;
177
+ },
178
+ onScrollPdf: _.debounce(function (e, that) {
179
+ const { scrollTop, scrollHeight, clientHeight } = e.target;
180
+ if (scrollTop + clientHeight >= scrollHeight) {
181
+ if (that.numPages >= that.pdfDoc._transport.numPages) {
182
+ return;
183
+ }
184
+ let oldNum = that.numPages;
185
+ that.numPages = Math.min(that.pdfDoc._transport.numPages, oldNum + that.lazySize);
186
+ if (that.numPages > oldNum) {
187
+ that._renderPage(oldNum + 1);
188
+ }
189
+ }
190
+ }, 200),
191
+ },
192
+ mounted() {
193
+ this.init();
194
+ document.getElementById('KnowledgePreview').addEventListener('scroll',(e) => {
195
+ this.onScrollPdf(e,this)
196
+ })
197
+ },
198
+ destroyed() {
199
+ if (this.pdfDoc){
200
+ this.pdfDoc.destroy()
201
+ }
202
+ }
203
+ };
204
+ </script>
205
+
206
+ <style scoped lang="less">
207
+ .vue-office-pdf{
208
+ //height: 100%;
209
+ .vue-office-pdf-main{
210
+ //height: calc(100% - 20px);
211
+ //overflow-y: scroll;
212
+ //background: #ededf0;
213
+ //background: #ffffff;
214
+ //padding: 10px 0;
215
+ position: relative;
216
+ .pdf-page{
217
+ background: #ffffff;
218
+ box-shadow: 0px 0px 18px 0px rgba(29, 55, 129, 0.07)!important;
219
+ /deep/.textLayer{
220
+ opacity: 1;
221
+ }
222
+ }
223
+ }
224
+ }
225
+ </style>