askbot-dragon 1.5.37-beta → 1.5.39-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.5.37-beta",
3
+ "version": "1.5.39-beta",
4
4
  "scripts": {
5
5
  "serve": "vue-cli-service serve",
6
6
  "build": "vue-cli-service build",
@@ -3,6 +3,12 @@ export function zoomElement (el) {
3
3
  let store = {
4
4
  scale: 1
5
5
  };
6
+ let scale = 1;
7
+ if (el.style.transform){
8
+ let transForm = el.style.transform;
9
+ var values = transForm.split('(')[1].split(')')[0].split(',');
10
+ scale = values[0] ? values[0] : 1
11
+ }
6
12
  // 缩放事件的处理
7
13
  el.addEventListener('touchstart', function (event) {
8
14
  let touches = event.touches;
@@ -67,13 +73,15 @@ export function zoomElement (el) {
67
73
  newScale = 3;
68
74
  }
69
75
  // 最小缩放比例限制
70
- if(newScale < 1) {
71
- newScale = 1;
76
+ if(newScale < scale) {
77
+ newScale = scale;
72
78
  }
73
79
  // 记住使用的缩放值
74
80
  store.scale = newScale;
75
81
  // 图像应用缩放效果
76
82
  el.style.transform = 'scale(' + newScale + ')';
83
+ el.style.transformOrigin = 'top left'
84
+
77
85
  }
78
86
  });
79
87
  document.addEventListener('touchend', function () {
@@ -246,7 +246,7 @@ export default {
246
246
  this.$refs.previewPdf.tagIds = item.tagIds
247
247
  this.$refs.previewPdf.isMessageRecord = this.isMessageRecord ? true : false ;
248
248
  let fileName = url.substring(url.lastIndexOf('.'))
249
- if (fileName === '.doc' || fileName === '.docx'){
249
+ if (fileName === '.doc' || fileName === '.docx' || fileName === '.txt'){
250
250
  this.$refs.previewPdf.fileName = fileName;
251
251
  } else {
252
252
  this.$refs.previewPdf.fileName = '';
@@ -0,0 +1,878 @@
1
+ <template>
2
+ <div class="pdf-touch-box"
3
+ ref="pdfView"
4
+ @scroll="pdfScroll"
5
+ >
6
+ <div :style="{ width:btnWidth + 'px' }">
7
+ <button @click="scaleEvent(3.5)">3.5</button>
8
+ <button @click="scaleEvent(2.5)">2.5</button>
9
+ <button @click="scaleEvent(1.8)">1.8</button>
10
+ <button @click="scaleEvent(1.4)">1.4</button>
11
+ <button @click="scaleEvent(1)">1</button>
12
+ <button @click="scaleEvent(0.5)">0.5</button>
13
+ </div>
14
+
15
+ <div
16
+ v-show="!loading"
17
+ class="pdf-canvas-wrap"
18
+ id="pdf-canvas-wrap"
19
+ :style="{
20
+ top: viewTop + 'px',
21
+ left: viewLeft + 'px',
22
+ width:viewWidth + 'px',
23
+ height: viewHeight + 'px'
24
+ }"
25
+ ></div>
26
+ <p v-show="loading">正在加载...</p>
27
+ </div>
28
+ </template>
29
+
30
+
31
+
32
+ <script>
33
+ // import * as PDFJS from 'pdfjs-dist'
34
+ // console.log(PDFJS)
35
+ //
36
+ // import { TextLayerBuilder, EventBus } from 'pdfjs-dist/web/pdf_viewer'
37
+ import _ from "lodash";
38
+
39
+ const pdfjsLib = window['pdfjsLib']
40
+ if(pdfjsLib) {
41
+ pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
42
+ // 'pdfjs-dist/build/pdf.worker';
43
+ }
44
+ const { TextLayerBuilder,EventBus } = window['pdfjs-dist/web/pdf_viewer']
45
+ // import 'pdfjs-dist/web/pdf_viewer.css'
46
+ console.log(TextLayerBuilder)
47
+
48
+ // 本地
49
+ // window.pdfjsWorker = require("pdfjs-dist/build/pdf.worker.js");
50
+
51
+ // cdn 2.8.335 2.6.347 2.5.207
52
+ pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.6.347/build/pdf.worker.min.js'
53
+
54
+ // https://github.com/mozilla/pdf.js/blob/master/examples/node/getinfo.js
55
+ // Requires single file built version of PDF.js -- please run
56
+ // `gulp singlefile` before running the example.
57
+ // const pdfjsLib = require("pdfjs-dist/legacy/build/pdf.js");
58
+
59
+ const CSS_UNITS = 96.0 / 72.0
60
+ // const PRINT_UNITS = 150 / 72.0;
61
+
62
+ let userAgent = (typeof navigator !== 'undefined' && navigator.userAgent) || ''
63
+ let platform = (typeof navigator !== 'undefined' && navigator.platform) || ''
64
+ let maxTouchPoints = (typeof navigator !== 'undefined' && navigator.maxTouchPoints) || 1
65
+
66
+ let maxCanvasPixels = 16777216
67
+ // PDF之外占据的宽度 -18 padding -18减去滚动条宽度(不确定)
68
+ let autoWidth = 36
69
+ let textLayerTop = 3
70
+ let scaleInterval = 0.05
71
+
72
+ let isAndroid = /Android/.test(userAgent)
73
+ let isIOS = /(iPad|iPhone|iPod)(?=;)/.test(userAgent) || (platform === 'MacIntel' && maxTouchPoints > 1)
74
+ ;(function checkCanvasSizeLimitation() {
75
+ if (isIOS || isAndroid) {
76
+ maxCanvasPixels = 5242880
77
+ autoWidth -= 18
78
+ textLayerTop -= 1
79
+ // 手机上面缩放对清晰度影响更小
80
+ scaleInterval = 0.4
81
+ }
82
+ })()
83
+ import AlloyFinger from 'alloyfinger'
84
+ //包装一下 不然 eslint 报警告
85
+ class FingerTouch {
86
+ constructor(element, options) {
87
+ Object.assign(this, AlloyFinger.prototype)
88
+ AlloyFinger.call(this, element, options)
89
+ }
90
+ }
91
+ export default {
92
+ name: "newPdfPosition",
93
+ data() {
94
+ return {
95
+ src: '../assets/js/test.pdf',
96
+ loading: true,
97
+ pdfDoc: null,
98
+ boxEl: null,
99
+ wrapEl: null,
100
+ areaWidth: 0,
101
+ btnWidth: 0,
102
+ viewWidth: 0,
103
+ viewHeight: 0,
104
+ pixelRatio: 2,
105
+ isFirstTimeRender: true,
106
+ viewport: null,
107
+ canvasEles: [],
108
+ canvasCtxs: [],
109
+ totallPage: 0,
110
+ pageScale: 1, // pdf 适应窗口产生的 scale
111
+ curCanvasCSSWh: null,
112
+ transform: null,
113
+ pageRenderedNum: 0,
114
+ scaleTimer: null,
115
+ lastStyleScale: 1,
116
+ lastRerenderScale: 1,
117
+ alloyFinger: null,
118
+ viewTop: 0,
119
+ viewLeft: 9,
120
+ textEls: [],
121
+ url: '',
122
+ pages: [],
123
+ pageLoadStatus: {
124
+ WAIT: 0,
125
+ LOADED: 1,
126
+ },
127
+ scale: 1,
128
+ rotation: 0,
129
+ pageSize: {},
130
+ PAGE_INTVERVAL: 15,
131
+ SLICE_COUNT: 5,
132
+ contentView: null,
133
+ fisrtLoad: true,
134
+ TextLayerBuilder: null,
135
+ totalPageCount: 0,
136
+ identifyTextPostion: {
137
+ top: 0,
138
+ left: 0,
139
+ width: 100,
140
+ height: 0,
141
+ page: 1,
142
+ pageHeight: 0,
143
+ pageWidth: 0,
144
+ extractInfo: {},
145
+ currentPageAllLine: []
146
+ },
147
+ currentPageAllLine: [],
148
+ pdfUrl: '',
149
+ cachePdf: [],
150
+ newViewer: null,
151
+ currentPage: 0,
152
+ changetoolbar: false,
153
+ allTr:[],
154
+ preViewType: 'pdf',
155
+ displacement:{
156
+ pageX: 0,
157
+ pageY: 0,
158
+ moveable: false,
159
+ pageX2: 0,
160
+ pageY2: 0,
161
+ originScale: 1,
162
+ },
163
+ isTouchMoved: false,
164
+ transformSalce: null,
165
+ isPC: false,
166
+ handScale: 'auto',
167
+ scaleList:[
168
+ {
169
+ label:'自动缩放',
170
+ value:'auto'
171
+ },
172
+ {
173
+ label:'实际比例',
174
+ value:'reality'
175
+ },
176
+ {
177
+ label:'100%',
178
+ value: 1
179
+ },
180
+ {
181
+ label:'120%',
182
+ value: 1.2
183
+ },
184
+ {
185
+ label:'150%',
186
+ value: 1.5
187
+ },
188
+ {
189
+ label:'170%',
190
+ value: 1.7
191
+ }
192
+ ,
193
+ {
194
+ label:'200%',
195
+ value: 2
196
+ }
197
+ ],
198
+ scrollTop:0,
199
+ scrollLeft:0,
200
+ }
201
+ },
202
+ props:["tagIds"],
203
+ mounted() {
204
+ // this.init()
205
+ },
206
+ methods: {
207
+ async init(loadPage) {
208
+ //禁止下拉刷新
209
+ document.addEventListener(
210
+ 'touchmove',
211
+ function () {
212
+ // ev.preventDefault()
213
+ },
214
+ { passive: false }
215
+ )
216
+ this.boxEl = document.querySelector('.pdf-touch-box')
217
+ this.wrapEl = document.getElementsByClassName('pdf-canvas-wrap')[0]
218
+ this.btnWidth = this.areaWidth = this.boxEl.clientWidth
219
+ await this.initPages(loadPage.total);
220
+ const loadingState = await this.getPDF(loadPage.page)
221
+ if (loadingState === 'success') {
222
+ this.initRenderOneByOne(loadPage.page)
223
+ this.initTouch()
224
+ } else this.boxEl.innerText = loadingState
225
+ },
226
+ initTouch() {
227
+ this.alloyFinger = new FingerTouch(this.wrapEl, {})
228
+ this.alloyFinger.on('pinch', e => {
229
+ let zoom = e.zoom
230
+ let curScale = this.lastStyleScale * zoom
231
+ if (curScale <= 1 || curScale >= 5) return
232
+ this.scaleEvent(curScale)
233
+ })
234
+
235
+ this.alloyFinger.on('pressMove', e => {
236
+ this.viewTop += e.deltaY
237
+ this.viewLeft += e.deltaX
238
+ })
239
+ },
240
+ scaleEvent(scale) {
241
+ // 渲染中 不让缩放 也不让重绘
242
+ if (this.pageRenderedNum != this.totallPage || this.totallPage === 0) return
243
+
244
+ // 没在渲染中 随意缩放
245
+ this.scaleCanvas(scale)
246
+
247
+ // 说明是第一次事件 或重绘完成 开始计时
248
+ if (this.scaleTimer === null) {
249
+ this.scaleTimer = this.renderDelayer(666)
250
+ }
251
+ //时间间隔内再次触发缩放 重新计时
252
+ clearTimeout(this.scaleTimer)
253
+ this.scaleTimer = this.renderDelayer(666)
254
+ },
255
+ renderDelayer(interval) {
256
+ return setTimeout(() => {
257
+ this.scaleRenderAll()
258
+ this.scaleTimer = null
259
+ }, interval)
260
+ },
261
+ scaleTopLeft(width, height) {
262
+ if (Math.abs(this.viewTop) > height / 2) this.viewTop *= 1 / 2
263
+ if (Math.abs(this.viewLeft) > width / 2) this.viewLeft *= 1 / 2
264
+ },
265
+ scaleCanvas(scale) {
266
+ this.lastStyleScale = scale
267
+ console.log(scale)
268
+ // 改变 viewport 大小
269
+ this.viewport = this.viewport.clone({
270
+ scale: (this.pageScale * CSS_UNITS * scale).toFixed(3)
271
+ })
272
+
273
+ const { styleWidth, styleHeight } = this.getCanvasCSSWH()
274
+
275
+ // 计算一下 top left 不然可能会显示到 窗口外面 看不到了
276
+ this.scaleTopLeft(styleWidth, styleHeight)
277
+
278
+ // 改变CSS canvas 会变模糊
279
+ this.canvasEles.forEach(canvas => {
280
+ // 不修改 width height 不然会重置 canvas 变空白
281
+ canvas.style.width = styleWidth + 'px'
282
+ canvas.style.height = styleHeight + 'px'
283
+ })
284
+ },
285
+ // 使用新渲染的 canvas 替换 缩放过后不清晰的 canvas
286
+ scaleRenderAll() {
287
+ let curInterval = Math.abs(this.lastStyleScale - this.lastRerenderScale)
288
+ let curScaleInterval = scaleInterval
289
+ let isNarrow = this.lastStyleScale < this.lastRerenderScale
290
+ // 如果是变小 变化不大时 清晰度影响更小
291
+ if (isNarrow) curScaleInterval = scaleInterval * 2
292
+
293
+ console.log('scaleRenderAll', curScaleInterval, curInterval)
294
+ // 变化很小的时候就不计时重新渲染了 清晰度影响不大 1.1 - 1 = 0.10000000000000009
295
+ if (curInterval <= curScaleInterval) return
296
+
297
+ this.lastRerenderScale = this.lastStyleScale
298
+
299
+ this.pageRenderedNum = 0
300
+ const len = this.canvasEles.length
301
+ for (let pageNum = 1; pageNum <= len; pageNum++) {
302
+ let newCanvas = document.createElement('canvas')
303
+ let newCtx = newCanvas.getContext('2d', {
304
+ alpha: false
305
+ })
306
+ newCanvas.setAttribute('id', `pdf-canvas${pageNum}`)
307
+
308
+ this.canvasCtxs[pageNum - 1] = newCtx
309
+
310
+ let that = this
311
+ console.debug('pdfDoc',this.pdfDoc)
312
+ this.pdfDoc.getPage(pageNum).then(function (page) {
313
+ that.setCanvasCSSWh.call(that, newCanvas)
314
+
315
+ let renderTask = that.pageRender.call(that, page, newCtx)
316
+
317
+ renderTask.promise
318
+ .then(function () {
319
+ let oldCanvas = that.canvasEles[pageNum - 1]
320
+ oldCanvas.parentElement.replaceChild(newCanvas, oldCanvas)
321
+ that.canvasEles[pageNum - 1] = newCanvas
322
+ that.pageRenderedNum++
323
+
324
+ return page.getTextContent()
325
+ })
326
+ .then(textContent => that.textRerender.call(that, pageNum, textContent))
327
+ .catch(e => console.log(e))
328
+ })
329
+ }
330
+ },
331
+ initPages (totalPage) {
332
+ this.totalPageCount = totalPage;
333
+ // this.totallPage = totalPage;
334
+ for (let i = 0; i < totalPage; i += 1) {
335
+ this.pages.push({
336
+ pageNo: i + 1,
337
+ loadStatus: false,
338
+ pdfPage: null,
339
+ dom: null
340
+ });
341
+ }
342
+ },
343
+ async getPDF (loadPage) {
344
+ let that = this;
345
+ if(that.pages[loadPage - 1] && ((that.pages[loadPage - 1].dom && that.pages[loadPage - 1].dom.children.length > 0) || that.pages[loadPage - 1].loadStatus)) {
346
+ return
347
+ } else {
348
+ if (that.changetoolbar) {
349
+ that.$nextTick(() => {
350
+ that.renderHighlights()
351
+ })
352
+ that.changetoolbar = false
353
+ }
354
+ }
355
+ // 记录开始缓存的状态
356
+ // pdfjsLib.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/legacy/build/pdf.worker.entry.js");
357
+ // 拿到第一个分片
358
+ const { url } = await that.fetchPdfFragment(loadPage);
359
+ let loadingTask = pdfjsLib.getDocument(url);
360
+ return new Promise(reslove => {
361
+ loadingTask.promise.then((pdfDoc_) => {
362
+ that.pdfDoc = pdfDoc_
363
+ that.totallPage += 1
364
+ console.debug('totallPage',that.totallPage)
365
+ // that.totallPage = pdfDoc_.numPages;
366
+ that.loading = false
367
+ reslove('success')
368
+ })
369
+ })
370
+ },
371
+ async fetchPdfFragment (pageIndex) {
372
+ // 置换加签后的文件地址。
373
+ let obj = {}
374
+ await this.$http.post(
375
+ '/knowledge-api/temporary-certificate/or-origin?expired=30',
376
+ this.pdfUrl + pageIndex + '.pdf',
377
+ {
378
+ headers: {
379
+ "Content-Type": "application/json",
380
+ },
381
+ }).then(async res => {
382
+ if(res.bodyText) {
383
+ // 最后返回一个 包含这4个参数的对象
384
+ obj = await {
385
+ "startPage": pageIndex, // 分片的开始页码
386
+ "endPage": pageIndex + 5, // 分片结束页码
387
+ "totalPage": this.totalPageCount, // pdf 总页数
388
+ "url": res.bodyText // 分片内容下载地址
389
+ }
390
+ }
391
+ if (res.data) {
392
+ // 最后返回一个 包含这4个参数的对象
393
+ obj = await {
394
+ "startPage": pageIndex, // 分片的开始页码
395
+ "endPage": pageIndex + 5, // 分片结束页码
396
+ "totalPage": this.totalPageCount, // pdf 总页数
397
+ "url": res.data // 分片内容下载地址
398
+ }
399
+ }
400
+ })
401
+ return obj
402
+ },
403
+ // 渲染需要展示的页面,不需展示的页码将其清除
404
+ renderPages (pageIndex) {
405
+ const pagesToRender = this.getRenderScope(pageIndex);
406
+ for (const i of this.pages) {
407
+ if(pagesToRender.some(p =>{ return p.pageNo == i.pageNo })) {
408
+ if(i.loadStatus === true) {
409
+ console.debug('pagesToRender',i)
410
+ this.initRenderOneByOne(i.pageNo)
411
+ } else {
412
+ // this.renderPageLoading(i, i.pageNo)
413
+ }
414
+ } else {
415
+ // this.clearPage(i);
416
+ }
417
+ }
418
+
419
+ },
420
+ // 根据当前的可视范围内的页码,我们前后只保留 8 页
421
+ getRenderScope (pageIndex) {
422
+ const pagesToRender = [];
423
+ let i = pageIndex - 1;
424
+ let j = pageIndex + 1;
425
+ // pageIndex - 1 表示当前页码数 对应的下标位置
426
+ pagesToRender.push(this.pages[pageIndex - 1]);
427
+ while (pagesToRender.length < 8 && pagesToRender.length < this.pages.length) {
428
+ if (i > 0) {
429
+ pagesToRender.push(this.pages[i - 1]);
430
+ i -= 1;
431
+ }
432
+ if (pagesToRender.length >= 8) {
433
+ break;
434
+ }
435
+ if (j <= this.pages.length) {
436
+ pagesToRender.push(this.pages[j - 1]);
437
+ j += 1;
438
+ }
439
+ }
440
+ // for (let index = 0; index < array.length; index++) {
441
+ // const element = array[index];
442
+
443
+ // }
444
+ return pagesToRender;
445
+ },
446
+ initRenderOneByOne(pageIndex) {
447
+ console.debug('pageIndex',pageIndex,this.totallPage)
448
+ // for (let pageNum = pageIndex; pageNum <= this.totallPage; pageNum++) {
449
+ //
450
+ // }
451
+ let canvas = document.createElement('canvas')
452
+ canvas.setAttribute('id', `pdf-canvas${pageIndex}`)
453
+ canvas.setAttribute('class', `pdfcanvas`)
454
+ // alpha 设定 canvas 背景总是不透明,可以加快浏览器绘制透明的内容和图片 初始化出来 canvas 为黑色背景
455
+ // 实际上 导致 重新渲染的时候 闪黑屏
456
+ // let ctx = canvas.getContext("2d", {
457
+ // alpha: false,
458
+ // });
459
+ let ctx = canvas.getContext('2d')
460
+ this.canvasCtxs.push(ctx)
461
+ this.canvasEles.push(canvas)
462
+ // this.wrapEl.appendChild(canvas);
463
+
464
+ let pageDiv = document.createElement('div')
465
+ pageDiv.setAttribute('id', 'page-' + pageIndex)
466
+ pageDiv.setAttribute('style', 'position: relative;')
467
+ this.wrapEl.appendChild(pageDiv)
468
+ pageDiv.appendChild(canvas)
469
+ this.renderSinglePage(canvas, pageIndex)
470
+ // this.renderSinglePage(this.canvasEles[0], 1)
471
+ },
472
+
473
+ renderSinglePage(canvas, pageNum) {
474
+ let ctx = this.canvasCtxs[pageNum - 1]
475
+ let that = this
476
+ that.pdfDoc.getPage(1).then(async function (page) {
477
+ that.pages[pageNum - 1].loadStatus = true
478
+ that.pages[pageNum - 1].pdfPage = page;
479
+ if (that.isFirstTimeRender) that.initView(page, ctx)
480
+
481
+ if (pageNum === 1) await that.getCanvasCSSWH()
482
+ await that.setCanvasCSSWh.call(that, canvas)
483
+ let renderTask = that.pageRender.call(that, page, ctx)
484
+
485
+ renderTask.promise
486
+ .then(function () {
487
+ // if (that.totallPage > pageNum) {
488
+ // that.renderSinglePage(that.canvasEles[pageNum], pageNum + 1)
489
+ // }
490
+ // const html = canvas.toDataURL();
491
+ // let image = document.createElement('img');
492
+ // image.setAttribute('src',html)
493
+
494
+ that.pageRenderedNum++
495
+ return page.getTextContent()
496
+ })
497
+ .then(textContent => that.textRender.call(that, canvas, pageNum, textContent))
498
+ })
499
+ },
500
+ textRerender(pageIndex, textContent) {
501
+ const oldDiv = this.textEls[pageIndex - 1]
502
+
503
+ const newDiv = document.createElement('div')
504
+ newDiv.setAttribute('class', 'textLayer')
505
+ newDiv.setAttribute('style', `top: ${textLayerTop}px`)
506
+
507
+ oldDiv.parentElement.replaceChild(newDiv, oldDiv)
508
+ this.textEls[pageIndex - 1] = newDiv
509
+ console.debug('textContent',textContent)
510
+ this.renderTextLayer(newDiv, pageIndex, textContent)
511
+ },
512
+ textRender(canvas, pageIndex, textContent) {
513
+ const textLayerDiv = document.createElement('div')
514
+ textLayerDiv.setAttribute('class', 'textLayer')
515
+ textLayerDiv.setAttribute('style', `top: ${textLayerTop}px`)
516
+ canvas.parentElement.appendChild(textLayerDiv)
517
+ this.textEls[pageIndex - 1] = textLayerDiv
518
+ this.renderTextLayer(textLayerDiv, pageIndex, textContent)
519
+ },
520
+ renderTextLayer(el, index, content) {
521
+ var textLayer = new TextLayerBuilder({
522
+ eventBus: new EventBus(),
523
+ textLayerDiv: el,
524
+ pageIndex: index,
525
+ viewport: this.viewport
526
+ })
527
+
528
+ textLayer.setTextContent(content)
529
+ textLayer.render()
530
+ this.fisrtLoad = false;
531
+ },
532
+ setCanvasCSSWh(canvas) {
533
+ let that = this
534
+ canvas.width = that.curCanvasCSSWh.width
535
+ canvas.height = that.curCanvasCSSWh.height
536
+ canvas.style.width = that.curCanvasCSSWh.styleWidth + 'px'
537
+ canvas.style.height = that.curCanvasCSSWh.styleHeight + 'px'
538
+ // canvas.style['border'] = '#d6d6d6 solid 1px'
539
+ canvas.style.margin = '0 0 9px 0'
540
+ },
541
+ pageRender(page, ctx) {
542
+ return page.render({
543
+ canvasContext: ctx,
544
+ transform: this.transform,
545
+ viewport: this.viewport,
546
+ enableWebGL: false,
547
+ renderInteractiveForms: false
548
+ })
549
+ },
550
+
551
+ drawBorder(canvas, ctx) {
552
+ ctx.save()
553
+ ctx.fillStyle = 'rgb(255, 255, 255)'
554
+ ctx.strokeRect(0, 0, canvas.width, canvas.height)
555
+ ctx.restore()
556
+ },
557
+ getCanvasCSSWH() {
558
+ let outputScale = {
559
+ sx: this.pixelRatio,
560
+ sy: this.pixelRatio,
561
+ scaled: this.pixelRatio !== 1
562
+ }
563
+
564
+ let pixelsInViewport = this.viewport.width * this.viewport.height
565
+ let maxScale = Math.sqrt(maxCanvasPixels / pixelsInViewport)
566
+
567
+ if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
568
+ // 这里触发会出错
569
+ // outputScale.sx = maxScale;
570
+ // outputScale.sy = maxScale;
571
+ // outputScale.scaled = true;
572
+ }
573
+
574
+ let sfx = (0, this.approximateFraction)(outputScale.sx)
575
+ let sfy = (0, this.approximateFraction)(outputScale.sy)
576
+ const width = (0, this.roundToDivide)(this.viewport.width * outputScale.sx, sfx[0])
577
+ const height = (0, this.roundToDivide)(this.viewport.height * outputScale.sy, sfy[0])
578
+ const styleWidth = (0, this.roundToDivide)(this.viewport.width, sfx[1])
579
+ const styleHeight = (0, this.roundToDivide)(this.viewport.height, sfy[1])
580
+
581
+ if (this.pixelRatio !== 1) this.transform = [this.pixelRatio, 0, 0, this.pixelRatio, 0, 0]
582
+
583
+ this.viewWidth = styleWidth + 2
584
+ // 12 加上 canvas border margin 误差?2 + 9 + 1
585
+ // this.viewHeight = this.totallPage * (this.viewport.height + 12) + 9
586
+ console.debug('totalPageCount',this.totalPageCount)
587
+ this.viewHeight = `${(this.totalPageCount * (this.viewport.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}`
588
+ console.debug('viewHeight',this.viewHeight,this.totallPage)
589
+ this.curCanvasCSSWh = { width, height, styleWidth, styleHeight }
590
+ return this.curCanvasCSSWh
591
+ },
592
+ approximateFraction(x) {
593
+ if (Math.floor(x) === x) {
594
+ return [x, 1]
595
+ }
596
+
597
+ var xinv = 1 / x
598
+ var limit = 8
599
+
600
+ if (xinv > limit) {
601
+ return [1, limit]
602
+ } else if (Math.floor(xinv) === xinv) {
603
+ return [1, xinv]
604
+ }
605
+
606
+ var x_ = x > 1 ? xinv : x
607
+ var a = 0,
608
+ b = 1,
609
+ c = 1,
610
+ d = 1
611
+ // eslint-disable-next-line
612
+ while (true) {
613
+ var p = a + c,
614
+ q = b + d
615
+
616
+ if (q > limit) {
617
+ break
618
+ }
619
+
620
+ if (x_ <= p / q) {
621
+ c = p
622
+ d = q
623
+ } else {
624
+ a = p
625
+ b = q
626
+ }
627
+ }
628
+
629
+ var result
630
+
631
+ if (x_ - a / b < c / d - x_) {
632
+ result = x_ === x ? [a, b] : [b, a]
633
+ } else {
634
+ result = x_ === x ? [c, d] : [d, c]
635
+ }
636
+
637
+ return result
638
+ },
639
+ roundToDivide(x, div) {
640
+ var r = x % div
641
+ return r === 0 ? x : Math.round(x - r + div)
642
+ },
643
+
644
+ initView(page, ctx) {
645
+ let devicePixelRatio = window.devicePixelRatio || 1
646
+ let backingStoreRatio =
647
+ ctx.webkitBackingStorePixelRatio ||
648
+ ctx.mozBackingStorePixelRatio ||
649
+ ctx.msBackingStorePixelRatio ||
650
+ ctx.oBackingStorePixelRatio ||
651
+ ctx.backingStorePixelRatio ||
652
+ 1
653
+ this.pixelRatio = devicePixelRatio / backingStoreRatio
654
+
655
+ this.viewport = page.getViewport({
656
+ scale: CSS_UNITS
657
+ })
658
+
659
+ this.pageScale = (this.areaWidth - autoWidth) / this.viewport.width
660
+ let curViewport = page.getViewport({
661
+ scale: this.pageScale * CSS_UNITS
662
+ })
663
+ this.viewport = curViewport
664
+
665
+ this.isFirstTimeRender = false
666
+ },
667
+ pdfScroll (e) {
668
+ if(this.preViewType !== 'pdf' || this.isTouchMoved) {
669
+ return
670
+ }
671
+ if(this.scrollTop != e.target.scrollTop) {
672
+ this.scrollTop = e.target.scrollTop
673
+ this.debounceScrollPdf(e, this)
674
+ }
675
+ },
676
+ // 这里加了防抖保证不会一次产生过多请求
677
+ debounceScrollPdf: _.debounce(async function (e, that) {
678
+ if (that.fisrtLoad) {
679
+ that.fisrtLoad = false
680
+ return
681
+ }
682
+ const scrollTop = e.target.scrollTop;
683
+ const height = e.target.clientHeight;
684
+ let startNum = 0;
685
+ let endNum = 0;
686
+ // if (scrollTop + height == scrollHeight){
687
+ // console.debug('=====',that.pages)
688
+ // for (let i = 0 ;i< that.pages.length; i++){
689
+ // if (!that.pages[i].loadStatus){
690
+ // console.debug('loadStatus',that.pages[i])
691
+ // const loadingState = await that.getPDF(that.pages[i].pageNo);
692
+ // if (loadingState === 'success'){
693
+ // that.initRenderOneByOne(that.pages[i].pageNo)
694
+ // }
695
+ // // that.renderPages(that.pages[i].pageNo)
696
+ // break
697
+ // }
698
+ // }
699
+ // }
700
+ startNum = Math.ceil(scrollTop / (that.viewport.height + that.PAGE_INTVERVAL))
701
+ endNum = startNum + Math.ceil(height / (that.viewport.height + that.PAGE_INTVERVAL))
702
+ console.debug('scrollTop',scrollTop,that.viewport.height,startNum,endNum)
703
+ if (startNum > 1){
704
+ // for (let pageIndex = startNum; pageIndex < endNum; pageIndex++) {
705
+ // if(pageIndex > 0 && pageIndex <= that.pages.length) {
706
+ // console.debug('startNum',scrollTop,startNum,endNum,height,that.curCanvasCSSWh)
707
+ // const loadingState = await that.getPDF(pageIndex);
708
+ // if (loadingState === 'success') {
709
+ // // that.renderPages(pageIndex + 1)
710
+ // that.initRenderOneByOne(pageIndex)
711
+ // // this.initTouch()
712
+ // } else that.boxEl.innerText = loadingState
713
+ // }
714
+ // }
715
+ }
716
+ }, 200),
717
+ renderHighlights(){
718
+ let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
719
+ if (lineHeightDom) {
720
+ lineHeightDom.forEach((d) => {
721
+ for (let i = 0; i < d.children.length; i++) {
722
+ if (d.getAttribute('react-count') == this.currentPage) {
723
+ d.children[i].style.backgroundColor = 'rgba(255, 136, 0, 0.3)'
724
+ d.children[i].classList.add('animation')
725
+ setTimeout(() =>{
726
+ d.children[i].classList.remove('animation')
727
+ }, 4000)
728
+ } else {
729
+ d.children[i].style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
730
+ d.children[i].classList.remove('animation')
731
+ }
732
+ }
733
+ })
734
+ }
735
+ }
736
+ },
737
+ watch:{
738
+ tagIds: {
739
+ handler(value) {
740
+ console.debug('tagIds',value)
741
+ if(value && value.length) {
742
+ // 在 pdf_view 下创建 所有canvs的容器
743
+ this.contentView = document.createElement('div')
744
+ this.contentView.style.transformOrigin = '0px 0px 0px'
745
+ this.$http.get('/knowledge-api/knowledge/knowledge-part-location-info/list?ids=' + value.join(',')).then(res =>{
746
+ if (res.data.code == 0) {
747
+ // tagIds 会按照gpt识别的生成有序的数组,前端直接按照下标的顺序取就可以了
748
+ // 缓存拿到的所有数据
749
+ this.cachePdf = res.data.data
750
+ console.debug('res',res.data.data[0])
751
+ let publicPageFileUrl = res.data.data[0].publicPageFileUrl
752
+ this.currentPage = 0;
753
+ this.pdfUrl = res.data.data[0].publicPageFileUrl.substring(0, res.data.data[0].publicPageFileUrl.lastIndexOf('/') + 1)
754
+ if (publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')) === '.pdf') {
755
+ this.preViewType = 'pdf'
756
+ // this.setPageAllLine(this.cachePdf)
757
+ this.init(res.data.data[0])
758
+ } else {
759
+ this.preViewType = 'excal'
760
+ this.$http.post(
761
+ '/knowledge-api/temporary-certificate/or-origin?expired=30',
762
+ publicPageFileUrl,
763
+ {
764
+ headers: {
765
+ "Content-Type": "application/json",
766
+ },
767
+ }).then(res => {
768
+ // 使用原声请求方式 axios会带有不需要的请求头
769
+ let xhr = new XMLHttpRequest();
770
+ xhr.open('GET', res.data || res.bodyText , true);
771
+ // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
772
+ xhr.onload = ({ currentTarget }) => {
773
+ // 请求完成
774
+ if (currentTarget.status === 200) { // 返回200
775
+ this.contentView.innerHTML = currentTarget.response
776
+ this.contentView.style.padding = '10px'
777
+ // this.contentView.style.position = 'relative'
778
+ this.$refs.pdfView.style.backgroundColor = '#FFFFFF'
779
+ this.$refs.pdfView.appendChild(this.contentView)
780
+ let allTr = Array.from(this.$refs.pdfView.getElementsByTagName('tr'))
781
+ this.allTr = []
782
+ for (let index = 0; index < allTr.length; index++) {
783
+ if(value.includes(allTr[index].getAttribute('tag-id'))) {
784
+ this.allTr.push(allTr[index])
785
+ }
786
+ }
787
+ this.currentChange(1)
788
+
789
+ }
790
+ }
791
+ xhr.send();
792
+ })
793
+ }
794
+ } else {
795
+ let div = document.createElement('div')
796
+ div.innerText = '文件加载异常'
797
+ this.contentView.appendChild(div)
798
+ this.$refs.pdfView.appendChild(this.contentView)
799
+ }
800
+ })
801
+ }
802
+ },
803
+ deep:true,
804
+ immediate:true
805
+ }
806
+ }
807
+ }
808
+ </script>
809
+
810
+ <style scoped>
811
+ .pdf-touch-box {
812
+ padding: 9px;
813
+ width: calc(100% - 18px);
814
+ height: calc(100% - 18px);
815
+ position: relative;
816
+ overflow: auto;
817
+ }
818
+ .scale-btn-box {
819
+ position: fixed;
820
+ top: 0;
821
+ left: 0;
822
+ height: 44px;
823
+ display: flex;
824
+ justify-content: space-around;
825
+ z-index: 99;
826
+ }
827
+ .scale-btn-box::after {
828
+ content: '';
829
+ width: 100%;
830
+ height: 100%;
831
+ position: absolute;
832
+ background: #fff;
833
+ top: 0;
834
+ left: 0;
835
+ filter: blur(18px);
836
+ opacity: 0.8;
837
+ }
838
+ .scale-btn {
839
+ position: relative;
840
+ z-index: 2;
841
+ width: 25%;
842
+ height: 100%;
843
+ display: inline-block;
844
+ line-height: 1;
845
+ white-space: nowrap;
846
+ cursor: pointer;
847
+ background: #fff;
848
+ border: 1px solid #dcdfe6;
849
+ color: #606266;
850
+ -webkit-appearance: none;
851
+ text-align: center;
852
+ box-sizing: border-box;
853
+ outline: none;
854
+ margin: 0;
855
+ transition: 0.1s;
856
+ font-weight: 500;
857
+ -moz-user-select: none;
858
+ -webkit-user-select: none;
859
+ -ms-user-select: none;
860
+ padding: 12px 20px;
861
+ font-size: 14px;
862
+ border-radius: 4px;
863
+ }
864
+ .pdf-canvas-wrap {
865
+ display: flex;
866
+ flex-direction: column;
867
+ align-items: center;
868
+ overflow: hidden;
869
+ /*margin-top: 44px;*/
870
+ padding-top: 9px;
871
+ /*height: 100%;*/
872
+ /*overflow-y: scroll;*/
873
+ /*position: absolute;*/
874
+ }
875
+ .pdf-canvas-tips {
876
+ margin-top: 44px;
877
+ }
878
+ </style>
@@ -44,6 +44,7 @@ if (pdfjsLib) {
44
44
  // 'pdfjs-dist/build/pdf.worker';
45
45
  }
46
46
  const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
47
+ const CSS_UNITS = 96.0 / 72.0
47
48
  // import { zoomElement } from '../assets/js/hammer'
48
49
  export default {
49
50
  name: 'pdfView',
@@ -292,25 +293,30 @@ export default {
292
293
  const canvas = document.createElement('canvas');
293
294
  const context = canvas.getContext('2d');
294
295
  // canvas.getContext('2d');
295
- canvas.height = this.pageSize.height;
296
- canvas.width = this.pageSize.width;
296
+ canvas.height = this.pageSize.height * CSS_UNITS;
297
+ canvas.width = this.pageSize.width * CSS_UNITS;
297
298
  canvas.style.position = 'relative'
298
299
  canvas.style.top = -3 + 'px'
299
300
  // 创建渲染的dom
300
301
  const pageDom = document.createElement('div');
301
302
  pageDom.style.position = 'absolute';
302
- pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
303
- pageDom.style.width = `${this.pageSize.width}px`;
304
- pageDom.style.height = `${this.pageSize.height}px`;
303
+ pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * CSS_UNITS) + this.PAGE_INTVERVAL}px`;
304
+ pageDom.style.width = `${this.pageSize.width * CSS_UNITS}px`;
305
+ pageDom.style.height = `${this.pageSize.height * CSS_UNITS}px`;
305
306
  pageDom.setAttribute('data-id', 'page' + pageNo)
306
- pageDom.appendChild(canvas);
307
+ // pageDom.appendChild(canvas);
307
308
  // 渲染内容
308
309
  let renderContext = {
309
310
  canvasContext: context,
310
311
  viewport: viewport,
312
+ transform: [CSS_UNITS, 0, 0, CSS_UNITS, 0, 0],
311
313
  }
312
314
  await pdfPage.render(renderContext).promise.then(() => {
313
- return pdfPage.getTextContent()
315
+ const html = canvas.toDataURL();
316
+ let image = document.createElement('img');
317
+ image.setAttribute('src',html)
318
+ pageDom.appendChild(image);
319
+ return pdfPage.getTextContent()
314
320
  }).then(async (textContent) => {
315
321
  const textLayerDiv = document.createElement('div');
316
322
  textLayerDiv.setAttribute('class', 'textLayer');
@@ -340,19 +346,19 @@ export default {
340
346
  let postionArr = lines[index].location
341
347
  let div = document.createElement('div')
342
348
  div.style.position = 'absolute';
343
- div.style.left = postionArr[0] * this.scale + 'px',
349
+ div.style.left = postionArr[0] * this.scale * CSS_UNITS + 'px',
344
350
  // 后端返回的坐标有基线对齐的问题,top 值是后端算好(基线top - 文字高度),在此加上文字高度的 1/9 (大致比例)为实际展示出文字的top值
345
- div.style.top = postionArr[1] * this.scale + 'px'
346
- div.style.height = postionArr[3] * this.scale + 'px';
347
- div.style.width = postionArr[2] * this.scale + 'px'
351
+ div.style.top = postionArr[1] * this.scale * CSS_UNITS + 'px'
352
+ div.style.height = postionArr[3] * this.scale * CSS_UNITS + 'px';
353
+ div.style.width = postionArr[2] * this.scale * CSS_UNITS + 'px'
348
354
  div.style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
349
355
  div.classList.add('lineHeight')
350
356
  rectdom.appendChild(div)
351
357
  if (index == 0 && j == 0) {
352
358
  if (this.transformSalce !== null) {
353
- rectdomTop = postionArr[1] * this.scale * this.transformSalce
359
+ rectdomTop = postionArr[1]* this.scale * this.transformSalce
354
360
  } else {
355
- rectdomTop = postionArr[1] * this.scale
361
+ rectdomTop = postionArr[1] * this.scale
356
362
  }
357
363
  // if(this.isPC) {
358
364
  // rectdomTop = rectdomTop - 50 < 0 ? 0 : rectdomTop - 50
@@ -376,26 +382,29 @@ export default {
376
382
  page.dom = await pageDom;
377
383
  page.loading = false
378
384
  this.contentView.appendChild(pageDom);
379
-
380
- if (this.transformSalce !== null) {
381
- if (this.fileName){
382
- this.contentView.style.transform = `scale(${this.transformSalce + 0.1}, ${this.transformSalce + 0.1})`;
383
- if (findPage){
384
- let AllLines = findPage.allLines;
385
- let postionArr = []
386
- if (AllLines.length){
387
- postionArr = AllLines[0].lines[0].location
388
- }
385
+ // 判断是否是doc/txt文件 pc端transform设置的比移动端小。pc端根据屏幕宽度字体大小已经够大。
386
+ if (this.fileName){
387
+ if (findPage){
388
+ let AllLines = findPage.allLines;
389
+ let postionArr = []
390
+ if (AllLines.length){
391
+ postionArr = AllLines[0].lines[0].location
392
+ }
393
+ if(this.transformSalce !== null){
389
394
  if (this.isPC){
390
- this.contentView.style.left = (postionArr[0] * this.scale * (this.transformSalce + 0.1) * -1) / 2 + 'px';
395
+ this.contentView.style.transform = `scale(${this.transformSalce - 0.1}, ${this.transformSalce - 0.1})`;
396
+ this.contentView.style.left = (postionArr[0] * this.scale * CSS_UNITS * (this.transformSalce) * -1) / 2+ 'px';
391
397
  } else {
392
- this.contentView.style.left = (postionArr[0] * this.scale * (this.transformSalce + 0.1) * -1) + 10 + 'px';
398
+ this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
399
+ this.contentView.style.left = (postionArr[0] * this.scale * CSS_UNITS * (this.transformSalce) * -1) + 10 + 'px';
393
400
  }
401
+ } else {
402
+ this.contentView.style.transform = 'scale(0.8)';
403
+ // this.contentView.style.left = ((postionArr[0] * this.scale) * -1)+ 'px';
394
404
  }
395
- } else {
396
- this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
397
405
  }
398
- // this.contentView.style.transform = `translate(${(AllLines[0].lines[0].location[0] * this.scale * -1) + 10 + 'px'})`
406
+ } else if(this.transformSalce !== null){
407
+ this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
399
408
  }
400
409
  if (this.changetoolbar) {
401
410
  setTimeout(() => {
@@ -545,10 +554,10 @@ export default {
545
554
  return
546
555
  }
547
556
  const pageDom = document.createElement('div');
548
- pageDom.style.width = `${this.pageSize.width}px`;
549
- pageDom.style.height = `${this.pageSize.height}px`;
557
+ pageDom.style.width = `${this.pageSize.width * CSS_UNITS}px`;
558
+ pageDom.style.height = `${this.pageSize.height * CSS_UNITS}px`;
550
559
  pageDom.style.position = 'absolute';
551
- pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL
560
+ pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * CSS_UNITS) + this.PAGE_INTVERVAL
552
561
  }px`;
553
562
  pageDom.style.backgroundImage = `url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif')`
554
563
  pageDom.style.backgroundPosition = 'center'
@@ -625,7 +634,7 @@ export default {
625
634
  if (this.transformSalce !== null) {
626
635
  this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce) + (this.identifyTextPostion.top * this.scale * this.transformSalce)}`
627
636
  } else {
628
- this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + (this.identifyTextPostion.top * this.scale * this.transformSalce)}`
637
+ this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + (this.identifyTextPostion.top * this.scale)}`
629
638
  }
630
639
  },
631
640
  scrollToExcalTop (currentPage) {
@@ -879,6 +888,7 @@ export default {
879
888
  if (value && value.length) {
880
889
  // 在 pdf_view 下创建 所有canvs的容器
881
890
  this.contentView = document.createElement('div')
891
+ this.contentView.setAttribute('id','contentView')
882
892
  this.contentView.style.transformOrigin = '0px 0px 0px'
883
893
  this.$http.get('/knowledge-api/knowledge/knowledge-part-location-info/list?ids=' + value.join(',')).then(res => {
884
894
  // res.data = {"data":[{"id":"64591b7d8bb8ab1b91c65f24","knowledgeId":"64591a9c8da27649473f3b4b","mainId":"fb348d095c0b4fd7bbd37826563dac7d","page":3,"total":18,"pageHeight":540.0,"pageWidth":960.00946,"publicPageFileUrl":"https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/fb348d095c0b4fd7bbd37826563dac7d/2023/05/08/11/55/18/64591b638bb8ab1b91c65eed/3.pdf","extractInfo":{"location":[280.488,161.32,398.71573,61.99298],"content":"黄花城水长城旅游区位于北京市怀柔区九渡河镇境内,距北京市区65公里,是以奇而著称,融山川、碧水、古长城为一体的旅游休闲胜地。而这里的“三绝景”更是引人入","lines":[{"content":"黄花城水长城旅游区位于北京市怀柔区九渡河镇境内,距","location":[280.488,161.32,398.71573,15.9869995]},{"content":"北京市区65公里,是以奇而著称,融山川、碧水、古长","location":[283.691,184.30899,392.3055,15.9869995]},{"content":"城为一体的旅游休闲胜地。而这里的“三绝景”更是引人入","location":[282.699,207.32599,394.3033,15.9869995]}],"tagId":null}}],"code":"0","msg":null,"traceId":null}
@@ -127,7 +127,9 @@ export default {
127
127
  drawer(value) {
128
128
  if(value) {
129
129
  this.$nextTick(() =>{
130
- zoomElement(document.getElementById('drawer_content_pre'))
130
+ setTimeout(() => {
131
+ zoomElement(document.getElementById('contentView'))
132
+ },1000)
131
133
  })
132
134
  }
133
135
  }