askbot-dragon 1.5.44-beta → 1.5.47-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.
Files changed (87) hide show
  1. package/README.md +27 -27
  2. package/babel.config.js +6 -6
  3. package/dragon.iml +7 -7
  4. package/package.json +58 -58
  5. package/public/index.html +74 -74
  6. package/src/App.vue +31 -31
  7. package/src/api/index.js +1 -1
  8. package/src/api/mock.http +2 -2
  9. package/src/api/requestUrl.js +185 -185
  10. package/src/assets/js/AliyunlssUtil.js +92 -92
  11. package/src/assets/js/Base64Util.js +22 -22
  12. package/src/assets/js/common.js +11 -11
  13. package/src/assets/js/hammer.js +100 -100
  14. package/src/assets/js/script.js +36 -36
  15. package/src/assets/less/common.css +6773 -6773
  16. package/src/assets/less/converSationContainer/common.less +199 -192
  17. package/src/assets/less/converSationContainer/converSatonContainer.less +493 -493
  18. package/src/assets/less/iconfont.css +37 -37
  19. package/src/assets/less/ticketMessage.less +294 -294
  20. package/src/components/ActionAlertIframe.vue +112 -112
  21. package/src/components/AiGuide.vue +467 -467
  22. package/src/components/AnswerDocknowledge.vue +504 -499
  23. package/src/components/AnswerVoice.vue +285 -285
  24. package/src/components/AskIFrame.vue +15 -15
  25. package/src/components/ConversationContainer.vue +5120 -5120
  26. package/src/components/FileType.vue +86 -86
  27. package/src/components/Message.vue +27 -27
  28. package/src/components/actionSatisfaction.vue +107 -107
  29. package/src/components/actionSendToBot.vue +62 -62
  30. package/src/components/answerDissatisfaction.vue +62 -62
  31. package/src/components/answerRadio.vue +131 -131
  32. package/src/components/ask-components/DissatisfactionOptions.vue +57 -57
  33. package/src/components/ask-components/Msgloading.vue +37 -37
  34. package/src/components/ask-components/SatisfactionV2.vue +15 -15
  35. package/src/components/askVideo.vue +138 -138
  36. package/src/components/assetDetails.vue +370 -370
  37. package/src/components/assetMessage.vue +228 -228
  38. package/src/components/associationIntention.vue +349 -349
  39. package/src/components/attachmentPreview.vue +90 -90
  40. package/src/components/botActionSatisfactor.vue +68 -68
  41. package/src/components/chatContent.vue +513 -513
  42. package/src/components/feedBack.vue +136 -136
  43. package/src/components/fielListView.vue +351 -351
  44. package/src/components/file/AliyunOssComponents.vue +108 -108
  45. package/src/components/formTemplate.vue +3557 -3557
  46. package/src/components/kkview.vue +1138 -1138
  47. package/src/components/loadingProcess.vue +164 -164
  48. package/src/components/message/ActionAlertIframe.vue +112 -112
  49. package/src/components/message/ShopMessage.vue +164 -164
  50. package/src/components/message/TextMessage.vue +924 -924
  51. package/src/components/message/TicketMessage.vue +201 -201
  52. package/src/components/message/swiper/index.js +4 -4
  53. package/src/components/message/swiper/ticketSwiper.vue +503 -503
  54. package/src/components/message/swiper/ticketSwiperItem.vue +61 -61
  55. package/src/components/msgLoading.vue +231 -231
  56. package/src/components/myPopup.vue +70 -70
  57. package/src/components/newPdfPosition.vue +877 -877
  58. package/src/components/pdfPosition.vue +1362 -1360
  59. package/src/components/popup.vue +227 -227
  60. package/src/components/previewDoc.vue +242 -242
  61. package/src/components/previewPdf.vue +310 -313
  62. package/src/components/receiverMessagePlatform.vue +65 -65
  63. package/src/components/recommend.vue +89 -89
  64. package/src/components/selector/hOption.vue +20 -20
  65. package/src/components/selector/hSelector.vue +199 -199
  66. package/src/components/selector/hWrapper.vue +216 -216
  67. package/src/components/senderMessagePlatform.vue +50 -50
  68. package/src/components/source/BotMessage.vue +24 -24
  69. package/src/components/source/CustomMessage.vue +24 -24
  70. package/src/components/test.vue +260 -260
  71. package/src/components/tree.vue +294 -294
  72. package/src/components/utils/AliyunIssUtil.js +81 -81
  73. package/src/components/utils/ckeditor.js +174 -174
  74. package/src/components/utils/ckeditorImageUpload/command.js +109 -109
  75. package/src/components/utils/ckeditorImageUpload/editing.js +11 -11
  76. package/src/components/utils/ckeditorImageUpload/plugin-image.js +11 -11
  77. package/src/components/utils/ckeditorImageUpload/toolbar-ui.js +40 -40
  78. package/src/components/utils/ckeditorfileUpload/common.js +180 -180
  79. package/src/components/utils/ckeditorfileUpload/editing.js +11 -11
  80. package/src/components/utils/ckeditorfileUpload/plugin_file.js +11 -11
  81. package/src/components/utils/ckeditorfileUpload/toolbar_ui.js +34 -34
  82. package/src/components/utils/format_date.js +25 -25
  83. package/src/components/utils/index.js +6 -6
  84. package/src/components/utils/math_utils.js +29 -29
  85. package/src/components/voiceComponent.vue +119 -119
  86. package/src/main.js +60 -60
  87. package/vue.config.js +55 -55
@@ -1,1361 +1,1363 @@
1
- <template>
2
- <div class="pdf_view" ref="pdfView" @scroll="pdfScroll" :style="{
3
- marginTop: isPC ? '50px' : '',
4
- marginBottom: tagIds.length > 1 ? '60px' : '0px',
5
- height: setHeight
6
- }">
7
- <div class="change_scale" v-if="isPC">
8
- <section @click="changeScale('reduce')">
9
- <i class="el-icon-minus"></i>
10
- </section>
11
- <el-divider direction="vertical"></el-divider>
12
- <section @click="changeScale('zoom')">
13
- <i class="el-icon-plus"></i>
14
- </section>
15
- <el-select size="small" v-model="handScale" @change="changeScale" placeholder="请选择">
16
- <el-option v-for="item in scaleList" :key="item.value" :label="item.label" :value="item.value">
17
- </el-option>
18
- </el-select>
19
- </div>
20
- <div class="btn_footer" v-if="tagIds.length > 1 && !isPC">
21
- <div class="prev" @click="prev">上一段</div>
22
- <div class="next" @click="next">下一段</div>
23
- </div>
24
- <div id="pagination" v-if="tagIds.length > 1 && isPC">
25
- <el-pagination :current-page="currentPage + 1" @current-change="currentChange" @prev-click="prev"
26
- @next-click="next" layout="slot, prev, pager, next" :page-size="1" :total="tagIds.length">
27
- <span class="total-class">答案由{{ tagIds.length }}段内容生成</span>
28
- </el-pagination>
29
- </div>
30
- </div>
31
- </template>
32
-
33
- <script>
34
- import _ from 'lodash'
35
- // import * as pdfjsLib from 'pdfjs-dist'
36
- // pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker';
37
- // import { TextLayerBuilder } from "pdfjs-dist/web/pdf_viewer";
38
- // EventBus pdf_viewer 支持绑定自定义事件,一版不做
39
- // import 'pdfjs-dist/web/pdf_viewer.css'
40
- /* eslint-disable */
41
- const pdfjsLib = window['pdfjsLib']
42
- if (pdfjsLib) {
43
- pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
44
- // 'pdfjs-dist/build/pdf.worker';
45
- }
46
- const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
47
- const CSS_UNITS = 96.0 / 72.0
48
- // import { zoomElement } from '../assets/js/hammer'
49
- export default {
50
- name: 'pdfView',
51
- props: ['tagIds', 'isMessageRecord','fileName'],
52
- data () {
53
- return {
54
- url: '',
55
- pages: [],
56
- pageLoadStatus: {
57
- WAIT: 0,
58
- LOADED: 1,
59
- },
60
- scale: 1,
61
- rotation: 0,
62
- pageSize: {},
63
- PAGE_INTVERVAL: 15,
64
- SLICE_COUNT: 5,
65
- contentView: null,
66
- fisrtLoad: true,
67
- TextLayerBuilder: null,
68
- totalPageCount: 0,
69
- identifyTextPostion: {
70
- top: 0,
71
- left: 0,
72
- width: 100,
73
- height: 0,
74
- page: 1,
75
- pageHeight: 0,
76
- pageWidth: 0,
77
- extractInfo: {},
78
- currentPageAllLine: []
79
- },
80
- currentPageAllLine: [],
81
- pdfUrl: '',
82
- cachePdf: [],
83
- newViewer: null,
84
- currentPage: 0,
85
- changetoolbar: false,
86
- allTr: [],
87
- preViewType: 'pdf',
88
- displacement: {
89
- pageX: 0,
90
- pageY: 0,
91
- moveable: false,
92
- pageX2: 0,
93
- pageY2: 0,
94
- originScale: 1,
95
- },
96
- isTouchMoved: false,
97
- transformSalce: null,
98
- isPC: false,
99
- handScale: 'auto',
100
- scaleList: [
101
- {
102
- label: '自动缩放',
103
- value: 'auto'
104
- },
105
- {
106
- label: '实际比例',
107
- value: 'reality'
108
- },
109
- {
110
- label: '100%',
111
- value: 1
112
- },
113
- {
114
- label: '120%',
115
- value: 1.2
116
- },
117
- {
118
- label: '150%',
119
- value: 1.5
120
- },
121
- {
122
- label: '170%',
123
- value: 1.7
124
- }
125
- ,
126
- {
127
- label: '200%',
128
- value: 2
129
- }
130
- ],
131
- scrollTop: 0,
132
- scrollLeft: 0
133
- }
134
- },
135
- methods: {
136
- getpdfResloutePage (pdfResloute) {
137
- // 根据当前页面宽度设置缩放比例
138
- // this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
139
- if (this.isMessageRecord) {
140
- this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
141
- } else {
142
- this.scale = 2
143
- }
144
- // 从后端获取到当前分片后所有的pdf页码,初始化数组,数组下{} 对应每页pdf文件
145
- this.pdfUrl = pdfResloute.publicPageFileUrl.substring(0, pdfResloute.publicPageFileUrl.lastIndexOf('/') + 1)
146
- this.initPages(pdfResloute.total)
147
- // 定位功能,加载对应页码位置
148
- this.loadPdfData(pdfResloute.page)
149
- },
150
- async loadPdfData (loadPage) {
151
- if (this.pages[loadPage - 1] && ((this.pages[loadPage - 1].dom && this.pages[loadPage - 1].dom.children.length > 0) || this.pages[loadPage - 1].loadStatus)) {
152
- return
153
- } else {
154
- if (this.changetoolbar) {
155
- this.$nextTick(() => {
156
- this.renderHighlights()
157
- })
158
- this.changetoolbar = false
159
- }
160
- }
161
- // 记录开始缓存的状态
162
- // pdfjsLib.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/legacy/build/pdf.worker.entry.js");
163
- // 拿到第一个分片
164
- const { startPage, url } = await this.fetchPdfFragment(loadPage);
165
- let loadingTask = pdfjsLib.getDocument(url)
166
- loadingTask.promise.then(async (pdfDoc) => {
167
- // 将已经下载的分片保存到 pages 数组中
168
- // for (let i = 0; i < pdfDoc.numPages; i += 1) {
169
- // const pageIndex = startPage + i;
170
- // const page = this.pages[pageIndex - 1];
171
- // // // 不在缓存列表内,重新获取本页pdf
172
- // // if (page.loadStatus !== this.pageLoadStatus.LOADED) {
173
-
174
- // // } else {
175
- // // if (this.changetoolbar) {
176
- // // this.$nextTick(() => {
177
- // // this.renderHighlights()
178
- // // })
179
- // // this.changetoolbar = false
180
- // // }
181
- // // }
182
- // }
183
- const page = this.pages[loadPage - 1]
184
- await pdfDoc.getPage(1).then(async (pdfPage) => {
185
- this.pages[loadPage - 1].loadStatus = true
186
- this.pages[loadPage - 1].pdfPage = pdfPage;
187
- // 通知可以进行渲染了
188
- await this.startRenderPages(pdfPage, page, loadPage)
189
- });
190
- });
191
- },
192
- initPages (totalPage) {
193
- // const pages = [];
194
- this.totalPageCount = totalPage
195
- for (let i = 0; i < totalPage; i += 1) {
196
- this.pages.push({
197
- pageNo: i + 1,
198
- loadStatus: false,
199
- pdfPage: null,
200
- dom: null
201
- });
202
- }
203
- },
204
- async fetchPdfFragment (pageIndex) {
205
- // 置换加签后的文件地址。
206
- let obj = {}
207
- await this.$http.post(
208
- '/knowledge-api/temporary-certificate/or-origin?expired=30',
209
- this.pdfUrl + pageIndex + '.pdf',
210
- {
211
- headers: {
212
- "Content-Type": "application/json",
213
- },
214
- }).then(async res => {
215
- if (res.bodyText) {
216
- // 最后返回一个 包含这4个参数的对象
217
- obj = await {
218
- "startPage": pageIndex, // 分片的开始页码
219
- "endPage": pageIndex + 5, // 分片结束页码
220
- "totalPage": this.totalPageCount, // pdf 总页数
221
- "url": res.bodyText // 分片内容下载地址
222
- }
223
- }
224
- if (res.data) {
225
- // 最后返回一个 包含这4个参数的对象
226
- obj = await {
227
- "startPage": pageIndex, // 分片的开始页码
228
- "endPage": pageIndex + 5, // 分片结束页码
229
- "totalPage": this.totalPageCount, // pdf 总页数
230
- "url": res.data // 分片内容下载地址
231
- }
232
- }
233
- })
234
- return obj
235
- },
236
- startRenderPages (pdfPage, page, pageIndex) {
237
- if (Object.keys(this.pageSize).length == 0) {
238
- const viewport = pdfPage.getViewport({
239
- scale: this.scale, // 缩放的比例
240
- rotation: this.rotation, // 旋转的角度
241
- });
242
- // 记录pdf页面高度
243
- const pageSize = {
244
- width: viewport.width,
245
- height: viewport.height,
246
- }
247
- this.pageSize = pageSize
248
- // 创建内容绘制区,并设置大小
249
- if (this.$refs.pdfView.clientWidth / this.pageSize.width >= 1 || this.isMessageRecord) {
250
- this.contentView.style.width = `${pageSize.width - 10}px`;
251
- this.contentView.style.height = `${(this.totalPageCount * (pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
252
- } else {
253
- this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
254
- this.contentView.style.width = `${pageSize.width * this.transformSalce - 10}px`;
255
- this.contentView.style.height = `${(this.totalPageCount * (pageSize.height * (this.transformSalce) + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
256
- }
257
- this.contentView.style.margin = '0 auto 0'
258
- this.contentView.style.position = 'relative'
259
- this.contentView.style.paddingBottom = '60px'
260
- // contentView.style.overflowY = 'auto'
261
- this.$refs.pdfView.appendChild(this.contentView);
262
- }
263
- this.renderPages(pageIndex)
264
- },
265
- // 渲染需要展示的页面,不需展示的页码将其清除
266
- renderPages (pageIndex) {
267
- const pagesToRender = this.getRenderScope(pageIndex);
268
- for (const i of this.pages) {
269
- if (pagesToRender.some(p => { return p.pageNo == i.pageNo })) {
270
- if (i.loadStatus === true) {
271
- this.renderPageContent(i, i.pageNo)
272
- } else {
273
- this.renderPageLoading(i, i.pageNo)
274
- }
275
- } else {
276
- this.clearPage(i);
277
- }
278
- }
279
-
280
- },
281
- async renderPageContent (page, pageIndex) {
282
- const { pdfPage, pageNo, dom } = page;
283
- // dom 元素已存在,无须重新渲染,直接返回
284
- if ((dom && dom.children.length != 0) || page.loading) {
285
- return;
286
- }
287
- page.loading = true
288
- const viewport = pdfPage.getViewport({
289
- scale: this.scale,
290
- rotation: this.rotation,
291
- });
292
- // 创建新的canvas
293
- const canvas = document.createElement('canvas');
294
- const context = canvas.getContext('2d');
295
- // canvas.getContext('2d');
296
- canvas.height = this.pageSize.height * (this.fileName ? CSS_UNITS : 1);
297
- canvas.width = this.pageSize.width * (this.fileName ? CSS_UNITS : 1);
298
- canvas.style.position = 'relative'
299
- canvas.style.top = -3 + 'px'
300
- // 创建渲染的dom
301
- const pageDom = document.createElement('div');
302
- pageDom.style.position = 'absolute';
303
- pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * (this.fileName ? CSS_UNITS : 1)) + this.PAGE_INTVERVAL}px`;
304
- pageDom.style.width = `${this.pageSize.width * (this.fileName ? CSS_UNITS : 1)}px`;
305
- pageDom.style.height = `${this.pageSize.height * (this.fileName ? CSS_UNITS : 1)}px`;
306
- pageDom.setAttribute('data-id', 'page' + pageNo)
307
- // pageDom.appendChild(canvas);
308
- // 渲染内容
309
- let renderContext = {
310
- canvasContext: context,
311
- viewport: viewport,
312
- transform: this.fileName ? [CSS_UNITS, 0, 0, CSS_UNITS, 0, 0] : '',
313
- }
314
- await pdfPage.render(renderContext).promise.then(() => {
315
- const html = canvas.toDataURL();
316
- let image = document.createElement('img');
317
- image.setAttribute('src',html)
318
- pageDom.appendChild(image);
319
- return pdfPage.getTextContent()
320
- }).then(async (textContent) => {
321
- const textLayerDiv = document.createElement('div');
322
- textLayerDiv.setAttribute('class', 'textLayer');
323
- // 将文本图层div添加至每页pdf的div中
324
- // 创建新的TextLayerBuilder实例
325
- let textLayer = new TextLayerBuilder({
326
- textLayerDiv: textLayerDiv,
327
- pageIndex: pdfPage._pageIndex,
328
- viewport: viewport,
329
- });
330
- let findPage = this.currentPageAllLine.find(l => { return l.page == pageIndex })
331
- let rectdomTop = 0
332
- if (findPage) {
333
- let AllLines = findPage.allLines
334
- // setTimeout(() => {
335
- if (AllLines.length > 0) {
336
- for (let j = 0; j < AllLines.length; j++) {
337
- let lines = AllLines[j].lines
338
- let rectdom = document.createElement('div')
339
- rectdom.setAttribute('react-count', AllLines[j].pageCount);
340
- rectdom.style.position = 'absolute';
341
- rectdom.style.top = 0
342
- rectdom.style.left = 0
343
- rectdom.classList.add('rectdom')
344
- for (let index = 0; index < lines.length; index++) {
345
- if (!/^\s+$/g.test(lines[index].content)) {
346
- let postionArr = lines[index].location
347
- let div = document.createElement('div')
348
- div.style.position = 'absolute';
349
- div.style.left = postionArr[0] * this.scale * (this.fileName ? CSS_UNITS : 1) + 'px',
350
- // 后端返回的坐标有基线对齐的问题,top 值是后端算好(基线top - 文字高度),在此加上文字高度的 1/9 (大致比例)为实际展示出文字的top值
351
- div.style.top = postionArr[1] * this.scale * (this.fileName ? CSS_UNITS : 1) + 'px'
352
- div.style.height = postionArr[3] * this.scale * (this.fileName ? CSS_UNITS : 1) + 'px';
353
- div.style.width = postionArr[2] * this.scale * (this.fileName ? CSS_UNITS : 1) + 'px'
354
- div.style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
355
- div.classList.add('lineHeight')
356
- rectdom.appendChild(div)
357
- if (index == 0 && j == 0) {
358
- if (this.transformSalce !== null) {
359
- rectdomTop = postionArr[1]* this.scale * this.transformSalce
360
- } else {
361
- rectdomTop = postionArr[1] * this.scale
362
- }
363
- // if(this.isPC) {
364
- // rectdomTop = rectdomTop - 50 < 0 ? 0 : rectdomTop - 50
365
- // }
366
- }
367
- }
368
- }
369
- if (rectdom.children.length > 0) {
370
- pageDom.appendChild(rectdom)
371
- }
372
- }
373
- }
374
- }
375
- textLayer.setTextContent(textContent);
376
- textLayer.render()
377
- pageDom.appendChild(textLayerDiv);
378
- let backgroundDom = document.getElementById('backgroundLoad' + pageNo)
379
- if (backgroundDom) {
380
- this.contentView.removeChild(backgroundDom);
381
- }
382
- page.dom = await pageDom;
383
- page.loading = false
384
- this.contentView.appendChild(pageDom);
385
- let pdf_view = document.getElementsByClassName('pdf_view');
386
- if (pdf_view && pdf_view[0]){
387
- pdf_view[0].style.backgroundImage = 'none'
388
- }
389
- // 判断是否是doc/txt文件 pc端transform设置的比移动端小。pc端根据屏幕宽度字体大小已经够大。
390
- if (this.fileName){
391
- if (findPage){
392
- let AllLines = findPage.allLines;
393
- let postionArr = []
394
- if (AllLines.length){
395
- postionArr = AllLines[0].lines[0].location
396
- }
397
- if(this.transformSalce !== null){
398
- if (this.isPC){
399
- this.contentView.style.transform = `scale(${this.transformSalce - 0.1}, ${this.transformSalce - 0.1})`;
400
- this.contentView.style.left = (postionArr[0] * this.scale * CSS_UNITS * (this.transformSalce) * -1) / 2+ 'px';
401
- } else {
402
- this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
403
- this.contentView.style.left = (postionArr[0] * this.scale * CSS_UNITS * (this.transformSalce) * -1) + 10 + 'px';
404
- }
405
- } else {
406
- this.contentView.style.transform = 'scale(0.8)';
407
- // this.contentView.style.left = ((postionArr[0] * this.scale) * -1)+ 'px';
408
- }
409
- }
410
- } else if(this.transformSalce !== null){
411
- this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
412
- }
413
- if (this.changetoolbar) {
414
- setTimeout(() => {
415
- this.renderHighlights()
416
- this.changetoolbar = false
417
- }, 500)
418
- }
419
- if (this.fisrtLoad) {
420
- setTimeout(() => {
421
- let pageoffsetHeight = 0
422
- if (this.transformSalce !== null) {
423
- pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce
424
- } else {
425
- pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL)
426
- }
427
- if (this.$refs.pdfView.clientHeight - pageoffsetHeight > 0 && pageIndex == 1) {
428
- const height = this.$refs.pdfView.clientHeight;
429
- let startNum = 0
430
- let endNum = 0
431
- if (this.transformSalce !== null) {
432
- startNum = Math.ceil(this.$refs.pdfView.scrollTop / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
433
- endNum = startNum + Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
434
- } else {
435
- startNum = Math.ceil(this.$refs.pdfView.scrollTop / (this.pageSize.height + this.PAGE_INTVERVAL))
436
- endNum = startNum + Math.ceil(height / (this.pageSize.height + this.PAGE_INTVERVAL))
437
- }
438
- for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
439
- if (pageIndex > 0 && pageIndex <= this.pages.length) {
440
- this.loadPdfData(pageIndex)
441
- }
442
- }
443
- }
444
- if (this.$refs.pdfView.scrollTop == Math.floor((pageNo - 1) * pageoffsetHeight)) {
445
- this.$refs.pdfView.scrollTop = rectdomTop
446
- this.fisrtLoad = false
447
- } else {
448
- this.$refs.pdfView.scrollTop = `${((pageNo - 1) * pageoffsetHeight) + rectdomTop - this.PAGE_INTVERVAL}`
449
- this.fisrtLoad = false
450
- }
451
- this.renderHighlights()
452
- // zoomElement(this.contentView)
453
- }, 100)
454
- }
455
- })
456
- },
457
- // 监听容器的滚动事件,触发 scrollPdf 方法
458
- // 这里加了防抖保证不会一次产生过多请求
459
- debounceScrollPdf: _.debounce(function (e, that) {
460
- if (this.fisrtLoad) {
461
- this.fisrtLoad = false
462
- return
463
- }
464
- const scrollTop = e.target.scrollTop;
465
- const height = e.target.clientHeight;
466
- let startNum = 0
467
- let endNum = 0
468
- if (this.transformSalce !== null) {
469
- startNum = Math.ceil(scrollTop / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
470
- endNum = startNum + Math.ceil(height / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
471
- } else {
472
- startNum = Math.ceil(scrollTop / (that.pageSize.height + that.PAGE_INTVERVAL))
473
- endNum = startNum + Math.ceil(height / (that.pageSize.height + that.PAGE_INTVERVAL))
474
- }
475
- for (let pageIndex = startNum; pageIndex < endNum; pageIndex++) {
476
- if (pageIndex > 0 && pageIndex <= that.pages.length) {
477
- that.loadPdfData(pageIndex)
478
- }
479
- }
480
- }, 200),
481
- directScrolling (e, that) {
482
- if (this.fisrtLoad) {
483
- this.fisrtLoad = false
484
- return
485
- }
486
- const scrollTop = e.target.scrollTop;
487
- const height = e.target.clientHeight;
488
- // 根据内容可视区域中心点计算页码, 没有滚动时,指向第一页
489
- const pageIndex = scrollTop > 0 ?
490
- Math.ceil((scrollTop + (height / 2)) / (that.pageSize.height + that.PAGE_INTVERVAL)) :
491
- 1;
492
- this.loadPdfData(pageIndex)
493
- },
494
- pdfScroll (e) {
495
- if (this.preViewType !== 'pdf' || this.isTouchMoved) {
496
- return
497
- }
498
- if (this.scrollLeft != e.target.scrollLeft) {
499
- this.scrollLeft = e.target.scrollLeft
500
- }
501
- if (this.scrollTop != e.target.scrollTop) {
502
- this.scrollTop = e.target.scrollTop
503
- this.debounceScrollPdf(e, this)
504
- }
505
- },
506
- // 分片每次只做一次处理,所以不考虑多片情况
507
- loadBefore (pageIndex) {
508
- this.loadPdfData(pageIndex)
509
- },
510
- loadAfter (pageIndex) {
511
- this.loadPdfData(pageIndex)
512
- },
513
- // 首先我们获取到需要渲染的范围
514
- // 根据当前的可视范围内的页码,我们前后只保留 8
515
- getRenderScope (pageIndex) {
516
- const pagesToRender = [];
517
- let i = pageIndex - 1;
518
- let j = pageIndex + 1;
519
- // pageIndex - 1 表示当前页码数 对应的下标位置
520
- pagesToRender.push(this.pages[pageIndex - 1]);
521
- while (pagesToRender.length < 8 && pagesToRender.length < this.pages.length) {
522
- if (i > 0) {
523
- pagesToRender.push(this.pages[i - 1]);
524
- i -= 1;
525
- }
526
- if (pagesToRender.length >= 8) {
527
- break;
528
- }
529
- if (j <= this.pages.length) {
530
- pagesToRender.push(this.pages[j - 1]);
531
- j += 1;
532
- }
533
- }
534
- // for (let index = 0; index < array.length; index++) {
535
- // const element = array[index];
536
-
537
- // }
538
- return pagesToRender;
539
- },
540
-
541
- // 清除页面 dom
542
- clearPage (page) {
543
- if (this.contentView.contains(page.dom) && page.dom) {
544
- this.contentView.removeChild(page.dom);
545
- page.loadStatus = false
546
- page.loading = false
547
- page.dom = undefined;
548
- }
549
- },
550
- // 页面正在下载时渲染loading视图
551
- renderPageLoading (page) {
552
- const { pageNo, dom } = page;
553
- if (dom && dom.children.length != 0) {
554
- return;
555
- }
556
- let backgroundDom = document.getElementById('backgroundLoad' + pageNo)
557
- if (this.contentView.contains(backgroundDom)) {
558
- return
559
- }
560
- const pageDom = document.createElement('div');
561
- pageDom.style.width = `${this.pageSize.width * (this.fileName ? CSS_UNITS : 1)}px`;
562
- pageDom.style.height = `${this.pageSize.height * (this.fileName ? CSS_UNITS : 1)}px`;
563
- pageDom.style.position = 'absolute';
564
- pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * (this.fileName ? CSS_UNITS : 1)) + this.PAGE_INTVERVAL
565
- }px`;
566
- pageDom.style.backgroundImage = `url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif')`
567
- pageDom.style.backgroundPosition = 'center'
568
- pageDom.style.backgroundRepeat = 'no-repeat'
569
- pageDom.style.backgroundColor = '#FFF'
570
- pageDom.setAttribute('id', 'backgroundLoad' + pageNo)
571
- page.dom = pageDom;
572
- this.contentView.appendChild(pageDom);
573
- },
574
- prev () {
575
- this.currentPage--
576
- if (this.currentPage < 0) {
577
- this.currentPage = 0
578
- if (!this.isPC) {
579
- this.$toast({
580
- message: '当前已经是第一段了',
581
- duration: 2000,
582
- })
583
- return
584
- }
585
- }
586
- if (this.preViewType == 'pdf') {
587
- this.scrollToUplaodePage(this.currentPage)
588
- } else {
589
- this.scrollToExcalTop(this.currentPage)
590
- }
591
- // this.getpdfResloutePage(this.cachePdf[this.currentPage - 1])
592
- },
593
- next () {
594
- this.currentPage++
595
- if (this.currentPage >= this.tagIds.length) {
596
- this.currentPage = this.tagIds.length - 1
597
- if (!this.isPC) {
598
- this.$toast({
599
- message: '当前已经是最后一段了',
600
- duration: 2000,
601
- })
602
- return
603
- }
604
- }
605
- if (this.preViewType == 'pdf') {
606
- this.scrollToUplaodePage(this.currentPage)
607
- } else {
608
- this.scrollToExcalTop(this.currentPage)
609
- }
610
- },
611
- currentChange (value) {
612
- this.currentPage = value - 1
613
- if (this.preViewType == 'pdf') {
614
- this.scrollToUplaodePage(this.currentPage)
615
- } else {
616
- this.scrollToExcalTop(this.currentPage)
617
- }
618
- },
619
- scrollToUplaodePage (currentPage) {
620
- this.changetoolbar = true
621
- if (this.preViewType !== 'pdf') {
622
- return
623
- }
624
-
625
- let pdfResloute = this.cachePdf[currentPage]
626
- this.identifyTextPostion.extractInfo = pdfResloute.extractInfo
627
- this.identifyTextPostion.left = pdfResloute.extractInfo.location[0]
628
- this.identifyTextPostion.top = pdfResloute.extractInfo.location[1]
629
- this.identifyTextPostion.width = pdfResloute.extractInfo.location[2]
630
- this.identifyTextPostion.height = pdfResloute.extractInfo.location[3]
631
- this.identifyTextPostion.page = pdfResloute.page
632
- this.identifyTextPostion.pageHeight = pdfResloute.pageHeight
633
- this.identifyTextPostion.pageWidth = pdfResloute.pageWidth
634
- // 在当前段落在最后一页pdf时,根据计算的高度并不能触发滚动,在此执行重新渲染方法,非次情况会执行两次,待优化
635
- this.$nextTick(() => {
636
- this.renderHighlights()
637
- })
638
- if (this.transformSalce !== null) {
639
- this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce) + (this.identifyTextPostion.top * this.scale * this.transformSalce)}`
640
- } else {
641
- this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + (this.identifyTextPostion.top * this.scale)}`
642
- }
643
- },
644
- scrollToExcalTop (currentPage) {
645
- for (let index = 0; index < this.allTr.length; index++) {
646
- if (index == currentPage) {
647
- Array.from(this.allTr[index].children).forEach(item => {
648
- item.style.background = 'rgba(255, 136, 0, 0.6)'
649
- item.classList.add('animation')
650
- setTimeout(() => {
651
- item.classList.remove('animation')
652
- }, 4000)
653
- })
654
- // getBoundingClientRect().top 当前元素距离屏幕顶部的高度 + 弹窗header 高度
655
- if (!this.isPC) {
656
- let top = this.allTr[index].getBoundingClientRect().top - this.$refs.pdfView.getBoundingClientRect().top
657
- this.$refs.pdfView.scrollTop = top
658
- } else {
659
- let top = this.allTr[index].getBoundingClientRect().top
660
- this.$refs.pdfView.scrollTop = top - 50
661
- }
662
- } else {
663
- Array.from(this.allTr[index].children).forEach(item => {
664
- item.style.background = 'rgba(54, 106, 255, 0.6)'
665
- item.classList.remove('animation')
666
- })
667
- }
668
- }
669
- },
670
- // pdf是否需要重新渲染高亮位置
671
- renderHighlights () {
672
- let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
673
- if (lineHeightDom) {
674
- lineHeightDom.forEach((d) => {
675
- for (let i = 0; i < d.children.length; i++) {
676
- if (d.getAttribute('react-count') == this.currentPage) {
677
- d.children[i].style.backgroundColor = 'rgba(255, 136, 0, 0.3)'
678
- d.children[i].classList.add('animation')
679
- setTimeout(() => {
680
- d.children[i].classList.remove('animation')
681
- }, 4000)
682
- } else {
683
- d.children[i].style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
684
- d.children[i].classList.remove('animation')
685
- }
686
- }
687
- })
688
- }
689
- },
690
- displayHiglight (pageIndex) {
691
- let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
692
- if (lineHeightDom) {
693
- lineHeightDom.forEach((d) => {
694
- if (d.getAttribute('page-index') == pageIndex) {
695
- d.style.display = 'none'
696
- }
697
- })
698
- }
699
- },
700
- // 前端暂时缓存多页
701
- autoLoadMore (pageIndex) {
702
- let pdfResloute = this.cachePdf.find(cache => {
703
- return cache.page == pageIndex
704
- })
705
- if (pdfResloute) {
706
- this.getpdfResloutePage(pdfResloute)
707
- } else {
708
- this.loadPdfData(pageIndex)
709
- }
710
- },
711
- setPageAllLine (arr) {
712
- this.currentPageAllLine = []
713
- arr.forEach((item, index) => {
714
- let i = this.currentPageAllLine.findIndex(l => { return l.page && l.page == item.page })
715
- if (i != -1) {
716
- // this.currentPageAllLine[i].allLines.lines.push(item.extractInfo.lines)
717
- this.currentPageAllLine[i].allLines.push({
718
- pageCount: index,
719
- lines: item.extractInfo.lines
720
- })
721
- } else {
722
- this.currentPageAllLine.push({
723
- page: item.page,
724
- allLines: [{
725
- pageCount: index,
726
- lines: item.extractInfo.lines
727
- }],
728
- })
729
- }
730
- })
731
- },
732
- openTouch () {
733
- // this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
734
- let that = this;
735
- this.$nextTick(() => {
736
- // setInterval(() => {
737
- // this.scale = this.scale + 0.1
738
- // that.pages.forEach((item, index) =>{
739
- // if(item.dom) {
740
- // item.dom.children.forEach( childDom =>{
741
- // if(childDom.getAttribute('react-count')) {
742
- // childDom.style.transform = "scale(" + this.scale + ")";
743
- // childDom.style.transformOrigin = "0px 0px 0px";
744
- // } else {
745
- // item.dom = null
746
- // this.startRenderPages(item.pdfPage, null, index)
747
- // }
748
- // } )
749
- // }
750
- // })
751
- // }, 100);
752
- // 获取放大或缩小的区域DOM
753
- let matrix_box = this.contentView
754
- matrix_box.addEventListener("touchstart", function (event) {
755
- this.isTouchMoved = true
756
- let touches = event.touches;
757
- let events = touches[0];
758
- let events2 = touches[1];
759
-
760
- // event.preventDefault();
761
-
762
- // 第一个触摸点的坐标
763
- that.displacement.pageX = events.pageX;
764
- that.displacement.pageY = events.pageY;
765
-
766
- that.displacement.moveable = true;
767
-
768
- if (events2) {
769
- that.displacement.pageX2 = events2.pageX;
770
- that.displacement.pageY2 = events2.pageY;
771
- }
772
-
773
- that.displacement.originScale = this.scale || 1;
774
- });
775
- document.addEventListener("touchmove", function (event) {
776
- if (!that.displacement.moveable) {
777
- return;
778
- }
779
- // event.preventDefault();
780
- let touches = event.touches;
781
- let events = touches[0];
782
- let events2 = touches[1];
783
- // 双指移动
784
- if (events2) {
785
- // 第2个指头坐标在touchmove时候获取
786
- if (!that.displacement.pageX2) {
787
- that.displacement.pageX2 = events2.pageX;
788
- }
789
- if (!that.displacement.pageY2) {
790
- that.displacement.pageY2 = events2.pageY;
791
- }
792
- // 双指缩放比例计算
793
- let zoom = that.getDistance({
794
- x: events.pageX,
795
- y: events.pageY
796
- },
797
- {
798
- x: events2.pageX,
799
- y: events2.pageY
800
- }
801
- ) / that.getDistance(
802
- {
803
- x: that.displacement.pageX,
804
- y: that.displacement.pageY
805
- },
806
- {
807
- x: that.displacement.pageX2,
808
- y: that.displacement.pageY2
809
- }
810
- );
811
- // 应用在元素上的缩放比例
812
- let newScale = that.displacement.originScale * zoom;
813
- // 最大缩放比例限制
814
- if (newScale > 2) {
815
- newScale = 2;
816
- }
817
- // 最大缩放比例限制
818
- if (newScale < 1) {
819
- newScale = 1;
820
- }
821
- // 记住使用的缩放值
822
- that.displacement.scale = newScale;
823
- // console.log(newScale);
824
- matrix_box.style.transform = "scale(" + newScale + ")";
825
- // 设置旋转元素的基点位置
826
- matrix_box.style.transformOrigin = "0px 0px 0px";
827
- }
828
- }, { passive: false });
829
- document.addEventListener('touchend', function () {
830
- that.isTouchMoved = false
831
- }, { passive: false })
832
- });
833
- },
834
- getDistance (start, stop) {
835
- // Math.hypot()计算参数的平方根
836
- return Math.hypot(stop.x - start.x, stop.y - start.y);
837
- },
838
- setupCanvas (canvas, width, height) {
839
- const dpr = 1;
840
- // const rect = canvas.getBoundingClientRect();
841
- canvas.width = width
842
- canvas.height = height
843
- const ctx = canvas.getContext('2d');
844
- ctx?.scale(dpr, dpr);
845
- return ctx;
846
- },
847
- changeScale (value) {
848
- if (value == 'zoom') {
849
- this.handScale = 'auto'
850
- this.transformSalce = (this.transformSalce + 0.2).toFixed(1)
851
- } else if (value == 'reduce') {
852
- if ((this.transformSalce - 0.2).toFixed(1) <= 0) {
853
- return
854
- }
855
- this.handScale = 'auto'
856
- this.transformSalce = (this.transformSalce - 0.2).toFixed(1)
857
- } else if (value == 'auto') {
858
- this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
859
- } else if (value == 'reality') {
860
- this.transformSalce = 0.5
861
- } else {
862
- this.transformSalce = (value / 2).toFixed(1)
863
- }
864
- this.transformSalce = Number(this.transformSalce)
865
- this.contentView.style.transform = 'scale(' + this.transformSalce + ')';
866
- // this.getpdfResloutePage(this.cachePdf[0])
867
- },
868
- },
869
- computed: {
870
- perviewUrl () {
871
- return '/web/viewer.html?file=' + '/pdflist/pdf4split-1.pdf'
872
- },
873
- setHeight () {
874
- if (this.tagIds.length > 1) {
875
- if (this.isPC) {
876
- return 'calc(100% - 110px)'
877
- } else {
878
- return 'calc(100% - 60px)'
879
- }
880
- } else {
881
- if (this.isPC) {
882
- return 'calc(100% - 50px)'
883
- } else {
884
- return '100%'
885
- }
886
- }
887
- }
888
- },
889
- watch: {
890
- tagIds: {
891
- handler (value) {
892
- if (value && value.length) {
893
- // pdf_view 下创建 所有canvs的容器
894
- this.contentView = document.createElement('div')
895
- this.contentView.setAttribute('id','contentView')
896
- this.contentView.style.transformOrigin = '0px 0px 0px'
897
- this.$http.get('/knowledge-api/knowledge/knowledge-part-location-info/list?ids=' + value.join(',')).then(res => {
898
- // 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}
899
- // res.data = {"data":[{"id":"64590ce1eb1320043401cc90","knowledgeId":"64590cd5017b461d67e282e1","mainId":"fb348d095c0b4fd7bbd37826563dac7d","page":2,"total":5,"pageHeight":841.8898,"pageWidth":595.30396,"publicPageFileUrl":"https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/fb348d095c0b4fd7bbd37826563dac7d/2023/05/08/10/53/20/64590ce0eb1320043401cc7b/2.pdf","extractInfo":{"location":[89.32981,638.1907,415.15512,98.63251],"content":":北京地铁 13\r号线 :藤黄\r色 :西直门站—\r东直门站 :17 :41.\r5 :6\r准\rB :2002年\r09月\r28日 ","lines":[{"content":":北京地铁 13\r号线 ","location":[89.32981,638.1907,99.44599,98.63251]},{"content":":藤黄\r色 ","location":[188.7758,638.1907,46.79959,98.63251]},{"content":":西直门站—\r东直门站 ","location":[235.5754,638.1907,86.09996,98.63251]},{"content":":17 ","location":[321.67535,638.1907,36.200012,98.63251]},{"content":":41.\r5 ","location":[357.87537,638.1907,39.400696,98.63251]},{"content":":6\r准\rB ","location":[397.27606,638.1907,41.099,98.63251]},{"content":":2002年\r09月\r28日 ","location":[438.37506,638.1907,66.10986,98.63251]}],"tagId":null}}],"code":"0","msg":null,"traceId":null}
900
- // 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}
901
- // res.data = {"data":[{"id":"6475eab868110215ab821a80","knowledgeId":"6475e7eac724c54c46cbfa2d","mainId":"5ecf2fcd704541149201ab9c1c31162d","page":0,"total":1,"pageHeight":0.0,"pageWidth":0.0,"publicPageFileUrl":"https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/5ecf2fcd704541149201ab9c1c31162d/2023/05/30/08/23/20/6475eab63339db423f26b196/0.html","extractInfo":{"location":null,"content":"产品:系统配置,产品型号:存储,VX30:4G+16G,VX50:16G+256G","lines":null,"tagId":"6475eab868110215ab821a80"}}],"code":"0","msg":null,"traceId":null}
902
- // res.data = {"data":[{"id":"6475e9393339db423f26af01","knowledgeId":"6475e44fc724c54c46cbfa21","mainId":"5ecf2fcd704541149201ab9c1c31162d","page":2,"total":2,"pageHeight":510.25,"pageWidth":1559.05,"publicPageFileUrl":"https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/5ecf2fcd704541149201ab9c1c31162d/2023/05/30/08/00/29/6475e55d3339db423f26a9b8/2.pdf","extractInfo":{"location":[327.70532,288.0498,414.9734,12.241608],"content":"三、指示灯状态说明1.白色常亮:开机/开机中2.红色常亮:待机3.白色呼吸:息屏4.红色闪烁:升级1.LAN:通过网线连接到主机的Camera端口2.电源开关:电源切换开关","lines":[{"content":"三、指示灯状态说明","location":[634.3203,288.0498,108.3584,12.0]},{"content":"1.白色常亮:开机/开机中","location":[634.3203,320.08978,108.23407,9.0]},{"content":"2.红色常亮:待机","location":[634.3204,341.3298,78.597046,9.0]},{"content":"3.白色呼吸:息屏","location":[634.32043,362.45282,78.597046,9.0]},{"content":"4.红色闪烁:升级","location":[634.3205,383.6928,78.597046,9.0]},{"content":"1.LAN:通过网线连接到主机的","location":[327.70535,291.2914,144.35995,9.0]},{"content":"Camera端口","location":[327.70532,306.88843,55.322998,9.0]},{"content":"2.电源开关:电源切换开关","location":[482.74832,291.2914,105.36301,9.0]}],"tagId":null}}],"code":"0","msg":null,"traceId":null}
903
- // if(value.length === 1) {
904
- // this.$refs.pdfView.style.height = 'calc(100% - 50px)'
905
- // }
906
- // res.data = {
907
- // "data": [
908
- // {
909
- // "id": "64e746120372d778849d2e8e",
910
- // "knowledgeId": "64e30035edffac0ec96a2d39",
911
- // "mainId": "e0f6898c6b0d47fa98e8f71ceab1bde8",
912
- // "page": 14,
913
- // "total": 60,
914
- // "pageHeight": 728.504,
915
- // "pageWidth": 515.906,
916
- // "publicPageFileUrl": "https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/e0f6898c6b0d47fa98e8f71ceab1bde8/2023/08/21/02/12/07/64e300378c3dfb3bc434f51a/15.pdf",
917
- // "extractInfo": {
918
- // "location": [
919
- // 52.665375,
920
- // 312.01306,
921
- // 404.98618,
922
- // 142.5199
923
- // ],
924
- // "content": null,
925
- // "lines": [
926
- // {
927
- // "content": null,
928
- // "location": [
929
- // 52.665375,
930
- // 312.01306,
931
- // 404.98618,
932
- // 142.5199
933
- // ]
934
- // }
935
- // ],
936
- // "tagId": null
937
- // },
938
- // "block": {
939
- // "type": "TEXT",
940
- // "location": [
941
- // 52.665375,
942
- // 312.01306,
943
- // 404.98618,
944
- // 142.5199
945
- // ],
946
- // "color": "#366AFF",
947
- // "flowChart": {
948
- // "content": ""
949
- // },
950
- // "image": {
951
- // "url": null,
952
- // "desc": ""
953
- // },
954
- // "table": {
955
- // "title": null,
956
- // "table": null
957
- // },
958
- // "text": {
959
- // "originText": "① 头部防护:安全帽\n佩戴要求:\n①存在坠物或对头部产生碰撞风险的作业场所需要佩戴安全帽 ;\n②安全帽必须戴正、戴牢、不能晃动,要系紧下颏带,调节好后箍以\n防安全帽脱落 ;\n③受强力撞击及超过有效期的安全帽必须更换。",
960
- // "indexText": "① 头部防护:安全帽\n佩戴要求:\n①存在坠物或对头部产生碰撞风险的作业场所需要佩戴安全帽 ;\n②安全帽必须戴正、戴牢、不能晃动,要系紧下颏带,调节好后箍以\n防安全帽脱落 ;\n③受强力撞击及超过有效期的安全帽必须更换。",
961
- // "lines": [
962
- // {
963
- // "location": [
964
- // 69.08148,
965
- // 368.92072,
966
- // 65.90851,
967
- // 10.5
968
- // ]
969
- // },
970
- // {
971
- // "location": [
972
- // 86.290985,
973
- // 384.67072,
974
- // 31.5,
975
- // 10.5
976
- // ]
977
- // },
978
- // {
979
- // "location": [
980
- // 286.2992,
981
- // 315.73584,
982
- // 37.656006,
983
- // 12.0
984
- // ]
985
- // },
986
- // {
987
- // "location": [
988
- // 324.6939,
989
- // 316.79932,
990
- // 122.74487,
991
- // 10.5
992
- // ]
993
- // },
994
- // {
995
- // "location": [
996
- // 286.2954,
997
- // 336.0458,
998
- // 149.625,
999
- // 10.5
1000
- // ]
1001
- // },
1002
- // {
1003
- // "location": [
1004
- // 286.2954,
1005
- // 356.0483,
1006
- // 161.15405,
1007
- // 10.5
1008
- // ]
1009
- // },
1010
- // {
1011
- // "location": [
1012
- // 286.2954,
1013
- // 376.0508,
1014
- // 161.15405,
1015
- // 10.5
1016
- // ]
1017
- // },
1018
- // {
1019
- // "location": [
1020
- // 286.2954,
1021
- // 396.0533,
1022
- // 76.125,
1023
- // 10.5
1024
- // ]
1025
- // },
1026
- // {
1027
- // "location": [
1028
- // 286.2954,
1029
- // 416.05582,
1030
- // 161.17517,
1031
- // 10.5
1032
- // ]
1033
- // },
1034
- // {
1035
- // "location": [
1036
- // 286.2954,
1037
- // 436.8038,
1038
- // 52.5,
1039
- // 10.5
1040
- // ]
1041
- // },
1042
- // {
1043
- // "location": [
1044
- // 338.7992,
1045
- // 435.73584,
1046
- // 12.0,
1047
- // 12.0
1048
- // ]
1049
- // }
1050
- // ]
1051
- // }
1052
- // }
1053
- // }
1054
- // ],
1055
- // "code": "0",
1056
- // "msg": null,
1057
- // "traceId": null
1058
- // }
1059
- if (res.data.code == 0) {
1060
- // tagIds 会按照gpt识别的生成有序的数组,前端直接按照下标的顺序取就可以了
1061
- // 缓存拿到的所有数据
1062
- this.cachePdf = res.data.data
1063
- let publicPageFileUrl = res.data.data[0].publicPageFileUrl
1064
- this.currentPage = 0
1065
- if (publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')) === '.pdf') {
1066
- this.preViewType = 'pdf'
1067
- this.setPageAllLine(this.cachePdf)
1068
- this.getpdfResloutePage(res.data.data[0])
1069
- } else {
1070
- this.preViewType = 'excal'
1071
- this.$http.post(
1072
- '/knowledge-api/temporary-certificate/or-origin?expired=30',
1073
- publicPageFileUrl,
1074
- {
1075
- headers: {
1076
- "Content-Type": "application/json",
1077
- },
1078
- }).then(res => {
1079
- // 使用原声请求方式 axios会带有不需要的请求头
1080
- let xhr = new XMLHttpRequest();
1081
- xhr.open('GET', res.data || res.bodyText, true);
1082
- // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
1083
- xhr.onload = ({ currentTarget }) => {
1084
- // 请求完成
1085
- if (currentTarget.status === 200) { // 返回200
1086
- let pdf_view = document.getElementsByClassName('pdf_view');
1087
- if (pdf_view && pdf_view[0]){
1088
- pdf_view[0].style.backgroundImage = 'none'
1089
- }
1090
- this.contentView.innerHTML = currentTarget.response
1091
- this.contentView.style.padding = '10px'
1092
- // this.contentView.style.position = 'relative'
1093
- this.$refs.pdfView.style.backgroundColor = '#FFFFFF'
1094
- this.$refs.pdfView.appendChild(this.contentView)
1095
-
1096
- let allTr = Array.from(this.$refs.pdfView.getElementsByTagName('tr'))
1097
- this.allTr = []
1098
- for (let index = 0; index < allTr.length; index++) {
1099
- if (value.includes(allTr[index].getAttribute('tag-id'))) {
1100
- this.allTr.push(allTr[index])
1101
- }
1102
- }
1103
- this.currentChange(1)
1104
-
1105
- }
1106
- }
1107
- xhr.send();
1108
- })
1109
- }
1110
- } else {
1111
- let div = document.createElement('div')
1112
- div.innerText = '文件加载异常'
1113
- this.contentView.appendChild(div)
1114
- this.$refs.pdfView.appendChild(this.contentView)
1115
- }
1116
- })
1117
- }
1118
- },
1119
- deep: true,
1120
- immediate: true
1121
- }
1122
- },
1123
- mounted () {
1124
- if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
1125
- this.isPC = false
1126
- } else {
1127
- this.isPC = true
1128
- }
1129
- }
1130
- }
1131
- </script>
1132
-
1133
- <style lang="less" scoped>
1134
- .pdf_view {
1135
- width: 100%;
1136
- height: calc(100% - 110px);
1137
- overflow: auto;
1138
- //overflow-y: scroll;
1139
- background-color: #f5f7fb;
1140
- // margin-bottom: 60px;
1141
- box-sizing: border-box;
1142
- background-image: url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif');
1143
- background-position: center;
1144
- background-size: 50px;
1145
- background-repeat: no-repeat;
1146
- // position: relative;
1147
- // > div {
1148
- // width: 100%;
1149
- // height: 100%;
1150
- // overflow: hidden;
1151
- // overflow-y: auto;
1152
- // position: relative;
1153
- // }
1154
- >iframe {
1155
- width: 100%;
1156
- height: 100%;
1157
- }
1158
-
1159
- a:link {
1160
- color: none;
1161
- }
1162
-
1163
- a:visited {
1164
- color: none;
1165
- }
1166
-
1167
- a:hover {
1168
- color: none;
1169
- }
1170
-
1171
- a:active {
1172
- color: none;
1173
- }
1174
- .btn_footer {
1175
- width: 100%;
1176
- height: 60px;
1177
- display: flex;
1178
- align-items: center;
1179
- justify-content: space-around;
1180
- position: absolute;
1181
- bottom: 0px;
1182
- left: 0;
1183
- z-index: 999;
1184
- background: #ffffff;
1185
-
1186
- .prev,
1187
- .next {
1188
- width: 35%;
1189
- height: 40px;
1190
- display: flex;
1191
- align-items: center;
1192
- justify-content: center;
1193
- border-radius: 50px;
1194
- cursor: pointer;
1195
- }
1196
-
1197
- .prev {
1198
- background: #F2F5FA;
1199
- color: #000;
1200
- }
1201
-
1202
- .next {
1203
- background: #366aff;
1204
- color: #ffffff;
1205
- }
1206
- }
1207
-
1208
- #pagination {
1209
- .total-class {
1210
- margin-right: 13px;
1211
- font-weight: 400;
1212
- }
1213
-
1214
- position: absolute;
1215
- bottom: 0px;
1216
- right: 0;
1217
- width: 100%;
1218
- display: flex;
1219
- align-items: center;
1220
- justify-content: center;
1221
- height: 50px;
1222
- background-color: white;
1223
- box-shadow: 0px 0px 18px 0px rgba(29, 55, 129, 0.07);
1224
- border-radius: 5px;
1225
- z-index: 1000;
1226
-
1227
-
1228
-
1229
- /deep/.el-pagination {
1230
- margin-right: 110px;
1231
- }
1232
-
1233
- /deep/.el-pager {
1234
- background: #EDF0F6;
1235
- border-radius: 15px;
1236
- }
1237
-
1238
- /deep/.el-pagination.is-background .btn-next {
1239
- width: 30px;
1240
- height: 30px;
1241
- background: #EDF0F6;
1242
- border-radius: 50%;
1243
- }
1244
-
1245
- /deep/.el-pagination .btn-next {
1246
- width: 30px;
1247
- height: 30px;
1248
- background: #EDF0F6;
1249
- border-radius: 50%;
1250
- padding-left: 0;
1251
- margin-left: 5px;
1252
- }
1253
-
1254
- /deep/.el-pagination .btn-prev {
1255
- width: 30px;
1256
- height: 30px;
1257
- background: #EDF0F6;
1258
- border-radius: 50%;
1259
- padding-right: 0;
1260
- margin-right: 5px;
1261
- }
1262
-
1263
- /deep/.el-pagination button {
1264
- padding: 0;
1265
- min-width: 30px;
1266
- }
1267
-
1268
- /deep/.el-pager li {
1269
- background: #EDF0F6;
1270
- height: 30px;
1271
- min-width: 30px;
1272
- line-height: 30px;
1273
- font-size: 12px;
1274
- color: #717b90;
1275
- }
1276
-
1277
- /deep/.el-pager li:first-child {
1278
- border-bottom-left-radius: 15px !important;
1279
- border-top-left-radius: 15px !important;
1280
- }
1281
-
1282
- /deep/.el-pager li:last-child {
1283
- border-top-right-radius: 15px !important;
1284
- border-bottom-right-radius: 15px !important;
1285
- }
1286
-
1287
- /deep/.el-pager li.active {
1288
- width: 30px;
1289
- height: 30px;
1290
- min-width: 30px;
1291
- background: #366AFF;
1292
- border: 3px solid #A1B9FF;
1293
- border-radius: 50%;
1294
- line-height: 24px;
1295
- color: white;
1296
- }
1297
-
1298
- /deep/.el-pagination.is-background .el-pager li:not(.disabled).active {
1299
- background: #366AFF;
1300
- }
1301
- }
1302
-
1303
- .change_scale {
1304
- width: 100%;
1305
- height: 50px;
1306
- position: absolute;
1307
- top: 50px;
1308
- left: 0;
1309
- background: #ffffff;
1310
- display: flex;
1311
- align-items: center;
1312
- padding: 0 10px;
1313
- box-sizing: border-box;
1314
-
1315
- section {
1316
- cursor: pointer;
1317
- width: 30px;
1318
- height: 30px;
1319
- margin-right: 5px;
1320
- border-radius: 5px;
1321
- display: flex;
1322
- align-items: center;
1323
- justify-content: center;
1324
-
1325
- i {
1326
- font-weight: 900;
1327
- }
1328
- }
1329
-
1330
- section:hover {
1331
- background: rgba(221, 222, 223, 1);
1332
- }
1333
- }
1334
- }
1335
- </style>
1336
- <style lang="less">
1337
- .animation {
1338
- animation-name: highlight;
1339
- animation-duration: 4s;
1340
- }
1341
-
1342
- @keyframes highlight {
1343
- 0% {
1344
- background: rgba(255, 136, 0, 0.3);
1345
- }
1346
- 25% {
1347
- background: rgba(255, 136, 0, 0.6);
1348
- }
1349
-
1350
- 50% {
1351
- background: rgba(255, 136, 0, 0.3);
1352
- }
1353
-
1354
- 75% {
1355
- background: rgba(255, 136, 0, 0.6);
1356
- }
1357
-
1358
- 100% {
1359
- background: rgba(255, 136, 0, 0.3);
1360
- }
1
+ <template>
2
+ <div id="pdf_view" class="pdf_view" :style="{
3
+ marginTop: isPC ? '50px' : '',
4
+ marginBottom: tagIds.length > 1 ? '60px' : '0px',
5
+ height: setHeight
6
+ }">
7
+ <div class="change_scale" v-if="isPC">
8
+ <section @click="changeScale('reduce')">
9
+ <i class="el-icon-minus"></i>
10
+ </section>
11
+ <el-divider direction="vertical"></el-divider>
12
+ <section @click="changeScale('zoom')">
13
+ <i class="el-icon-plus"></i>
14
+ </section>
15
+ <el-select size="small" v-model="handScale" @change="changeScale" placeholder="请选择">
16
+ <el-option v-for="item in scaleList" :key="item.value" :label="item.label" :value="item.value">
17
+ </el-option>
18
+ </el-select>
19
+ </div>
20
+ <div class="pdf_container_view" id="pdf_container_view" @scroll="pdfScroll" ref="pdfView"></div>
21
+ <div class="btn_footer" v-if="tagIds.length > 1 && !isPC">
22
+ <div class="prev" @click="prev">上一段</div>
23
+ <div class="next" @click="next">下一段</div>
24
+ </div>
25
+ <div id="pagination" v-if="tagIds.length > 1 && isPC">
26
+ <el-pagination :current-page="currentPage + 1" @current-change="currentChange" @prev-click="prev"
27
+ @next-click="next" layout="slot, prev, pager, next" :page-size="1" :total="tagIds.length">
28
+ <span class="total-class">答案由{{ tagIds.length }}段内容生成</span>
29
+ </el-pagination>
30
+ </div>
31
+ </div>
32
+ </template>
33
+
34
+ <script>
35
+ import _ from 'lodash'
36
+ // import * as pdfjsLib from 'pdfjs-dist'
37
+ // pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker';
38
+ // import { TextLayerBuilder } from "pdfjs-dist/web/pdf_viewer";
39
+ // EventBus pdf_viewer 支持绑定自定义事件,一版不做
40
+ // import 'pdfjs-dist/web/pdf_viewer.css'
41
+ /* eslint-disable */
42
+ const pdfjsLib = window['pdfjsLib']
43
+ if (pdfjsLib) {
44
+ pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
45
+ // 'pdfjs-dist/build/pdf.worker';
46
+ }
47
+ const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
48
+ const CSS_UNITS = 96.0 / 72.0
49
+ // import { zoomElement } from '../assets/js/hammer'
50
+ export default {
51
+ name: 'pdfView',
52
+ props: ['tagIds', 'isMessageRecord','fileName'],
53
+ data () {
54
+ return {
55
+ url: '',
56
+ pages: [],
57
+ pageLoadStatus: {
58
+ WAIT: 0,
59
+ LOADED: 1,
60
+ },
61
+ scale: 1,
62
+ rotation: 0,
63
+ pageSize: {},
64
+ PAGE_INTVERVAL: 15,
65
+ SLICE_COUNT: 5,
66
+ contentView: null,
67
+ fisrtLoad: true,
68
+ TextLayerBuilder: null,
69
+ totalPageCount: 0,
70
+ identifyTextPostion: {
71
+ top: 0,
72
+ left: 0,
73
+ width: 100,
74
+ height: 0,
75
+ page: 1,
76
+ pageHeight: 0,
77
+ pageWidth: 0,
78
+ extractInfo: {},
79
+ currentPageAllLine: []
80
+ },
81
+ currentPageAllLine: [],
82
+ pdfUrl: '',
83
+ cachePdf: [],
84
+ newViewer: null,
85
+ currentPage: 0,
86
+ changetoolbar: false,
87
+ allTr: [],
88
+ preViewType: 'pdf',
89
+ displacement: {
90
+ pageX: 0,
91
+ pageY: 0,
92
+ moveable: false,
93
+ pageX2: 0,
94
+ pageY2: 0,
95
+ originScale: 1,
96
+ },
97
+ isTouchMoved: false,
98
+ transformSalce: null,
99
+ defaultTransform:0.8,
100
+ isPC: false,
101
+ handScale: 'auto',
102
+ scaleList: [
103
+ {
104
+ label: '自动缩放',
105
+ value: 'auto'
106
+ },
107
+ {
108
+ label: '实际比例',
109
+ value: 'reality'
110
+ },
111
+ {
112
+ label: '100%',
113
+ value: 1
114
+ },
115
+ {
116
+ label: '120%',
117
+ value: 1.2
118
+ },
119
+ {
120
+ label: '150%',
121
+ value: 1.5
122
+ },
123
+ {
124
+ label: '170%',
125
+ value: 1.7
126
+ }
127
+ ,
128
+ {
129
+ label: '200%',
130
+ value: 2
131
+ }
132
+ ],
133
+ scrollTop: 0,
134
+ scrollLeft: 0
135
+ }
136
+ },
137
+ methods: {
138
+ getpdfResloutePage (pdfResloute) {
139
+ // 根据当前页面宽度设置缩放比例
140
+ // this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
141
+ if (this.isMessageRecord) {
142
+ this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
143
+ } else {
144
+ this.scale = 2
145
+ }
146
+ // 从后端获取到当前分片后所有的pdf页码,初始化数组,数组下{} 对应每页pdf文件
147
+ this.pdfUrl = pdfResloute.publicPageFileUrl.substring(0, pdfResloute.publicPageFileUrl.lastIndexOf('/') + 1)
148
+ this.initPages(pdfResloute.total)
149
+ // 定位功能,加载对应页码位置
150
+ this.loadPdfData(pdfResloute.page)
151
+ },
152
+ async loadPdfData (loadPage) {
153
+ if (this.pages[loadPage - 1] && ((this.pages[loadPage - 1].dom && this.pages[loadPage - 1].dom.children.length > 0) || this.pages[loadPage - 1].loadStatus)) {
154
+ return
155
+ } else {
156
+ if (this.changetoolbar) {
157
+ this.$nextTick(() => {
158
+ this.renderHighlights()
159
+ })
160
+ this.changetoolbar = false
161
+ }
162
+ }
163
+ // 记录开始缓存的状态
164
+ // pdfjsLib.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/legacy/build/pdf.worker.entry.js");
165
+ // 拿到第一个分片
166
+ const { startPage, url } = await this.fetchPdfFragment(loadPage);
167
+ let loadingTask = pdfjsLib.getDocument(url)
168
+ loadingTask.promise.then(async (pdfDoc) => {
169
+ // 将已经下载的分片保存到 pages 数组中
170
+ // for (let i = 0; i < pdfDoc.numPages; i += 1) {
171
+ // const pageIndex = startPage + i;
172
+ // const page = this.pages[pageIndex - 1];
173
+ // // // 不在缓存列表内,重新获取本页pdf
174
+ // // if (page.loadStatus !== this.pageLoadStatus.LOADED) {
175
+
176
+ // // } else {
177
+ // // if (this.changetoolbar) {
178
+ // // this.$nextTick(() => {
179
+ // // this.renderHighlights()
180
+ // // })
181
+ // // this.changetoolbar = false
182
+ // // }
183
+ // // }
184
+ // }
185
+ const page = this.pages[loadPage - 1]
186
+ await pdfDoc.getPage(1).then(async (pdfPage) => {
187
+ this.pages[loadPage - 1].loadStatus = true
188
+ this.pages[loadPage - 1].pdfPage = pdfPage;
189
+ // 通知可以进行渲染了
190
+ await this.startRenderPages(pdfPage, page, loadPage)
191
+ });
192
+ });
193
+ },
194
+ initPages (totalPage) {
195
+ // const pages = [];
196
+ this.totalPageCount = totalPage
197
+ for (let i = 0; i < totalPage; i += 1) {
198
+ this.pages.push({
199
+ pageNo: i + 1,
200
+ loadStatus: false,
201
+ pdfPage: null,
202
+ dom: null
203
+ });
204
+ }
205
+ },
206
+ async fetchPdfFragment (pageIndex) {
207
+ // 置换加签后的文件地址。
208
+ let obj = {}
209
+ await this.$http.post(
210
+ '/knowledge-api/temporary-certificate/or-origin?expired=30',
211
+ this.pdfUrl + pageIndex + '.pdf',
212
+ {
213
+ headers: {
214
+ "Content-Type": "application/json",
215
+ },
216
+ }).then(async res => {
217
+ if (res.bodyText) {
218
+ // 最后返回一个 包含这4个参数的对象
219
+ obj = await {
220
+ "startPage": pageIndex, // 分片的开始页码
221
+ "endPage": pageIndex + 5, // 分片结束页码
222
+ "totalPage": this.totalPageCount, // pdf 总页数
223
+ "url": res.bodyText // 分片内容下载地址
224
+ }
225
+ }
226
+ if (res.data) {
227
+ // 最后返回一个 包含这4个参数的对象
228
+ obj = await {
229
+ "startPage": pageIndex, // 分片的开始页码
230
+ "endPage": pageIndex + 5, // 分片结束页码
231
+ "totalPage": this.totalPageCount, // pdf 总页数
232
+ "url": res.data // 分片内容下载地址
233
+ }
234
+ }
235
+ })
236
+ return obj
237
+ },
238
+ startRenderPages (pdfPage, page, pageIndex) {
239
+ if (Object.keys(this.pageSize).length == 0) {
240
+ const viewport = pdfPage.getViewport({
241
+ scale: this.scale, // 缩放的比例
242
+ rotation: this.rotation, // 旋转的角度
243
+ });
244
+ // 记录pdf页面高度
245
+ const pageSize = {
246
+ width: viewport.width,
247
+ height: viewport.height,
248
+ }
249
+ this.pageSize = pageSize
250
+ // 创建内容绘制区,并设置大小
251
+ if (this.$refs.pdfView.clientWidth / this.pageSize.width >= 1 || this.isMessageRecord) {
252
+ this.contentView.style.width = `${pageSize.width - 10}px`;
253
+ this.contentView.style.height = `${(this.totalPageCount * (pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
254
+ } else {
255
+ this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
256
+ this.contentView.style.width = `${pageSize.width * this.transformSalce - 10}px`;
257
+ this.contentView.style.height = `${(this.totalPageCount * (pageSize.height * (this.transformSalce) + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
258
+ }
259
+ this.contentView.style.margin = '0 auto 0'
260
+ this.contentView.style.position = 'relative'
261
+ this.contentView.style.paddingBottom = '60px'
262
+ // contentView.style.overflowY = 'auto'
263
+ this.$refs.pdfView.appendChild(this.contentView);
264
+ }
265
+ this.renderPages(pageIndex)
266
+ },
267
+ // 渲染需要展示的页面,不需展示的页码将其清除
268
+ renderPages (pageIndex) {
269
+ const pagesToRender = this.getRenderScope(pageIndex);
270
+ for (const i of this.pages) {
271
+ if (pagesToRender.some(p => { return p.pageNo == i.pageNo })) {
272
+ if (i.loadStatus === true) {
273
+ this.renderPageContent(i, i.pageNo)
274
+ } else {
275
+ this.renderPageLoading(i, i.pageNo)
276
+ }
277
+ } else {
278
+ this.clearPage(i);
279
+ }
280
+ }
281
+
282
+ },
283
+ async renderPageContent (page, pageIndex) {
284
+ const { pdfPage, pageNo, dom } = page;
285
+ // dom 元素已存在,无须重新渲染,直接返回
286
+ if ((dom && dom.children.length != 0) || page.loading) {
287
+ return;
288
+ }
289
+ page.loading = true
290
+ const viewport = pdfPage.getViewport({
291
+ scale: this.scale,
292
+ rotation: this.rotation,
293
+ });
294
+ // 创建新的canvas
295
+ const canvas = document.createElement('canvas');
296
+ const context = canvas.getContext('2d');
297
+ // canvas.getContext('2d');
298
+ canvas.height = this.pageSize.height * (this.fileName ? CSS_UNITS : 1);
299
+ canvas.width = this.pageSize.width * (this.fileName ? CSS_UNITS : 1);
300
+ canvas.style.position = 'relative'
301
+ canvas.style.top = -3 + 'px'
302
+ // 创建渲染的dom
303
+ const pageDom = document.createElement('div');
304
+ pageDom.style.position = 'absolute';
305
+ pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * (this.fileName ? CSS_UNITS : 1)) + this.PAGE_INTVERVAL}px`;
306
+ pageDom.style.width = `${this.pageSize.width * (this.fileName ? CSS_UNITS : 1)}px`;
307
+ pageDom.style.height = `${this.pageSize.height * (this.fileName ? CSS_UNITS : 1)}px`;
308
+ pageDom.setAttribute('data-id', 'page' + pageNo)
309
+ // pageDom.appendChild(canvas);
310
+ // 渲染内容
311
+ let renderContext = {
312
+ canvasContext: context,
313
+ viewport: viewport,
314
+ transform: this.fileName ? [CSS_UNITS, 0, 0, CSS_UNITS, 0, 0] : '',
315
+ }
316
+ await pdfPage.render(renderContext).promise.then(() => {
317
+ const html = canvas.toDataURL();
318
+ let image = document.createElement('img');
319
+ image.setAttribute('src',html)
320
+ pageDom.appendChild(image);
321
+ return pdfPage.getTextContent()
322
+ }).then(async (textContent) => {
323
+ const textLayerDiv = document.createElement('div');
324
+ textLayerDiv.setAttribute('class', 'textLayer');
325
+ // 将文本图层div添加至每页pdf的div中
326
+ // 创建新的TextLayerBuilder实例
327
+ let textLayer = new TextLayerBuilder({
328
+ textLayerDiv: textLayerDiv,
329
+ pageIndex: pdfPage._pageIndex,
330
+ viewport: viewport,
331
+ });
332
+ let findPage = this.currentPageAllLine.find(l => { return l.page == pageIndex })
333
+ let rectdomTop = 0
334
+ if (findPage) {
335
+ let AllLines = findPage.allLines
336
+ // setTimeout(() => {
337
+ if (AllLines.length > 0) {
338
+ for (let j = 0; j < AllLines.length; j++) {
339
+ let lines = AllLines[j].lines
340
+ let rectdom = document.createElement('div')
341
+ rectdom.setAttribute('react-count', AllLines[j].pageCount);
342
+ rectdom.style.position = 'absolute';
343
+ rectdom.style.top = 0
344
+ rectdom.style.left = 0
345
+ rectdom.classList.add('rectdom')
346
+ for (let index = 0; index < lines.length; index++) {
347
+ if (!/^\s+$/g.test(lines[index].content)) {
348
+ let postionArr = lines[index].location
349
+ let div = document.createElement('div')
350
+ div.style.position = 'absolute';
351
+ div.style.left = postionArr[0] * this.scale * (this.fileName ? CSS_UNITS : 1) + 'px',
352
+ // 后端返回的坐标有基线对齐的问题,top 值是后端算好(基线top - 文字高度),在此加上文字高度的 1/9 (大致比例)为实际展示出文字的top值
353
+ div.style.top = postionArr[1] * this.scale * (this.fileName ? CSS_UNITS : 1) + 'px'
354
+ div.style.height = postionArr[3] * this.scale * (this.fileName ? CSS_UNITS : 1) + 'px';
355
+ div.style.width = postionArr[2] * this.scale * (this.fileName ? CSS_UNITS : 1) + 'px'
356
+ div.style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
357
+ div.classList.add('lineHeight')
358
+ rectdom.appendChild(div)
359
+ if (index == 0 && j == 0) {
360
+ if (this.transformSalce !== null) {
361
+ rectdomTop = postionArr[1]* this.scale * (this.fileName ? CSS_UNITS : 1) * this.transformSalce
362
+ } else {
363
+ rectdomTop = postionArr[1] * this.scale * (this.fileName ? CSS_UNITS : 1) * this.defaultTransform
364
+ }
365
+ // if(this.isPC) {
366
+ // rectdomTop = rectdomTop - 50 < 0 ? 0 : rectdomTop - 50
367
+ // }
368
+ }
369
+ }
370
+ }
371
+ if (rectdom.children.length > 0) {
372
+ pageDom.appendChild(rectdom)
373
+ }
374
+ }
375
+ }
376
+ }
377
+ textLayer.setTextContent(textContent);
378
+ textLayer.render()
379
+ pageDom.appendChild(textLayerDiv);
380
+ let backgroundDom = document.getElementById('backgroundLoad' + pageNo)
381
+ if (backgroundDom) {
382
+ this.contentView.removeChild(backgroundDom);
383
+ }
384
+ page.dom = await pageDom;
385
+ page.loading = false
386
+ this.contentView.appendChild(pageDom);
387
+ let pdf_view = document.getElementsByClassName('pdf_view');
388
+ if (pdf_view && pdf_view[0]){
389
+ pdf_view[0].style.backgroundImage = 'none'
390
+ }
391
+ let postionArr = []
392
+ if (findPage){
393
+ let AllLines = findPage.allLines
394
+ if (AllLines.length){
395
+ postionArr = AllLines[0].lines[0].location
396
+ }
397
+ }
398
+ if(this.transformSalce !== null && this.fileName) {
399
+ this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
400
+ if (postionArr.length){
401
+ this.contentView.style.left = (postionArr[0] * this.scale * CSS_UNITS * (this.transformSalce) * -1) + 10 + 'px';
402
+ }
403
+ } else {
404
+ this.contentView.style.transform = `scale(${this.defaultTransform})`;
405
+ if (postionArr.length){
406
+ this.contentView.style.left = (postionArr[0] * this.scale * CSS_UNITS * (this.defaultTransform) * -1) / 2 + 'px';
407
+ }
408
+ }
409
+ if (this.changetoolbar) {
410
+ setTimeout(() => {
411
+ this.renderHighlights()
412
+ this.changetoolbar = false
413
+ }, 500)
414
+ }
415
+ if (this.fisrtLoad) {
416
+ setTimeout(() => {
417
+ let pageoffsetHeight = 0
418
+ if (this.transformSalce !== null) {
419
+ pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce * (this.fileName ? CSS_UNITS : 1)
420
+ } else {
421
+ pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL) * this.defaultTransform *(this.fileName ? CSS_UNITS : 1)
422
+ }
423
+ if (this.$refs.pdfView.clientHeight - pageoffsetHeight > 0 && pageIndex == 1) {
424
+ const height = this.$refs.pdfView.clientHeight;
425
+ let startNum = 0
426
+ let endNum = 0
427
+ if (this.transformSalce !== null) {
428
+ startNum = Math.ceil(this.$refs.pdfView.scrollTop / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce* (this.fileName ? CSS_UNITS : 1)))
429
+ endNum = startNum + Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce* (this.fileName ? CSS_UNITS : 1)))
430
+ } else {
431
+ startNum = Math.ceil(this.$refs.pdfView.scrollTop / ((this.pageSize.height + this.PAGE_INTVERVAL) * (this.fileName ? CSS_UNITS : 1) * this.defaultTransform))
432
+ endNum = startNum + Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * (this.fileName ? CSS_UNITS : 1) * this.defaultTransform))}
433
+ console.log(this.$refs.pdfView.scrollTop, startNum, endNum, 'endNumendNum');
434
+ for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
435
+ if (pageIndex > 0 && pageIndex <= this.pages.length) {
436
+ this.loadPdfData(pageIndex)
437
+ }
438
+ }
439
+ }
440
+ if (this.$refs.pdfView.scrollTop == Math.floor((pageNo - 1) * pageoffsetHeight)) {
441
+ this.$refs.pdfView.scrollTop = rectdomTop
442
+ this.fisrtLoad = false
443
+ } else {
444
+ this.$refs.pdfView.scrollTop = `${((pageNo - 1) * pageoffsetHeight) + rectdomTop - this.PAGE_INTVERVAL}`
445
+ this.fisrtLoad = false
446
+ }
447
+ this.renderHighlights()
448
+ // zoomElement(this.contentView)
449
+ }, 100)
450
+ }
451
+ })
452
+ },
453
+ // 监听容器的滚动事件,触发 scrollPdf 方法
454
+ // 这里加了防抖保证不会一次产生过多请求
455
+ debounceScrollPdf: _.debounce(function (e, that) {
456
+ if (this.fisrtLoad) {
457
+ this.fisrtLoad = false
458
+ return
459
+ }
460
+ const scrollTop = e.target.scrollTop;
461
+ const height = e.target.clientHeight;
462
+ let startNum = 0
463
+ let endNum = 0
464
+ if (this.transformSalce !== null) {
465
+ startNum = Math.ceil(scrollTop / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce * (this.fileName ? CSS_UNITS : 1)))
466
+ endNum = startNum + Math.ceil(height / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce * (this.fileName ? CSS_UNITS : 1)))
467
+ } else {
468
+ startNum = Math.ceil(scrollTop / ((that.pageSize.height + that.PAGE_INTVERVAL) * (this.fileName ? CSS_UNITS : 1) * this.defaultTransform))
469
+ endNum = startNum + Math.ceil(height / ((that.pageSize.height + that.PAGE_INTVERVAL) * (this.fileName ? CSS_UNITS : 1) * this.defaultTransform))
470
+ }
471
+ for (let pageIndex = startNum; pageIndex < endNum; pageIndex++) {
472
+ if (pageIndex > 0 && pageIndex <= that.pages.length) {
473
+ that.loadPdfData(pageIndex)
474
+ }
475
+ }
476
+ }, 200),
477
+ directScrolling (e, that) {
478
+ if (this.fisrtLoad) {
479
+ this.fisrtLoad = false
480
+ return
481
+ }
482
+ const scrollTop = e.target.scrollTop;
483
+ const height = e.target.clientHeight;
484
+ // 根据内容可视区域中心点计算页码, 没有滚动时,指向第一页
485
+ const pageIndex = scrollTop > 0 ?
486
+ Math.ceil((scrollTop + (height / 2)) / (that.pageSize.height + that.PAGE_INTVERVAL)) :
487
+ 1;
488
+ this.loadPdfData(pageIndex)
489
+ },
490
+ pdfScroll (e) {
491
+ if (this.preViewType !== 'pdf' || this.isTouchMoved) {
492
+ return
493
+ }
494
+ if (this.scrollLeft != e.target.scrollLeft) {
495
+ this.scrollLeft = e.target.scrollLeft
496
+ }
497
+ if (this.scrollTop != e.target.scrollTop) {
498
+ this.scrollTop = e.target.scrollTop
499
+ this.debounceScrollPdf(e, this)
500
+ }
501
+ },
502
+ // 分片每次只做一次处理,所以不考虑多片情况
503
+ loadBefore (pageIndex) {
504
+ this.loadPdfData(pageIndex)
505
+ },
506
+ loadAfter (pageIndex) {
507
+ this.loadPdfData(pageIndex)
508
+ },
509
+ // 首先我们获取到需要渲染的范围
510
+ // 根据当前的可视范围内的页码,我们前后只保留 8 页
511
+ getRenderScope (pageIndex) {
512
+ const pagesToRender = [];
513
+ let i = pageIndex - 1;
514
+ let j = pageIndex + 1;
515
+ // pageIndex - 1 表示当前页码数 对应的下标位置
516
+ pagesToRender.push(this.pages[pageIndex - 1]);
517
+ while (pagesToRender.length < 8 && pagesToRender.length < this.pages.length) {
518
+ if (i > 0) {
519
+ pagesToRender.push(this.pages[i - 1]);
520
+ i -= 1;
521
+ }
522
+ if (pagesToRender.length >= 8) {
523
+ break;
524
+ }
525
+ if (j <= this.pages.length) {
526
+ pagesToRender.push(this.pages[j - 1]);
527
+ j += 1;
528
+ }
529
+ }
530
+ // for (let index = 0; index < array.length; index++) {
531
+ // const element = array[index];
532
+
533
+ // }
534
+ return pagesToRender;
535
+ },
536
+
537
+ // 清除页面 dom
538
+ clearPage (page) {
539
+ if (this.contentView.contains(page.dom) && page.dom) {
540
+ this.contentView.removeChild(page.dom);
541
+ page.loadStatus = false
542
+ page.loading = false
543
+ page.dom = undefined;
544
+ }
545
+ },
546
+ // 页面正在下载时渲染loading视图
547
+ renderPageLoading (page) {
548
+ const { pageNo, dom } = page;
549
+ if (dom && dom.children.length != 0) {
550
+ return;
551
+ }
552
+ let backgroundDom = document.getElementById('backgroundLoad' + pageNo)
553
+ if (this.contentView.contains(backgroundDom)) {
554
+ return
555
+ }
556
+ const pageDom = document.createElement('div');
557
+ pageDom.style.width = `${this.pageSize.width * (this.fileName ? CSS_UNITS : 1)}px`;
558
+ pageDom.style.height = `${this.pageSize.height * (this.fileName ? CSS_UNITS : 1)}px`;
559
+ pageDom.style.position = 'absolute';
560
+ pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * (this.fileName ? CSS_UNITS : 1)) + this.PAGE_INTVERVAL
561
+ }px`;
562
+ pageDom.style.backgroundImage = `url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif')`
563
+ pageDom.style.backgroundPosition = 'center'
564
+ pageDom.style.backgroundRepeat = 'no-repeat'
565
+ pageDom.style.backgroundColor = '#FFF'
566
+ pageDom.setAttribute('id', 'backgroundLoad' + pageNo)
567
+ page.dom = pageDom;
568
+ this.contentView.appendChild(pageDom);
569
+ },
570
+ prev () {
571
+ this.currentPage--
572
+ if (this.currentPage < 0) {
573
+ this.currentPage = 0
574
+ if (!this.isPC) {
575
+ this.$toast({
576
+ message: '当前已经是第一段了',
577
+ duration: 2000,
578
+ })
579
+ return
580
+ }
581
+ }
582
+ if (this.preViewType == 'pdf') {
583
+ this.scrollToUplaodePage(this.currentPage)
584
+ } else {
585
+ this.scrollToExcalTop(this.currentPage)
586
+ }
587
+ // this.getpdfResloutePage(this.cachePdf[this.currentPage - 1])
588
+ },
589
+ next () {
590
+ this.currentPage++
591
+ if (this.currentPage >= this.tagIds.length) {
592
+ this.currentPage = this.tagIds.length - 1
593
+ if (!this.isPC) {
594
+ this.$toast({
595
+ message: '当前已经是最后一段了',
596
+ duration: 2000,
597
+ })
598
+ return
599
+ }
600
+ }
601
+ if (this.preViewType == 'pdf') {
602
+ this.scrollToUplaodePage(this.currentPage)
603
+ } else {
604
+ this.scrollToExcalTop(this.currentPage)
605
+ }
606
+ },
607
+ currentChange (value) {
608
+ this.currentPage = value - 1
609
+ if (this.preViewType == 'pdf') {
610
+ this.scrollToUplaodePage(this.currentPage)
611
+ } else {
612
+ this.scrollToExcalTop(this.currentPage)
613
+ }
614
+ },
615
+ scrollToUplaodePage (currentPage) {
616
+ this.changetoolbar = true
617
+ if (this.preViewType !== 'pdf') {
618
+ return
619
+ }
620
+
621
+ let pdfResloute = this.cachePdf[currentPage]
622
+ this.identifyTextPostion.extractInfo = pdfResloute.extractInfo
623
+ this.identifyTextPostion.left = pdfResloute.extractInfo.location[0]
624
+ this.identifyTextPostion.top = pdfResloute.extractInfo.location[1]
625
+ this.identifyTextPostion.width = pdfResloute.extractInfo.location[2]
626
+ this.identifyTextPostion.height = pdfResloute.extractInfo.location[3]
627
+ this.identifyTextPostion.page = pdfResloute.page
628
+ this.identifyTextPostion.pageHeight = pdfResloute.pageHeight
629
+ this.identifyTextPostion.pageWidth = pdfResloute.pageWidth
630
+ // 在当前段落在最后一页pdf时,根据计算的高度并不能触发滚动,在此执行重新渲染方法,非次情况会执行两次,待优化
631
+ this.$nextTick(() => {
632
+ this.renderHighlights()
633
+ })
634
+ if (this.transformSalce !== null) {
635
+ this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce) + (this.identifyTextPostion.top * this.scale * this.transformSalce)}`
636
+ } else {
637
+ this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + (this.identifyTextPostion.top * this.scale * this.defaultTransform)}`
638
+ }
639
+ },
640
+ scrollToExcalTop (currentPage) {
641
+ for (let index = 0; index < this.allTr.length; index++) {
642
+ if (index == currentPage) {
643
+ Array.from(this.allTr[index].children).forEach(item => {
644
+ item.style.background = 'rgba(255, 136, 0, 0.6)'
645
+ item.classList.add('animation')
646
+ setTimeout(() => {
647
+ item.classList.remove('animation')
648
+ }, 4000)
649
+ })
650
+ // getBoundingClientRect().top 当前元素距离屏幕顶部的高度 + 弹窗header 高度
651
+ if (!this.isPC) {
652
+ let top = this.allTr[index].getBoundingClientRect().top - this.$refs.pdfView.getBoundingClientRect().top
653
+ this.$refs.pdfView.scrollTop = top
654
+ } else {
655
+ let top = this.allTr[index].getBoundingClientRect().top
656
+ this.$refs.pdfView.scrollTop = top - 50
657
+ }
658
+ } else {
659
+ Array.from(this.allTr[index].children).forEach(item => {
660
+ item.style.background = 'rgba(54, 106, 255, 0.6)'
661
+ item.classList.remove('animation')
662
+ })
663
+ }
664
+ }
665
+ },
666
+ // pdf是否需要重新渲染高亮位置
667
+ renderHighlights () {
668
+ let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
669
+ if (lineHeightDom) {
670
+ lineHeightDom.forEach((d) => {
671
+ for (let i = 0; i < d.children.length; i++) {
672
+ if (d.getAttribute('react-count') == this.currentPage) {
673
+ d.children[i].style.backgroundColor = 'rgba(255, 136, 0, 0.3)'
674
+ d.children[i].classList.add('animation')
675
+ setTimeout(() => {
676
+ d.children[i].classList.remove('animation')
677
+ }, 4000)
678
+ } else {
679
+ d.children[i].style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
680
+ d.children[i].classList.remove('animation')
681
+ }
682
+ }
683
+ })
684
+ }
685
+ },
686
+ displayHiglight (pageIndex) {
687
+ let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
688
+ if (lineHeightDom) {
689
+ lineHeightDom.forEach((d) => {
690
+ if (d.getAttribute('page-index') == pageIndex) {
691
+ d.style.display = 'none'
692
+ }
693
+ })
694
+ }
695
+ },
696
+ // 前端暂时缓存多页
697
+ autoLoadMore (pageIndex) {
698
+ let pdfResloute = this.cachePdf.find(cache => {
699
+ return cache.page == pageIndex
700
+ })
701
+ if (pdfResloute) {
702
+ this.getpdfResloutePage(pdfResloute)
703
+ } else {
704
+ this.loadPdfData(pageIndex)
705
+ }
706
+ },
707
+ setPageAllLine (arr) {
708
+ this.currentPageAllLine = []
709
+ arr.forEach((item, index) => {
710
+ let i = this.currentPageAllLine.findIndex(l => { return l.page && l.page == item.page })
711
+ if (i != -1) {
712
+ // this.currentPageAllLine[i].allLines.lines.push(item.extractInfo.lines)
713
+ this.currentPageAllLine[i].allLines.push({
714
+ pageCount: index,
715
+ lines: item.extractInfo.lines
716
+ })
717
+ } else {
718
+ this.currentPageAllLine.push({
719
+ page: item.page,
720
+ allLines: [{
721
+ pageCount: index,
722
+ lines: item.extractInfo.lines
723
+ }],
724
+ })
725
+ }
726
+ })
727
+ },
728
+ openTouch () {
729
+ // this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
730
+ let that = this;
731
+ this.$nextTick(() => {
732
+ // setInterval(() => {
733
+ // this.scale = this.scale + 0.1
734
+ // that.pages.forEach((item, index) =>{
735
+ // if(item.dom) {
736
+ // item.dom.children.forEach( childDom =>{
737
+ // if(childDom.getAttribute('react-count')) {
738
+ // childDom.style.transform = "scale(" + this.scale + ")";
739
+ // childDom.style.transformOrigin = "0px 0px 0px";
740
+ // } else {
741
+ // item.dom = null
742
+ // this.startRenderPages(item.pdfPage, null, index)
743
+ // }
744
+ // } )
745
+ // }
746
+ // })
747
+ // }, 100);
748
+ // 获取放大或缩小的区域DOM
749
+ let matrix_box = this.contentView
750
+ matrix_box.addEventListener("touchstart", function (event) {
751
+ this.isTouchMoved = true
752
+ let touches = event.touches;
753
+ let events = touches[0];
754
+ let events2 = touches[1];
755
+
756
+ // event.preventDefault();
757
+
758
+ // 第一个触摸点的坐标
759
+ that.displacement.pageX = events.pageX;
760
+ that.displacement.pageY = events.pageY;
761
+
762
+ that.displacement.moveable = true;
763
+
764
+ if (events2) {
765
+ that.displacement.pageX2 = events2.pageX;
766
+ that.displacement.pageY2 = events2.pageY;
767
+ }
768
+
769
+ that.displacement.originScale = this.scale || 1;
770
+ });
771
+ document.addEventListener("touchmove", function (event) {
772
+ if (!that.displacement.moveable) {
773
+ return;
774
+ }
775
+ // event.preventDefault();
776
+ let touches = event.touches;
777
+ let events = touches[0];
778
+ let events2 = touches[1];
779
+ // 双指移动
780
+ if (events2) {
781
+ // 第2个指头坐标在touchmove时候获取
782
+ if (!that.displacement.pageX2) {
783
+ that.displacement.pageX2 = events2.pageX;
784
+ }
785
+ if (!that.displacement.pageY2) {
786
+ that.displacement.pageY2 = events2.pageY;
787
+ }
788
+ // 双指缩放比例计算
789
+ let zoom = that.getDistance({
790
+ x: events.pageX,
791
+ y: events.pageY
792
+ },
793
+ {
794
+ x: events2.pageX,
795
+ y: events2.pageY
796
+ }
797
+ ) / that.getDistance(
798
+ {
799
+ x: that.displacement.pageX,
800
+ y: that.displacement.pageY
801
+ },
802
+ {
803
+ x: that.displacement.pageX2,
804
+ y: that.displacement.pageY2
805
+ }
806
+ );
807
+ // 应用在元素上的缩放比例
808
+ let newScale = that.displacement.originScale * zoom;
809
+ // 最大缩放比例限制
810
+ if (newScale > 2) {
811
+ newScale = 2;
812
+ }
813
+ // 最大缩放比例限制
814
+ if (newScale < 1) {
815
+ newScale = 1;
816
+ }
817
+ // 记住使用的缩放值
818
+ that.displacement.scale = newScale;
819
+ // console.log(newScale);
820
+ matrix_box.style.transform = "scale(" + newScale + ")";
821
+ // 设置旋转元素的基点位置
822
+ matrix_box.style.transformOrigin = "0px 0px 0px";
823
+ }
824
+ }, { passive: false });
825
+ document.addEventListener('touchend', function () {
826
+ that.isTouchMoved = false
827
+ }, { passive: false })
828
+ });
829
+ },
830
+ getDistance (start, stop) {
831
+ // Math.hypot()计算参数的平方根
832
+ return Math.hypot(stop.x - start.x, stop.y - start.y);
833
+ },
834
+ setupCanvas (canvas, width, height) {
835
+ const dpr = 1;
836
+ // const rect = canvas.getBoundingClientRect();
837
+ canvas.width = width
838
+ canvas.height = height
839
+ const ctx = canvas.getContext('2d');
840
+ ctx?.scale(dpr, dpr);
841
+ return ctx;
842
+ },
843
+ changeScale (value) {
844
+ if (value == 'zoom') {
845
+ this.handScale = 'auto'
846
+ this.transformSalce = (this.transformSalce + 0.2).toFixed(1)
847
+ } else if (value == 'reduce') {
848
+ if ((this.transformSalce - 0.2).toFixed(1) <= 0) {
849
+ return
850
+ }
851
+ this.handScale = 'auto'
852
+ this.transformSalce = (this.transformSalce - 0.2).toFixed(1)
853
+ } else if (value == 'auto') {
854
+ this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
855
+ } else if (value == 'reality') {
856
+ this.transformSalce = 0.5
857
+ } else {
858
+ this.transformSalce = (value / 2).toFixed(1)
859
+ }
860
+ this.transformSalce = Number(this.transformSalce)
861
+ this.contentView.style.transform = 'scale(' + this.transformSalce + ')';
862
+ // this.getpdfResloutePage(this.cachePdf[0])
863
+ },
864
+ },
865
+ computed: {
866
+ perviewUrl () {
867
+ return '/web/viewer.html?file=' + '/pdflist/pdf4split-1.pdf'
868
+ },
869
+ setHeight () {
870
+ if (this.tagIds.length > 1) {
871
+ if (this.isPC) {
872
+ return 'calc(100% - 110px)'
873
+ } else {
874
+ return 'calc(100% - 60px)'
875
+ }
876
+ } else {
877
+ if (this.isPC) {
878
+ return 'calc(100% - 50px)'
879
+ } else {
880
+ return '100%'
881
+ }
882
+ }
883
+ }
884
+ },
885
+ watch: {
886
+ tagIds: {
887
+ handler (value) {
888
+ if (value && value.length) {
889
+ // 在 pdf_view 下创建 所有canvs的容器
890
+ this.contentView = document.createElement('div')
891
+ this.contentView.setAttribute('id','contentView')
892
+ this.contentView.style.transformOrigin = '0px 0px 0px'
893
+ this.$http.get('/knowledge-api/knowledge/knowledge-part-location-info/list?ids=' + value.join(',')).then(res => {
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}
895
+ // res.data = {"data":[{"id":"64590ce1eb1320043401cc90","knowledgeId":"64590cd5017b461d67e282e1","mainId":"fb348d095c0b4fd7bbd37826563dac7d","page":2,"total":5,"pageHeight":841.8898,"pageWidth":595.30396,"publicPageFileUrl":"https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/fb348d095c0b4fd7bbd37826563dac7d/2023/05/08/10/53/20/64590ce0eb1320043401cc7b/2.pdf","extractInfo":{"location":[89.32981,638.1907,415.15512,98.63251],"content":":北京地铁 13\r号线 :藤黄\r色 :西直门站—\r东直门站 :17 :41.\r5 :6\r准\rB :2002年\r09月\r28日 ","lines":[{"content":":北京地铁 13\r号线 ","location":[89.32981,638.1907,99.44599,98.63251]},{"content":":藤黄\r色 ","location":[188.7758,638.1907,46.79959,98.63251]},{"content":":西直门站—\r东直门站 ","location":[235.5754,638.1907,86.09996,98.63251]},{"content":":17 ","location":[321.67535,638.1907,36.200012,98.63251]},{"content":":41.\r5 ","location":[357.87537,638.1907,39.400696,98.63251]},{"content":":6\r准\rB ","location":[397.27606,638.1907,41.099,98.63251]},{"content":":2002年\r09月\r28日 ","location":[438.37506,638.1907,66.10986,98.63251]}],"tagId":null}}],"code":"0","msg":null,"traceId":null}
896
+ // 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}
897
+ // res.data = {"data":[{"id":"6475eab868110215ab821a80","knowledgeId":"6475e7eac724c54c46cbfa2d","mainId":"5ecf2fcd704541149201ab9c1c31162d","page":0,"total":1,"pageHeight":0.0,"pageWidth":0.0,"publicPageFileUrl":"https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/5ecf2fcd704541149201ab9c1c31162d/2023/05/30/08/23/20/6475eab63339db423f26b196/0.html","extractInfo":{"location":null,"content":"产品:系统配置,产品型号:存储,VX30:4G+16G,VX50:16G+256G","lines":null,"tagId":"6475eab868110215ab821a80"}}],"code":"0","msg":null,"traceId":null}
898
+ // res.data = {"data":[{"id":"6475e9393339db423f26af01","knowledgeId":"6475e44fc724c54c46cbfa21","mainId":"5ecf2fcd704541149201ab9c1c31162d","page":2,"total":2,"pageHeight":510.25,"pageWidth":1559.05,"publicPageFileUrl":"https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/5ecf2fcd704541149201ab9c1c31162d/2023/05/30/08/00/29/6475e55d3339db423f26a9b8/2.pdf","extractInfo":{"location":[327.70532,288.0498,414.9734,12.241608],"content":"三、指示灯状态说明1.白色常亮:开机/开机中2.红色常亮:待机3.白色呼吸:息屏4.红色闪烁:升级1.LAN:通过网线连接到主机的Camera端口2.电源开关:电源切换开关","lines":[{"content":"三、指示灯状态说明","location":[634.3203,288.0498,108.3584,12.0]},{"content":"1.白色常亮:开机/开机中","location":[634.3203,320.08978,108.23407,9.0]},{"content":"2.红色常亮:待机","location":[634.3204,341.3298,78.597046,9.0]},{"content":"3.白色呼吸:息屏","location":[634.32043,362.45282,78.597046,9.0]},{"content":"4.红色闪烁:升级","location":[634.3205,383.6928,78.597046,9.0]},{"content":"1.LAN:通过网线连接到主机的","location":[327.70535,291.2914,144.35995,9.0]},{"content":"Camera端口","location":[327.70532,306.88843,55.322998,9.0]},{"content":"2.电源开关:电源切换开关","location":[482.74832,291.2914,105.36301,9.0]}],"tagId":null}}],"code":"0","msg":null,"traceId":null}
899
+ // if(value.length === 1) {
900
+ // this.$refs.pdfView.style.height = 'calc(100% - 50px)'
901
+ // }
902
+ // res.data = {
903
+ // "data": [
904
+ // {
905
+ // "id": "64e746120372d778849d2e8e",
906
+ // "knowledgeId": "64e30035edffac0ec96a2d39",
907
+ // "mainId": "e0f6898c6b0d47fa98e8f71ceab1bde8",
908
+ // "page": 14,
909
+ // "total": 60,
910
+ // "pageHeight": 728.504,
911
+ // "pageWidth": 515.906,
912
+ // "publicPageFileUrl": "https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/e0f6898c6b0d47fa98e8f71ceab1bde8/2023/08/21/02/12/07/64e300378c3dfb3bc434f51a/15.pdf",
913
+ // "extractInfo": {
914
+ // "location": [
915
+ // 52.665375,
916
+ // 312.01306,
917
+ // 404.98618,
918
+ // 142.5199
919
+ // ],
920
+ // "content": null,
921
+ // "lines": [
922
+ // {
923
+ // "content": null,
924
+ // "location": [
925
+ // 52.665375,
926
+ // 312.01306,
927
+ // 404.98618,
928
+ // 142.5199
929
+ // ]
930
+ // }
931
+ // ],
932
+ // "tagId": null
933
+ // },
934
+ // "block": {
935
+ // "type": "TEXT",
936
+ // "location": [
937
+ // 52.665375,
938
+ // 312.01306,
939
+ // 404.98618,
940
+ // 142.5199
941
+ // ],
942
+ // "color": "#366AFF",
943
+ // "flowChart": {
944
+ // "content": ""
945
+ // },
946
+ // "image": {
947
+ // "url": null,
948
+ // "desc": ""
949
+ // },
950
+ // "table": {
951
+ // "title": null,
952
+ // "table": null
953
+ // },
954
+ // "text": {
955
+ // "originText": "① 头部防护:安全帽\n佩戴要求:\n①存在坠物或对头部产生碰撞风险的作业场所需要佩戴安全帽 ;\n②安全帽必须戴正、戴牢、不能晃动,要系紧下颏带,调节好后箍以\n防安全帽脱落 ;\n③受强力撞击及超过有效期的安全帽必须更换。",
956
+ // "indexText": "① 头部防护:安全帽\n佩戴要求:\n①存在坠物或对头部产生碰撞风险的作业场所需要佩戴安全帽 ;\n②安全帽必须戴正、戴牢、不能晃动,要系紧下颏带,调节好后箍以\n防安全帽脱落 ;\n③受强力撞击及超过有效期的安全帽必须更换。",
957
+ // "lines": [
958
+ // {
959
+ // "location": [
960
+ // 69.08148,
961
+ // 368.92072,
962
+ // 65.90851,
963
+ // 10.5
964
+ // ]
965
+ // },
966
+ // {
967
+ // "location": [
968
+ // 86.290985,
969
+ // 384.67072,
970
+ // 31.5,
971
+ // 10.5
972
+ // ]
973
+ // },
974
+ // {
975
+ // "location": [
976
+ // 286.2992,
977
+ // 315.73584,
978
+ // 37.656006,
979
+ // 12.0
980
+ // ]
981
+ // },
982
+ // {
983
+ // "location": [
984
+ // 324.6939,
985
+ // 316.79932,
986
+ // 122.74487,
987
+ // 10.5
988
+ // ]
989
+ // },
990
+ // {
991
+ // "location": [
992
+ // 286.2954,
993
+ // 336.0458,
994
+ // 149.625,
995
+ // 10.5
996
+ // ]
997
+ // },
998
+ // {
999
+ // "location": [
1000
+ // 286.2954,
1001
+ // 356.0483,
1002
+ // 161.15405,
1003
+ // 10.5
1004
+ // ]
1005
+ // },
1006
+ // {
1007
+ // "location": [
1008
+ // 286.2954,
1009
+ // 376.0508,
1010
+ // 161.15405,
1011
+ // 10.5
1012
+ // ]
1013
+ // },
1014
+ // {
1015
+ // "location": [
1016
+ // 286.2954,
1017
+ // 396.0533,
1018
+ // 76.125,
1019
+ // 10.5
1020
+ // ]
1021
+ // },
1022
+ // {
1023
+ // "location": [
1024
+ // 286.2954,
1025
+ // 416.05582,
1026
+ // 161.17517,
1027
+ // 10.5
1028
+ // ]
1029
+ // },
1030
+ // {
1031
+ // "location": [
1032
+ // 286.2954,
1033
+ // 436.8038,
1034
+ // 52.5,
1035
+ // 10.5
1036
+ // ]
1037
+ // },
1038
+ // {
1039
+ // "location": [
1040
+ // 338.7992,
1041
+ // 435.73584,
1042
+ // 12.0,
1043
+ // 12.0
1044
+ // ]
1045
+ // }
1046
+ // ]
1047
+ // }
1048
+ // }
1049
+ // }
1050
+ // ],
1051
+ // "code": "0",
1052
+ // "msg": null,
1053
+ // "traceId": null
1054
+ // }
1055
+ if (res.data.code == 0) {
1056
+ // tagIds 会按照gpt识别的生成有序的数组,前端直接按照下标的顺序取就可以了
1057
+ // 缓存拿到的所有数据
1058
+ this.cachePdf = res.data.data
1059
+ let publicPageFileUrl = res.data.data[0].publicPageFileUrl
1060
+ this.currentPage = 0
1061
+ if (publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')) === '.pdf') {
1062
+ this.preViewType = 'pdf'
1063
+ this.setPageAllLine(this.cachePdf)
1064
+ this.getpdfResloutePage(res.data.data[0])
1065
+ } else {
1066
+ this.preViewType = 'excal'
1067
+ this.$http.post(
1068
+ '/knowledge-api/temporary-certificate/or-origin?expired=30',
1069
+ publicPageFileUrl,
1070
+ {
1071
+ headers: {
1072
+ "Content-Type": "application/json",
1073
+ },
1074
+ }).then(res => {
1075
+ // 使用原声请求方式 axios会带有不需要的请求头
1076
+ let xhr = new XMLHttpRequest();
1077
+ xhr.open('GET', res.data || res.bodyText, true);
1078
+ // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
1079
+ xhr.onload = ({ currentTarget }) => {
1080
+ // 请求完成
1081
+ if (currentTarget.status === 200) { // 返回200
1082
+ let pdf_view = document.getElementsByClassName('pdf_view');
1083
+ if (pdf_view && pdf_view[0]){
1084
+ pdf_view[0].style.backgroundImage = 'none'
1085
+ }
1086
+ this.contentView.innerHTML = currentTarget.response
1087
+ this.contentView.style.padding = '10px'
1088
+ // this.contentView.style.position = 'relative'
1089
+ this.$refs.pdfView.style.backgroundColor = '#FFFFFF'
1090
+ this.$refs.pdfView.appendChild(this.contentView)
1091
+
1092
+ let allTr = Array.from(this.$refs.pdfView.getElementsByTagName('tr'))
1093
+ this.allTr = []
1094
+ for (let index = 0; index < allTr.length; index++) {
1095
+ if (value.includes(allTr[index].getAttribute('tag-id'))) {
1096
+ this.allTr.push(allTr[index])
1097
+ }
1098
+ }
1099
+ this.currentChange(1)
1100
+
1101
+ }
1102
+ }
1103
+ xhr.send();
1104
+ })
1105
+ }
1106
+ } else {
1107
+ let div = document.createElement('div')
1108
+ div.innerText = '文件加载异常'
1109
+ this.contentView.appendChild(div)
1110
+ this.$refs.pdfView.appendChild(this.contentView)
1111
+ }
1112
+ })
1113
+ }
1114
+ },
1115
+ deep: true,
1116
+ immediate: true
1117
+ }
1118
+ },
1119
+ mounted () {
1120
+ if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
1121
+ this.isPC = false
1122
+ } else {
1123
+ this.isPC = true
1124
+ }
1125
+ }
1126
+ }
1127
+ </script>
1128
+
1129
+ <style lang="less" scoped>
1130
+ .pdf_view {
1131
+ width: 100%;
1132
+ height: calc(100% - 110px);
1133
+ overflow: auto;
1134
+ //overflow-y: scroll;
1135
+ background-color: #f5f7fb;
1136
+ // margin-bottom: 60px;
1137
+ box-sizing: border-box;
1138
+ background-image: url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif');
1139
+ background-position: center;
1140
+ background-size: 50px;
1141
+ background-repeat: no-repeat;
1142
+ // position: relative;
1143
+ // > div {
1144
+ // width: 100%;
1145
+ // height: 100%;
1146
+ // overflow: hidden;
1147
+ // overflow-y: auto;
1148
+ // position: relative;
1149
+ // }
1150
+ >iframe {
1151
+ width: 100%;
1152
+ height: 100%;
1153
+ }
1154
+
1155
+ a:link {
1156
+ color: none;
1157
+ }
1158
+
1159
+ a:visited {
1160
+ color: none;
1161
+ }
1162
+
1163
+ a:hover {
1164
+ color: none;
1165
+ }
1166
+
1167
+ a:active {
1168
+ color: none;
1169
+ }
1170
+ .btn_footer {
1171
+ width: 100%;
1172
+ height: 60px;
1173
+ display: flex;
1174
+ align-items: center;
1175
+ justify-content: space-around;
1176
+ position: absolute;
1177
+ bottom: 0px;
1178
+ left: 0;
1179
+ z-index: 999;
1180
+ background: #ffffff;
1181
+
1182
+ .prev,
1183
+ .next {
1184
+ width: 35%;
1185
+ height: 40px;
1186
+ display: flex;
1187
+ align-items: center;
1188
+ justify-content: center;
1189
+ border-radius: 50px;
1190
+ cursor: pointer;
1191
+ }
1192
+
1193
+ .prev {
1194
+ background: #F2F5FA;
1195
+ color: #000;
1196
+ }
1197
+
1198
+ .next {
1199
+ background: #366aff;
1200
+ color: #ffffff;
1201
+ }
1202
+ }
1203
+
1204
+ #pagination {
1205
+ .total-class {
1206
+ margin-right: 13px;
1207
+ font-weight: 400;
1208
+ }
1209
+
1210
+ position: absolute;
1211
+ bottom: 0px;
1212
+ right: 0;
1213
+ width: 100%;
1214
+ display: flex;
1215
+ align-items: center;
1216
+ justify-content: center;
1217
+ height: 50px;
1218
+ background-color: white;
1219
+ box-shadow: 0px 0px 18px 0px rgba(29, 55, 129, 0.07);
1220
+ border-radius: 5px;
1221
+ z-index: 1000;
1222
+
1223
+
1224
+
1225
+ /deep/.el-pagination {
1226
+ margin-right: 110px;
1227
+ }
1228
+
1229
+ /deep/.el-pager {
1230
+ background: #EDF0F6;
1231
+ border-radius: 15px;
1232
+ }
1233
+
1234
+ /deep/.el-pagination.is-background .btn-next {
1235
+ width: 30px;
1236
+ height: 30px;
1237
+ background: #EDF0F6;
1238
+ border-radius: 50%;
1239
+ }
1240
+
1241
+ /deep/.el-pagination .btn-next {
1242
+ width: 30px;
1243
+ height: 30px;
1244
+ background: #EDF0F6;
1245
+ border-radius: 50%;
1246
+ padding-left: 0;
1247
+ margin-left: 5px;
1248
+ }
1249
+
1250
+ /deep/.el-pagination .btn-prev {
1251
+ width: 30px;
1252
+ height: 30px;
1253
+ background: #EDF0F6;
1254
+ border-radius: 50%;
1255
+ padding-right: 0;
1256
+ margin-right: 5px;
1257
+ }
1258
+
1259
+ /deep/.el-pagination button {
1260
+ padding: 0;
1261
+ min-width: 30px;
1262
+ }
1263
+
1264
+ /deep/.el-pager li {
1265
+ background: #EDF0F6;
1266
+ height: 30px;
1267
+ min-width: 30px;
1268
+ line-height: 30px;
1269
+ font-size: 12px;
1270
+ color: #717b90;
1271
+ }
1272
+
1273
+ /deep/.el-pager li:first-child {
1274
+ border-bottom-left-radius: 15px !important;
1275
+ border-top-left-radius: 15px !important;
1276
+ }
1277
+
1278
+ /deep/.el-pager li:last-child {
1279
+ border-top-right-radius: 15px !important;
1280
+ border-bottom-right-radius: 15px !important;
1281
+ }
1282
+
1283
+ /deep/.el-pager li.active {
1284
+ width: 30px;
1285
+ height: 30px;
1286
+ min-width: 30px;
1287
+ background: #366AFF;
1288
+ border: 3px solid #A1B9FF;
1289
+ border-radius: 50%;
1290
+ line-height: 24px;
1291
+ color: white;
1292
+ }
1293
+
1294
+ /deep/.el-pagination.is-background .el-pager li:not(.disabled).active {
1295
+ background: #366AFF;
1296
+ }
1297
+ }
1298
+
1299
+ .change_scale {
1300
+ width: 100%;
1301
+ height: 50px;
1302
+ position: absolute;
1303
+ top: 50px;
1304
+ left: 0;
1305
+ background: #ffffff;
1306
+ display: flex;
1307
+ align-items: center;
1308
+ padding: 0 10px;
1309
+ box-sizing: border-box;
1310
+
1311
+ section {
1312
+ cursor: pointer;
1313
+ width: 30px;
1314
+ height: 30px;
1315
+ margin-right: 5px;
1316
+ border-radius: 5px;
1317
+ display: flex;
1318
+ align-items: center;
1319
+ justify-content: center;
1320
+
1321
+ i {
1322
+ font-weight: 900;
1323
+ }
1324
+ }
1325
+
1326
+ section:hover {
1327
+ background: rgba(221, 222, 223, 1);
1328
+ }
1329
+ }
1330
+ .pdf_container_view{
1331
+ height: 100%;
1332
+ width: 100%;
1333
+ position: relative;
1334
+ overflow: auto;
1335
+ }
1336
+ }
1337
+ </style>
1338
+ <style lang="less">
1339
+ .animation {
1340
+ animation-name: highlight;
1341
+ animation-duration: 4s;
1342
+ }
1343
+
1344
+ @keyframes highlight {
1345
+ 0% {
1346
+ background: rgba(255, 136, 0, 0.3);
1347
+ }
1348
+ 25% {
1349
+ background: rgba(255, 136, 0, 0.6);
1350
+ }
1351
+
1352
+ 50% {
1353
+ background: rgba(255, 136, 0, 0.3);
1354
+ }
1355
+
1356
+ 75% {
1357
+ background: rgba(255, 136, 0, 0.6);
1358
+ }
1359
+
1360
+ 100% {
1361
+ background: rgba(255, 136, 0, 0.3);
1362
+ }
1361
1363
  }</style>