askbot-dragon 1.5.17 → 1.5.18-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 (86) 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 +89 -89
  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 +192 -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 +287 -211
  20. package/src/components/ActionAlertIframe.vue +112 -112
  21. package/src/components/AiGuide.vue +467 -467
  22. package/src/components/AnswerDocknowledge.vue +492 -492
  23. package/src/components/AnswerVoice.vue +285 -285
  24. package/src/components/AskIFrame.vue +15 -15
  25. package/src/components/ConversationContainer.vue +4974 -4660
  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 +205 -177
  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/pdfPosition.vue +1552 -1140
  58. package/src/components/popup.vue +227 -227
  59. package/src/components/previewDoc.vue +228 -228
  60. package/src/components/previewPdf.vue +294 -294
  61. package/src/components/receiverMessagePlatform.vue +65 -65
  62. package/src/components/recommend.vue +89 -89
  63. package/src/components/selector/hOption.vue +20 -20
  64. package/src/components/selector/hSelector.vue +199 -199
  65. package/src/components/selector/hWrapper.vue +216 -216
  66. package/src/components/senderMessagePlatform.vue +50 -50
  67. package/src/components/source/BotMessage.vue +24 -24
  68. package/src/components/source/CustomMessage.vue +24 -24
  69. package/src/components/test.vue +260 -260
  70. package/src/components/tree.vue +294 -294
  71. package/src/components/utils/AliyunIssUtil.js +81 -81
  72. package/src/components/utils/ckeditor.js +174 -174
  73. package/src/components/utils/ckeditorImageUpload/command.js +109 -109
  74. package/src/components/utils/ckeditorImageUpload/editing.js +11 -11
  75. package/src/components/utils/ckeditorImageUpload/plugin-image.js +11 -11
  76. package/src/components/utils/ckeditorImageUpload/toolbar-ui.js +40 -40
  77. package/src/components/utils/ckeditorfileUpload/common.js +180 -180
  78. package/src/components/utils/ckeditorfileUpload/editing.js +11 -11
  79. package/src/components/utils/ckeditorfileUpload/plugin_file.js +11 -11
  80. package/src/components/utils/ckeditorfileUpload/toolbar_ui.js +34 -34
  81. package/src/components/utils/format_date.js +25 -25
  82. package/src/components/utils/index.js +6 -6
  83. package/src/components/utils/math_utils.js +29 -29
  84. package/src/components/voiceComponent.vue +119 -119
  85. package/src/main.js +60 -60
  86. package/vue.config.js +55 -55
@@ -1,1141 +1,1553 @@
1
- <template>
2
- <div
3
- class="pdf_view"
4
- ref="pdfView"
5
- @scroll="pdfScroll"
6
- :style="{
7
- marginTop: isPC ? '50px' : '',
8
- marginBottom: tagIds.length > 1 ? '60px' : '0px',
9
- height: setHeight
10
- }">
11
- <div class="change_scale" v-if="isPC">
12
- <section @click="changeScale('reduce')">
13
- <i class="el-icon-minus"></i>
14
- </section>
15
- <el-divider direction="vertical"></el-divider>
16
- <section @click="changeScale('zoom')">
17
- <i class="el-icon-plus"></i>
18
- </section>
19
- <el-select size="small" v-model="handScale" @change="changeScale" placeholder="请选择">
20
- <el-option
21
- v-for="item in scaleList"
22
- :key="item.value"
23
- :label="item.label"
24
- :value="item.value">
25
- </el-option>
26
- </el-select>
27
- </div>
28
- <div class="btn_footer" v-if="tagIds.length > 1 && !isPC">
29
- <div class="prev" @click="prev">上一段</div>
30
- <div class="next" @click="next">下一段</div>
31
- </div>
32
- <div id="pagination" v-if="tagIds.length > 1 && isPC">
33
- <el-pagination :current-page="currentPage + 1" @current-change="currentChange" @prev-click="prev"
34
- @next-click="next" layout="slot, prev, pager, next" :page-size="1" :total="tagIds.length">
35
- <span class="total-class">答案由{{ tagIds.length }}段内容生成</span>
36
- </el-pagination>
37
- </div>
38
- </div>
39
- </template>
40
-
41
- <script>
42
- import _ from 'lodash'
43
- // import * as pdfjsLib from 'pdfjs-dist'
44
- // pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker';
45
- // import { TextLayerBuilder } from "pdfjs-dist/web/pdf_viewer";
46
- // EventBus pdf_viewer 支持绑定自定义事件,一版不做
47
- // import 'pdfjs-dist/web/pdf_viewer.css'
48
- /* eslint-disable */
49
- const pdfjsLib = window['pdfjsLib']
50
- if(pdfjsLib) {
51
- pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
52
- // 'pdfjs-dist/build/pdf.worker';
53
- }
54
- const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
55
- // import { zoomElement } from '../assets/js/hammer'
56
- export default {
57
- name: 'pdfView',
58
- props:['tagIds','isMessageRecord'],
59
- data() {
60
- return {
61
- url: '',
62
- pages: [],
63
- pageLoadStatus: {
64
- WAIT: 0,
65
- LOADED: 1,
66
- },
67
- scale: 1,
68
- rotation: 0,
69
- pageSize: {},
70
- PAGE_INTVERVAL: 15,
71
- SLICE_COUNT: 5,
72
- contentView: null,
73
- fisrtLoad: true,
74
- TextLayerBuilder: null,
75
- totalPageCount: 0,
76
- identifyTextPostion: {
77
- top: 0,
78
- left: 0,
79
- width: 100,
80
- height: 0,
81
- page: 1,
82
- pageHeight: 0,
83
- pageWidth: 0,
84
- extractInfo: {},
85
- currentPageAllLine: []
86
- },
87
- currentPageAllLine: [],
88
- pdfUrl: '',
89
- cachePdf: [],
90
- newViewer: null,
91
- currentPage: 0,
92
- changetoolbar: false,
93
- allTr:[],
94
- preViewType: 'pdf',
95
- displacement:{
96
- pageX: 0,
97
- pageY: 0,
98
- moveable: false,
99
- pageX2: 0,
100
- pageY2: 0,
101
- originScale: 1,
102
- },
103
- isTouchMoved: false,
104
- transformSalce: null,
105
- isPC: false,
106
- handScale: 'auto',
107
- scaleList:[
108
- {
109
- label:'自动缩放',
110
- value:'auto'
111
- },
112
- {
113
- label:'实际比例',
114
- value:'reality'
115
- },
116
- {
117
- label:'100%',
118
- value: 1
119
- },
120
- {
121
- label:'120%',
122
- value: 1.2
123
- },
124
- {
125
- label:'150%',
126
- value: 1.5
127
- },
128
- {
129
- label:'170%',
130
- value: 1.7
131
- }
132
- ,
133
- {
134
- label:'200%',
135
- value: 2
136
- }
137
- ],
138
- scrollTop:0,
139
- scrollLeft:0
140
- }
141
- },
142
- methods: {
143
- getpdfResloutePage (pdfResloute) {
144
- // 根据当前页面宽度设置缩放比例
145
- // this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
146
- // console.log(this.scale,'this.scale');
147
- if(this.isMessageRecord) {
148
- this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
149
- } else {
150
- this.scale = 2
151
- }
152
- // 从后端获取到当前分片后所有的pdf页码,初始化数组,数组下{} 对应每页pdf文件
153
- this.pdfUrl = pdfResloute.publicPageFileUrl.substring(0, pdfResloute.publicPageFileUrl.lastIndexOf('/') + 1)
154
- this.initPages(pdfResloute.total)
155
- // 定位功能,加载对应页码位置
156
- this.loadPdfData(pdfResloute.page)
157
- },
158
- async loadPdfData (loadPage) {
159
- if(this.pages[loadPage - 1] && ((this.pages[loadPage - 1].dom && this.pages[loadPage - 1].dom.children.length > 0) || this.pages[loadPage - 1].loading)) {
160
- return
161
- }
162
- this.pages[loadPage - 1].loading = true
163
- // pdfjsLib.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/legacy/build/pdf.worker.entry.js");
164
- // 拿到第一个分片
165
- const { startPage, url } = await this.fetchPdfFragment(loadPage);
166
- let loadingTask = pdfjsLib.getDocument(url)
167
- loadingTask.promise.then((pdfDoc) => {
168
- // 将已经下载的分片保存到 pages 数组中
169
- for (let i = 0; i < pdfDoc.numPages; i += 1) {
170
- const pageIndex = startPage + i;
171
- const page = this.pages[pageIndex - 1];
172
- // 不在缓存列表内,重新获取本页pdf
173
- if (page.loadStatus !== this.pageLoadStatus.LOADED) {
174
- pdfDoc.getPage(i + 1).then((pdfPage) => {
175
- page.pdfPage = pdfPage;
176
- page.loadStatus = this.pageLoadStatus.LOADED;
177
- // 通知可以进行渲染了
178
- this.startRenderPages(pdfPage, page, pageIndex)
179
- });
180
- } else {
181
- if (this.changetoolbar) {
182
- this.$nextTick(() => {
183
- this.renderHighlights()
184
- })
185
- this.changetoolbar = false
186
- }
187
- }
188
- }
189
- });
190
- },
191
- initPages (totalPage) {
192
- // const pages = [];
193
- this.totalPageCount = totalPage
194
- for (let i = 0; i < totalPage; i += 1) {
195
- this.pages.push({
196
- pageNo: i + 1,
197
- loadStatus: this.pageLoadStatus.WAIT,
198
- pdfPage: null,
199
- dom: null
200
- });
201
- }
202
- },
203
- async fetchPdfFragment (pageIndex) {
204
- // 置换加签后的文件地址。
205
- let obj = {}
206
- await this.$http.post(
207
- '/knowledge-api/temporary-certificate/or-origin?expired=30',
208
- this.pdfUrl + pageIndex + '.pdf',
209
- {
210
- headers: {
211
- "Content-Type": "application/json",
212
- },
213
- }).then(async res => {
214
- if(res.bodyText) {
215
- // 最后返回一个 包含这4个参数的对象
216
- obj = await {
217
- "startPage": pageIndex, // 分片的开始页码
218
- "endPage": pageIndex + 5, // 分片结束页码
219
- "totalPage": this.totalPageCount, // pdf 总页数
220
- "url": res.bodyText // 分片内容下载地址
221
- }
222
- }
223
- if (res.data) {
224
- // 最后返回一个 包含这4个参数的对象
225
- obj = await {
226
- "startPage": pageIndex, // 分片的开始页码
227
- "endPage": pageIndex + 5, // 分片结束页码
228
- "totalPage": this.totalPageCount, // pdf 总页数
229
- "url": res.data // 分片内容下载地址
230
- }
231
- }
232
- })
233
- return obj
234
- },
235
- startRenderPages (pdfPage, page, pageIndex) {
236
- if(Object.keys(this.pageSize).length == 0) {
237
- const viewport = pdfPage.getViewport({
238
- scale: this.scale, // 缩放的比例
239
- rotation: this.rotation, // 旋转的角度
240
- });
241
- // 记录pdf页面高度
242
- const pageSize = {
243
- width: viewport.width,
244
- height: viewport.height,
245
- }
246
- this.pageSize = pageSize
247
- // 创建内容绘制区,并设置大小
248
- if(this.$refs.pdfView.clientWidth / this.pageSize.width >= 1 || this.isMessageRecord) {
249
- this.contentView.style.width = `${pageSize.width - 10 }px`;
250
- this.contentView.style.height = `${(this.totalPageCount * (pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
251
- } else {
252
- this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
253
- this.contentView.style.width = `${pageSize.width * this.transformSalce - 10}px`;
254
- this.contentView.style.height = `${(this.totalPageCount * (pageSize.height * (this.transformSalce) + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
255
- }
256
- this.contentView.style.margin = '0 auto 0'
257
- this.contentView.style.position = 'relative'
258
- this.contentView.style.paddingBottom = '60px'
259
- // contentView.style.overflowY = 'auto'
260
- this.$refs.pdfView.appendChild(this.contentView);
261
- }
262
- this.renderPages(pageIndex)
263
- },
264
- renderPageContent (page, pageIndex) {
265
- const { pdfPage, pageNo, dom } = page;
266
- // dom 元素已存在,无须重新渲染,直接返回
267
- if (dom && dom.children.length != 0) {
268
- return;
269
- }
270
- const viewport = pdfPage.getViewport({
271
- scale: this.scale,
272
- rotation: this.rotation,
273
- });
274
- // 创建新的canvas
275
- const canvas = document.createElement('canvas');
276
- const context = canvas.getContext('2d');
277
- // canvas.getContext('2d');
278
- canvas.height = this.pageSize.height;
279
- canvas.width = this.pageSize.width;
280
- // 创建渲染的dom
281
- const pageDom = document.createElement('div');
282
- pageDom.style.position = 'absolute';
283
- pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
284
- pageDom.style.width = `${this.pageSize.width}px`;
285
- pageDom.style.height = `${this.pageSize.height}px`;
286
- pageDom.appendChild(canvas);
287
- // 渲染内容
288
- let renderContext = {
289
- canvasContext: context,
290
- viewport: viewport,
291
- }
292
- pdfPage.render(renderContext).promise.then(() => {
293
- console.log(pdfPage.getTextContent(), 'getTextContent');
294
- return pdfPage.getTextContent()
295
- }).then((textContent) => {
296
- const textLayerDiv = document.createElement('div');
297
- textLayerDiv.setAttribute('class', 'textLayer');
298
- // 将文本图层div添加至每页pdf的div中
299
- // 创建新的TextLayerBuilder实例
300
- let textLayer = new TextLayerBuilder({
301
- textLayerDiv: textLayerDiv,
302
- pageIndex: pdfPage._pageIndex,
303
- viewport: viewport,
304
- });
305
- let findPage = this.currentPageAllLine.find(l => { return l.page == pageIndex })
306
- let rectdomTop = 0
307
- if (findPage) {
308
- let AllLines = findPage.allLines
309
- // setTimeout(() => {
310
- console.log(findPage,'findPage');
311
- if (AllLines.length > 0) {
312
- for (let j = 0; j < AllLines.length; j++) {
313
- let lines = AllLines[j].lines
314
- let rectdom = document.createElement('div')
315
- rectdom.setAttribute('react-count', AllLines[j].pageCount);
316
- rectdom.style.position = 'absolute';
317
- rectdom.style.top = 0
318
- rectdom.style.left = 0
319
- rectdom.classList.add('rectdom')
320
- for (let index = 0; index < lines.length; index++) {
321
- if (!/^\s+$/g.test(lines[index].content)) {
322
- let postionArr = lines[index].location
323
- let div = document.createElement('div')
324
- div.style.position = 'absolute';
325
- div.style.left = postionArr[0] * this.scale + 'px',
326
- // 后端返回的坐标有基线对齐的问题,top 值是后端算好(基线top - 文字高度),在此加上文字高度的 1/9 (大致比例)为实际展示出文字的top值
327
- div.style.top = (postionArr[1] + postionArr[3] / 9) * this.scale + 'px'
328
- div.style.height = postionArr[3] * this.scale + 'px';
329
- div.style.width = postionArr[2] * this.scale + 'px'
330
- div.style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
331
- div.classList.add('lineHeight')
332
- rectdom.appendChild(div)
333
- if(index == 0 && j == 0) {
334
- if(this.transformSalce !== null) {
335
- rectdomTop = (postionArr[1] + postionArr[3] / 9) * this.scale * this.transformSalce
336
- } else {
337
- rectdomTop = (postionArr[1] + postionArr[3] / 9) * this.scale
338
- }
339
- // if(this.isPC) {
340
- // rectdomTop = rectdomTop - 50 < 0 ? 0 : rectdomTop - 50
341
- // }
342
- // console.log(rectdomTop,div.style.top, (postionArr[1] + postionArr[3] / 9) * this.scale);
343
- }
344
- }
345
- }
346
- if (rectdom.children.length > 0) {
347
- pageDom.appendChild(rectdom)
348
- }
349
- }
350
- }
351
- }
352
- textLayer.setTextContent(textContent);
353
- textLayer.render()
354
- pageDom.appendChild(textLayer.textLayerDiv);
355
- page.dom = pageDom;
356
- page.loading = false
357
- this.contentView.appendChild(pageDom);
358
- if(this.transformSalce !== null) {
359
- this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
360
- }
361
- if (this.changetoolbar) {
362
- setTimeout(() => {
363
- this.renderHighlights()
364
- this.changetoolbar = false
365
- }, 100)
366
- }
367
- // console.log(this.fisrtLoad,'this.fisrtLoad');
368
- if (this.fisrtLoad) {
369
- setTimeout(() => {
370
- let pageoffsetHeight = 0
371
- if(this.transformSalce !== null) {
372
- pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce
373
- } else {
374
- pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL)
375
- }
376
- if (this.$refs.pdfView.clientHeight - pageoffsetHeight > 0 && pageIndex == 1) {
377
- const height = this.$refs.pdfView.clientHeight;
378
- let startNum = 0
379
- let endNum = 0
380
- if(this.transformSalce !== null) {
381
- startNum = Math.ceil(this.$refs.pdfView.scrollTop / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
382
- endNum = startNum + Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
383
- console.log( Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce)),this.pageSize.height , this.PAGE_INTVERVAL, height, this.transformSalce,'startNum');
384
-
385
- } else {
386
- startNum = Math.ceil(this.$refs.pdfView.scrollTop / (this.pageSize.height + this.PAGE_INTVERVAL))
387
- endNum = startNum + Math.ceil(height / (this.pageSize.height + this.PAGE_INTVERVAL))
388
-
389
- }
390
- for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
391
- if(pageIndex > 0 && pageIndex <= this.pages.length) {
392
- this.loadPdfData(pageIndex)
393
- }
394
- }
395
- }
396
- if (this.$refs.pdfView.scrollTop == Math.floor((pageNo - 1) * pageoffsetHeight)) {
397
- this.$refs.pdfView.scrollTop = rectdomTop
398
- this.fisrtLoad = false
399
- } else {
400
- this.$refs.pdfView.scrollTop = `${((pageNo - 1) * pageoffsetHeight) + rectdomTop - this.PAGE_INTVERVAL}`
401
- this.fisrtLoad = false
402
- }
403
- this.renderHighlights()
404
- // zoomElement(this.contentView)
405
- }, 100)
406
- }
407
- })
408
- },
409
- // 监听容器的滚动事件,触发 scrollPdf 方法
410
- // 这里加了防抖保证不会一次产生过多请求
411
- debounceScrollPdf: _.debounce(function (e, that) {
412
- if (this.fisrtLoad) {
413
- this.fisrtLoad = false
414
- return
415
- }
416
- const scrollTop = e.target.scrollTop;
417
- const height = e.target.clientHeight;
418
- let startNum = 0
419
- let endNum = 0
420
- if(this.transformSalce !== null) {
421
- startNum = Math.ceil(scrollTop / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
422
- endNum = startNum + Math.ceil(height / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
423
- } else {
424
- startNum = Math.ceil(scrollTop / (that.pageSize.height + that.PAGE_INTVERVAL))
425
- endNum = startNum + Math.ceil(height / (that.pageSize.height + that.PAGE_INTVERVAL))
426
- }
427
- for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
428
- if(pageIndex > 0 && pageIndex <= that.pages.length) {
429
- that.loadPdfData(pageIndex)
430
- }
431
- }
432
- console.log('=======');
433
- }, 200),
434
- directScrolling (e, that) {
435
- if (this.fisrtLoad) {
436
- this.fisrtLoad = false
437
- return
438
- }
439
- const scrollTop = e.target.scrollTop;
440
- const height = e.target.clientHeight;
441
- // 根据内容可视区域中心点计算页码, 没有滚动时,指向第一页
442
- const pageIndex = scrollTop > 0 ?
443
- Math.ceil((scrollTop + (height / 2)) / (that.pageSize.height + that.PAGE_INTVERVAL)) :
444
- 1;
445
- this.loadPdfData(pageIndex)
446
- },
447
- pdfScroll (e) {
448
- if(this.preViewType !== 'pdf' || this.isTouchMoved) {
449
- return
450
- }
451
- if(this.scrollLeft != e.target.scrollLeft) {
452
- this.scrollLeft = e.target.scrollLeft
453
- }
454
- if(this.scrollTop != e.target.scrollTop) {
455
- this.scrollTop = e.target.scrollTop
456
- this.debounceScrollPdf(e, this)
457
- }
458
- },
459
- // 分片每次只做一次处理,所以不考虑多片情况
460
- loadBefore (pageIndex) {
461
- this.loadPdfData(pageIndex)
462
- },
463
- loadAfter (pageIndex) {
464
- this.loadPdfData(pageIndex)
465
- },
466
- // 首先我们获取到需要渲染的范围
467
- // 根据当前的可视范围内的页码,我们前后只保留 8 页
468
- getRenderScope (pageIndex) {
469
- const pagesToRender = [];
470
- let i = pageIndex - 1;
471
- let j = pageIndex + 1;
472
- // pageIndex - 1 表示当前页码数 对应的下标位置
473
- pagesToRender.push(this.pages[pageIndex - 1]);
474
- while (pagesToRender.length < 8 && pagesToRender.length < this.pages.length) {
475
- if (i > 0) {
476
- pagesToRender.push(this.pages[i - 1]);
477
- i -= 1;
478
- }
479
- if (pagesToRender.length >= 8) {
480
- break;
481
- }
482
- if (j <= this.pages.length) {
483
- pagesToRender.push(this.pages[j - 1]);
484
- j += 1;
485
- }
486
- }
487
- return pagesToRender;
488
- },
489
- // 渲染需要展示的页面,不需展示的页码将其清除
490
- renderPages (pageIndex) {
491
- const pagesToRender = this.getRenderScope(pageIndex);
492
- for (const i of this.pages) {
493
- if (pagesToRender.includes(i)) {
494
- i.loadStatus === this.pageLoadStatus.LOADED ?
495
- this.renderPageContent(i, pageIndex) :
496
- this.renderPageLoading(i);
497
- } else {
498
- this.clearPage(i);
499
- }
500
- }
501
- },
502
- // 清除页面 dom
503
- clearPage (page) {
504
- if (page.dom) {
505
- this.contentView.removeChild(page.dom);
506
- page.loadStatus = 0
507
- page.loading = false
508
- page.dom = undefined;
509
- }
510
- },
511
- // 页面正在下载时渲染loading视图
512
- renderPageLoading (page) {
513
- const { pageNo, dom } = page;
514
- if (dom && dom.children.length != 0) {
515
- return;
516
- }
517
- const pageDom = document.createElement('div');
518
- pageDom.style.width = `${this.pageSize.width}px`;
519
- pageDom.style.height = `${this.pageSize.height}px`;
520
- pageDom.style.position = 'absolute';
521
- pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL
522
- }px`;
523
- pageDom.style.backgroundImage = `url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif')`
524
- pageDom.style.backgroundPosition = 'center'
525
- pageDom.style.backgroundRepeat = 'no-repeat'
526
- pageDom.style.backgroundColor = '#FFF'
527
- page.dom = pageDom;
528
- this.contentView.appendChild(pageDom);
529
- },
530
- prev () {
531
- this.currentPage--
532
- if (this.currentPage < 0) {
533
- this.currentPage = 0
534
- if(!this.isPC) {
535
- this.$toast({
536
- message:'当前已经是第一段了',
537
- duration:2000,
538
- })
539
- return
540
- }
541
- }
542
- if(this.preViewType == 'pdf') {
543
- this.scrollToUplaodePage(this.currentPage)
544
- } else {
545
- this.scrollToExcalTop(this.currentPage)
546
- }
547
- // this.getpdfResloutePage(this.cachePdf[this.currentPage - 1])
548
- },
549
- next () {
550
- this.currentPage++
551
- if (this.currentPage >= this.tagIds.length) {
552
- this.currentPage = this.tagIds.length - 1
553
- if(!this.isPC) {
554
- this.$toast({
555
- message:'当前已经是最后一段了',
556
- duration:2000,
557
- })
558
- return
559
- }
560
- }
561
- if(this.preViewType == 'pdf') {
562
- this.scrollToUplaodePage(this.currentPage)
563
- } else {
564
- this.scrollToExcalTop(this.currentPage)
565
- }
566
- },
567
- currentChange (value) {
568
- this.currentPage = value - 1
569
- if(this.preViewType == 'pdf') {
570
- this.scrollToUplaodePage(this.currentPage)
571
- } else {
572
- this.scrollToExcalTop(this.currentPage)
573
- }
574
- },
575
- scrollToUplaodePage (currentPage) {
576
- this.changetoolbar = true
577
- if(this.preViewType !== 'pdf') {
578
- return
579
- }
580
-
581
- let pdfResloute = this.cachePdf[currentPage]
582
- this.identifyTextPostion.extractInfo = pdfResloute.extractInfo
583
- this.identifyTextPostion.left = pdfResloute.extractInfo.location[0]
584
- this.identifyTextPostion.top = pdfResloute.extractInfo.location[1]
585
- this.identifyTextPostion.width = pdfResloute.extractInfo.location[2]
586
- this.identifyTextPostion.height = pdfResloute.extractInfo.location[3]
587
- this.identifyTextPostion.page = pdfResloute.page
588
- this.identifyTextPostion.pageHeight = pdfResloute.pageHeight
589
- this.identifyTextPostion.pageWidth = pdfResloute.pageWidth
590
- // 在当前段落在最后一页pdf时,根据计算的高度并不能触发滚动,在此执行重新渲染方法,非次情况会执行两次,待优化
591
- this.$nextTick(() => {
592
- this.renderHighlights()
593
- })
594
- if(this.transformSalce !== null) {
595
- this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce) + this.identifyTextPostion.top}`
596
- } else {
597
- this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.identifyTextPostion.top}`
598
- }
599
- },
600
- scrollToExcalTop(currentPage) {
601
- for (let index = 0; index < this.allTr.length; index++) {
602
- if(index == currentPage) {
603
- Array.from(this.allTr[index].children).forEach(item =>{
604
- item.style.background = 'rgba(255, 136, 0, 0.6)'
605
- item.classList.add('animation')
606
- setTimeout(() =>{
607
- item.classList.remove('animation')
608
- }, 4000)
609
- })
610
- // getBoundingClientRect().top 当前元素距离屏幕顶部的高度 + 弹窗header 高度
611
- if(!this.isPC) {
612
- let top = this.allTr[index].getBoundingClientRect().top - this.$refs.pdfView.getBoundingClientRect().top
613
- this.$refs.pdfView.scrollTop = top
614
- } else {
615
- let top = this.allTr[index].getBoundingClientRect().top
616
- this.$refs.pdfView.scrollTop = top - 50
617
- }
618
- } else {
619
- Array.from(this.allTr[index].children).forEach(item =>{
620
- item.style.background = 'rgba(54, 106, 255, 0.6)'
621
- item.classList.remove('animation')
622
- })
623
- }
624
- }
625
- },
626
- // pdf是否需要重新渲染高亮位置
627
- renderHighlights () {
628
- let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
629
- console.log(lineHeightDom, this.currentPage, 'this.currentPage');
630
- if (lineHeightDom) {
631
- lineHeightDom.forEach((d) => {
632
- for (let i = 0; i < d.children.length; i++) {
633
- if (d.getAttribute('react-count') == this.currentPage) {
634
- d.children[i].style.backgroundColor = 'rgba(255, 136, 0, 0.3)'
635
- d.children[i].classList.add('animation')
636
- setTimeout(() =>{
637
- d.children[i].classList.remove('animation')
638
- }, 4000)
639
- } else {
640
- d.children[i].style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
641
- d.children[i].classList.remove('animation')
642
- }
643
- }
644
- })
645
- }
646
- },
647
- displayHiglight (pageIndex) {
648
- let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
649
- if (lineHeightDom) {
650
- lineHeightDom.forEach((d) => {
651
- if (d.getAttribute('page-index') == pageIndex) {
652
- d.style.display = 'none'
653
- }
654
- })
655
- }
656
- },
657
- // 前端暂时缓存多页
658
- autoLoadMore (pageIndex) {
659
- let pdfResloute = this.cachePdf.find(cache => {
660
- return cache.page == pageIndex
661
- })
662
- if (pdfResloute) {
663
- this.getpdfResloutePage(pdfResloute)
664
- } else {
665
- this.loadPdfData(pageIndex)
666
- }
667
- },
668
- setPageAllLine (arr) {
669
- this.currentPageAllLine = []
670
- arr.forEach((item, index) => {
671
- let i = this.currentPageAllLine.findIndex(l => { return l.page && l.page == item.page })
672
- if (i != -1) {
673
- // this.currentPageAllLine[i].allLines.lines.push(item.extractInfo.lines)
674
- this.currentPageAllLine[i].allLines.push({
675
- pageCount: index,
676
- lines: item.extractInfo.lines
677
- })
678
- } else {
679
- this.currentPageAllLine.push({
680
- page: item.page,
681
- allLines: [{
682
- pageCount: index,
683
- lines: item.extractInfo.lines
684
- }],
685
- })
686
- }
687
- })
688
- },
689
- openTouch() {
690
- // this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
691
- let that = this;
692
- this.$nextTick(() => {
693
- // setInterval(() => {
694
- // this.scale = this.scale + 0.1
695
- // that.pages.forEach((item, index) =>{
696
- // if(item.dom) {
697
- // item.dom.children.forEach( childDom =>{
698
- // if(childDom.getAttribute('react-count')) {
699
- // childDom.style.transform = "scale(" + this.scale + ")";
700
- // childDom.style.transformOrigin = "0px 0px 0px";
701
- // } else {
702
- // item.dom = null
703
- // this.startRenderPages(item.pdfPage, null, index)
704
- // }
705
- // } )
706
- // }
707
- // })
708
- // }, 100);
709
- // 获取放大或缩小的区域DOM
710
- let matrix_box = this.contentView
711
- matrix_box.addEventListener("touchstart", function (event) {
712
- this.isTouchMoved = true
713
- let touches = event.touches;
714
- let events = touches[0];
715
- let events2 = touches[1];
716
-
717
- // event.preventDefault();
718
-
719
- // 第一个触摸点的坐标
720
- that.displacement.pageX = events.pageX;
721
- that.displacement.pageY = events.pageY;
722
-
723
- that.displacement.moveable = true;
724
-
725
- if (events2) {
726
- that.displacement.pageX2 = events2.pageX;
727
- that.displacement.pageY2 = events2.pageY;
728
- }
729
-
730
- that.displacement.originScale = this.scale || 1;
731
- // console.log(that.displacement);
732
- });
733
- document.addEventListener("touchmove", function (event) {
734
- if (!that.displacement.moveable) {
735
- return;
736
- }
737
- // event.preventDefault();
738
- let touches = event.touches;
739
- let events = touches[0];
740
- let events2 = touches[1];
741
- // 双指移动
742
- if (events2) {
743
- // 第2个指头坐标在touchmove时候获取
744
- if (!that.displacement.pageX2) {
745
- that.displacement.pageX2 = events2.pageX;
746
- }
747
- if (!that.displacement.pageY2) {
748
- that.displacement.pageY2 = events2.pageY;
749
- }
750
- // 双指缩放比例计算
751
- let zoom = that.getDistance({
752
- x: events.pageX,
753
- y: events.pageY
754
- },
755
- {
756
- x: events2.pageX,
757
- y: events2.pageY
758
- }
759
- ) / that.getDistance(
760
- {
761
- x: that.displacement.pageX,
762
- y: that.displacement.pageY
763
- },
764
- {
765
- x: that.displacement.pageX2,
766
- y: that.displacement.pageY2
767
- }
768
- );
769
- // 应用在元素上的缩放比例
770
- let newScale = that.displacement.originScale * zoom;
771
- console.log(zoom, newScale , this.scale, 'newScale');
772
- // 最大缩放比例限制
773
- if (newScale > 2) {
774
- newScale = 2;
775
- }
776
- // 最大缩放比例限制
777
- if(newScale < 1) {
778
- newScale = 1;
779
- }
780
- // 记住使用的缩放值
781
- that.displacement.scale = newScale;
782
- // console.log(newScale);
783
- matrix_box.style.transform = "scale(" + newScale + ")";
784
- // 设置旋转元素的基点位置
785
- matrix_box.style.transformOrigin = "0px 0px 0px";
786
- }
787
- },{ passive: false });
788
- document.addEventListener('touchend',function() {
789
- that.isTouchMoved = false
790
- },{ passive: false })
791
- });
792
- },
793
- getDistance(start, stop) {
794
- // Math.hypot()计算参数的平方根
795
- return Math.hypot(stop.x - start.x, stop.y - start.y);
796
- },
797
- setupCanvas(canvas, width, height) {
798
- const dpr = 1;
799
- // const rect = canvas.getBoundingClientRect();
800
- canvas.width = width
801
- canvas.height = height
802
- const ctx = canvas.getContext('2d');
803
- console.log(canvas.width, canvas.height, dpr, this.scale);
804
- ctx?.scale(dpr, dpr );
805
- return ctx;
806
- },
807
- changeScale(value) {
808
- if(value == 'zoom') {
809
- this.handScale = 'auto'
810
- this.transformSalce = (this.transformSalce + 0.2).toFixed(1)
811
- } else if(value == 'reduce') {
812
- if((this.transformSalce - 0.2).toFixed(1) <= 0) {
813
- return
814
- }
815
- this.handScale = 'auto'
816
- this.transformSalce = (this.transformSalce - 0.2).toFixed(1)
817
- } else if(value == 'auto') {
818
- this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
819
- } else if(value == 'reality') {
820
- this.transformSalce = 0.5
821
- } else {
822
- this.transformSalce = (value / 2).toFixed(1)
823
- }
824
- this.transformSalce = Number(this.transformSalce)
825
- this.contentView.style.transform = 'scale(' + this.transformSalce + ')';
826
- // this.getpdfResloutePage(this.cachePdf[0])
827
- },
828
- },
829
- computed:{
830
- perviewUrl() {
831
- return '/web/viewer.html?file=' + '/pdflist/pdf4split-1.pdf'
832
- },
833
- setHeight() {
834
- if(this.tagIds.length > 1 ) {
835
- if(this.isPC) {
836
- return 'calc(100% - 110px)'
837
- } else {
838
- return 'calc(100% - 60px)'
839
- }
840
- } else {
841
- if(this.isPC) {
842
- return 'calc(100% - 50px)'
843
- } else {
844
- return '100%'
845
- }
846
- }
847
- }
848
- },
849
- watch:{
850
- tagIds: {
851
- handler(value) {
852
- if(value && value.length) {
853
- // 在 pdf_view 下创建 所有canvs的容器
854
- this.contentView = document.createElement('div')
855
- this.contentView.style.transformOrigin = '0px 0px 0px'
856
- this.$http.get('/knowledge-api/knowledge/knowledge-part-location-info/list?ids=' + value.join(',')).then(res =>{
857
- // 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}
858
- // 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}
859
- // 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}
860
- // 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}
861
- // 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}
862
- // if(value.length === 1) {
863
- // this.$refs.pdfView.style.height = 'calc(100% - 50px)'
864
- // }
865
- if (res.data.code == 0) {
866
- // tagIds 会按照gpt识别的生成有序的数组,前端直接按照下标的顺序取就可以了
867
- // 缓存拿到的所有数据
868
- this.cachePdf = res.data.data
869
- let publicPageFileUrl = res.data.data[0].publicPageFileUrl
870
- this.currentPage = 0
871
- // console.log(publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')));
872
- if (publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')) === '.pdf') {
873
- this.preViewType = 'pdf'
874
- this.setPageAllLine(this.cachePdf)
875
- this.getpdfResloutePage(res.data.data[0])
876
- } else {
877
- this.preViewType = 'excal'
878
- this.$http.post(
879
- '/knowledge-api/temporary-certificate/or-origin?expired=30',
880
- publicPageFileUrl,
881
- {
882
- headers: {
883
- "Content-Type": "application/json",
884
- },
885
- }).then(res => {
886
- // 使用原声请求方式 axios会带有不需要的请求头
887
- let xhr = new XMLHttpRequest();
888
- xhr.open('GET', res.data || res.bodyText , true);
889
- // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
890
- xhr.onload = ({ currentTarget }) => {
891
- // 请求完成
892
- if (currentTarget.status === 200) { // 返回200
893
- this.contentView.innerHTML = currentTarget.response
894
- this.contentView.style.padding = '10px'
895
- // this.contentView.style.position = 'relative'
896
- this.$refs.pdfView.style.backgroundColor = '#FFFFFF'
897
- this.$refs.pdfView.appendChild(this.contentView)
898
- let allTr = Array.from(this.$refs.pdfView.getElementsByTagName('tr'))
899
- this.allTr = []
900
- for (let index = 0; index < allTr.length; index++) {
901
- if(value.includes(allTr[index].getAttribute('tag-id'))) {
902
- this.allTr.push(allTr[index])
903
- }
904
- }
905
- this.currentChange(1)
906
-
907
- }
908
- }
909
- xhr.send();
910
- })
911
- }
912
- } else {
913
- let div = document.createElement('div')
914
- div.innerText = '文件加载异常'
915
- this.contentView.appendChild(div)
916
- this.$refs.pdfView.appendChild(this.contentView)
917
- }
918
- })
919
- }
920
- },
921
- deep:true,
922
- immediate:true
923
- }
924
- },
925
- mounted () {
926
- if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
927
- this.isPC = false
928
- } else {
929
- this.isPC = true
930
- }
931
- }
932
- }
933
- </script>
934
-
935
- <style lang="less" scoped>
936
- .pdf_view {
937
- width: 100%;
938
- height: calc(100% - 110px);
939
- overflow: auto;
940
- background-color: #f5f7fb;
941
- // margin-bottom: 60px;
942
- box-sizing: border-box;
943
- // position: relative;
944
- // > div {
945
- // width: 100%;
946
- // height: 100%;
947
- // overflow: hidden;
948
- // overflow-y: auto;
949
- // position: relative;
950
- // }
951
- > iframe {
952
- width: 100%;
953
- height: 100%;
954
- }
955
- a:link {
956
- color: none;
957
- }
958
- a:visited {
959
- color: none;
960
- }
961
- a:hover {
962
- color: none;
963
- }
964
- a:active {
965
- color: none;
966
- }
967
- .btn_footer {
968
- width: 100%;
969
- height: 60px;
970
- display: flex;
971
- align-items: center;
972
- justify-content: space-around;
973
- position: absolute;
974
- bottom: 0px;
975
- left: 0;
976
- z-index: 999;
977
- background: #ffffff;
978
- .prev, .next {
979
- width: 35%;
980
- height: 40px;
981
- display: flex;
982
- align-items: center;
983
- justify-content: center;
984
- border-radius: 50px;
985
- cursor: pointer;
986
- }
987
- .prev {
988
- background: #F2F5FA;
989
- color: #000;
990
- }
991
- .next {
992
- background: #366aff;
993
- color: #ffffff;
994
- }
995
- }
996
- #pagination {
997
- .total-class {
998
- margin-right: 13px;
999
- font-weight: 400;
1000
- }
1001
-
1002
- position: absolute;
1003
- bottom: 0px;
1004
- right: 0;
1005
- width: 100%;
1006
- display: flex;
1007
- align-items: center;
1008
- justify-content: center;
1009
- height: 50px;
1010
- background-color: white;
1011
- box-shadow: 0px 0px 18px 0px rgba(29, 55, 129, 0.07);
1012
- border-radius: 5px;
1013
- z-index: 1000;
1014
-
1015
- /deep/.el-pagination {
1016
- margin-right: 110px;
1017
- }
1018
-
1019
- /deep/.el-pager {
1020
- background: #EDF0F6;
1021
- border-radius: 15px;
1022
- }
1023
-
1024
- /deep/.el-pagination.is-background .btn-next {
1025
- width: 30px;
1026
- height: 30px;
1027
- background: #EDF0F6;
1028
- border-radius: 50%;
1029
- }
1030
-
1031
- /deep/.el-pagination .btn-next {
1032
- width: 30px;
1033
- height: 30px;
1034
- background: #EDF0F6;
1035
- border-radius: 50%;
1036
- padding-left: 0;
1037
- margin-left: 5px;
1038
- }
1039
-
1040
- /deep/.el-pagination .btn-prev {
1041
- width: 30px;
1042
- height: 30px;
1043
- background: #EDF0F6;
1044
- border-radius: 50%;
1045
- padding-right: 0;
1046
- margin-right: 5px;
1047
- }
1048
-
1049
- /deep/.el-pagination button {
1050
- padding: 0;
1051
- min-width: 30px;
1052
- }
1053
-
1054
- /deep/.el-pager li {
1055
- background: #EDF0F6;
1056
- height: 30px;
1057
- min-width: 30px;
1058
- line-height: 30px;
1059
- font-size: 12px;
1060
- color: #717b90;
1061
- }
1062
-
1063
- /deep/.el-pager li:first-child {
1064
- border-bottom-left-radius: 15px !important;
1065
- border-top-left-radius: 15px !important;
1066
- }
1067
-
1068
- /deep/.el-pager li:last-child {
1069
- border-top-right-radius: 15px !important;
1070
- border-bottom-right-radius: 15px !important;
1071
- }
1072
-
1073
- /deep/.el-pager li.active {
1074
- width: 30px;
1075
- height: 30px;
1076
- min-width: 30px;
1077
- background: #366AFF;
1078
- border: 3px solid #A1B9FF;
1079
- border-radius: 50%;
1080
- line-height: 24px;
1081
- color: white;
1082
- }
1083
-
1084
- /deep/.el-pagination.is-background .el-pager li:not(.disabled).active {
1085
- background: #366AFF;
1086
- }
1087
- }
1088
- .change_scale {
1089
- width: 100%;
1090
- height: 50px;
1091
- position: absolute;
1092
- top: 50px;
1093
- left: 0;
1094
- background: #ffffff;
1095
- display: flex;
1096
- align-items: center;
1097
- padding: 0 10px;
1098
- box-sizing: border-box;
1099
- section {
1100
- cursor: pointer;
1101
- width: 30px;
1102
- height: 30px;
1103
- margin-right: 5px;
1104
- border-radius: 5px;
1105
- display: flex;
1106
- align-items: center;
1107
- justify-content: center;
1108
- i {
1109
- font-weight: 900;
1110
- }
1111
- }
1112
- section:hover {
1113
- background: rgba(221, 222, 223, 1);
1114
- }
1115
- }
1116
- }
1117
-
1118
- </style>
1119
- <style lang="less">
1120
- .animation {
1121
- animation-name: highlight;
1122
- animation-duration: 4s;
1123
- }
1124
- @keyframes highlight {
1125
- 0% {
1126
- background:rgba(255, 136, 0, 0.3);
1127
- }
1128
- 25% {
1129
- background:rgba(255, 136, 0, 0.6);
1130
- }
1131
- 50% {
1132
- background:rgba(255, 136, 0, 0.3);
1133
- }
1134
- 75% {
1135
- background:rgba(255, 136, 0, 0.6);
1136
- }
1137
- 100% {
1138
- background:rgba(255, 136, 0, 0.3);
1139
- }
1140
- }
1
+ <template>
2
+ <div
3
+ class="pdf_view"
4
+ ref="pdfView"
5
+ @scroll="pdfScroll"
6
+ :style="{
7
+ marginTop: isPC ? '50px' : '',
8
+ marginBottom: tagIds.length > 1 ? '60px' : '0px',
9
+ height: setHeight
10
+ }">
11
+ <div class="change_scale" v-if="isPC">
12
+ <section @click="changeScale('reduce')">
13
+ <i class="el-icon-minus"></i>
14
+ </section>
15
+ <el-divider direction="vertical"></el-divider>
16
+ <section @click="changeScale('zoom')">
17
+ <i class="el-icon-plus"></i>
18
+ </section>
19
+ <el-select size="small" v-model="handScale" @change="changeScale" placeholder="请选择">
20
+ <el-option
21
+ v-for="item in scaleList"
22
+ :key="item.value"
23
+ :label="item.label"
24
+ :value="item.value">
25
+ </el-option>
26
+ </el-select>
27
+ </div>
28
+ <div class="btn_footer" v-if="tagIds.length > 1 && !isPC">
29
+ <div class="prev" @click="prev">上一段</div>
30
+ <div class="next" @click="next">下一段</div>
31
+ </div>
32
+ <div id="pagination" v-if="tagIds.length > 1 && isPC">
33
+ <el-pagination :current-page="currentPage + 1" @current-change="currentChange" @prev-click="prev"
34
+ @next-click="next" layout="slot, prev, pager, next" :page-size="1" :total="tagIds.length">
35
+ <span class="total-class">答案由{{ tagIds.length }}段内容生成</span>
36
+ </el-pagination>
37
+ </div>
38
+ </div>
39
+ </template>
40
+
41
+ <script>
42
+ import _ from 'lodash'
43
+ // import * as pdfjsLib from 'pdfjs-dist'
44
+ // pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker';
45
+ // import { TextLayerBuilder } from "pdfjs-dist/web/pdf_viewer";
46
+ // EventBus pdf_viewer 支持绑定自定义事件,一版不做
47
+ // import 'pdfjs-dist/web/pdf_viewer.css'
48
+ /* eslint-disable */
49
+ const pdfjsLib = window['pdfjsLib']
50
+ if(pdfjsLib) {
51
+ pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
52
+ // 'pdfjs-dist/build/pdf.worker';
53
+ }
54
+ const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
55
+ // import { zoomElement } from '../assets/js/hammer'
56
+ export default {
57
+ name: 'pdfView',
58
+ props:['tagIds','isMessageRecord'],
59
+ data() {
60
+ return {
61
+ url: '',
62
+ pages: [],
63
+ pageLoadStatus: {
64
+ WAIT: 0,
65
+ LOADED: 1,
66
+ },
67
+ scale: 1,
68
+ rotation: 0,
69
+ pageSize: {},
70
+ PAGE_INTVERVAL: 15,
71
+ SLICE_COUNT: 5,
72
+ contentView: null,
73
+ fisrtLoad: true,
74
+ TextLayerBuilder: null,
75
+ totalPageCount: 0,
76
+ identifyTextPostion: {
77
+ top: 0,
78
+ left: 0,
79
+ width: 100,
80
+ height: 0,
81
+ page: 1,
82
+ pageHeight: 0,
83
+ pageWidth: 0,
84
+ extractInfo: {},
85
+ currentPageAllLine: []
86
+ },
87
+ currentPageAllLine: [],
88
+ pdfUrl: '',
89
+ cachePdf: [],
90
+ newViewer: null,
91
+ currentPage: 0,
92
+ changetoolbar: false,
93
+ allTr:[],
94
+ preViewType: 'pdf',
95
+ displacement:{
96
+ pageX: 0,
97
+ pageY: 0,
98
+ moveable: false,
99
+ pageX2: 0,
100
+ pageY2: 0,
101
+ originScale: 1,
102
+ },
103
+ isTouchMoved: false,
104
+ transformSalce: null,
105
+ isPC: false,
106
+ handScale: 'auto',
107
+ scaleList:[
108
+ {
109
+ label:'自动缩放',
110
+ value:'auto'
111
+ },
112
+ {
113
+ label:'实际比例',
114
+ value:'reality'
115
+ },
116
+ {
117
+ label:'100%',
118
+ value: 1
119
+ },
120
+ {
121
+ label:'120%',
122
+ value: 1.2
123
+ },
124
+ {
125
+ label:'150%',
126
+ value: 1.5
127
+ },
128
+ {
129
+ label:'170%',
130
+ value: 1.7
131
+ }
132
+ ,
133
+ {
134
+ label:'200%',
135
+ value: 2
136
+ }
137
+ ],
138
+ scrollTop:0,
139
+ scrollLeft:0
140
+ }
141
+ },
142
+ methods: {
143
+ getpdfResloutePage (pdfResloute) {
144
+ // 根据当前页面宽度设置缩放比例
145
+ // this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
146
+ // console.log(this.scale,'this.scale');
147
+ if(this.isMessageRecord) {
148
+ this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
149
+ } else {
150
+ this.scale = 2
151
+ }
152
+ // 从后端获取到当前分片后所有的pdf页码,初始化数组,数组下{} 对应每页pdf文件
153
+ this.pdfUrl = pdfResloute.publicPageFileUrl.substring(0, pdfResloute.publicPageFileUrl.lastIndexOf('/') + 1)
154
+ this.initPages(pdfResloute.total)
155
+ // 定位功能,加载对应页码位置
156
+ this.loadPdfData(pdfResloute.page)
157
+ },
158
+ async loadPdfData (loadPage) {
159
+ if(this.pages[loadPage - 1] && ((this.pages[loadPage - 1].dom && this.pages[loadPage - 1].dom.children.length > 0) || this.pages[loadPage - 1].loading)) {
160
+ return
161
+ }
162
+ this.pages[loadPage - 1].loading = true
163
+ // pdfjsLib.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/legacy/build/pdf.worker.entry.js");
164
+ // 拿到第一个分片
165
+ const { startPage, url } = await this.fetchPdfFragment(loadPage);
166
+ let loadingTask = pdfjsLib.getDocument(url)
167
+ loadingTask.promise.then((pdfDoc) => {
168
+ // 将已经下载的分片保存到 pages 数组中
169
+ for (let i = 0; i < pdfDoc.numPages; i += 1) {
170
+ const pageIndex = startPage + i;
171
+ const page = this.pages[pageIndex - 1];
172
+ // 不在缓存列表内,重新获取本页pdf
173
+ if (page.loadStatus !== this.pageLoadStatus.LOADED) {
174
+ pdfDoc.getPage(i + 1).then((pdfPage) => {
175
+ page.pdfPage = pdfPage;
176
+ page.loadStatus = this.pageLoadStatus.LOADED;
177
+ // 通知可以进行渲染了
178
+ this.startRenderPages(pdfPage, page, pageIndex)
179
+ });
180
+ } else {
181
+ if (this.changetoolbar) {
182
+ this.$nextTick(() => {
183
+ this.renderHighlights()
184
+ })
185
+ this.changetoolbar = false
186
+ }
187
+ }
188
+ }
189
+ });
190
+ },
191
+ initPages (totalPage) {
192
+ // const pages = [];
193
+ this.totalPageCount = totalPage
194
+ for (let i = 0; i < totalPage; i += 1) {
195
+ this.pages.push({
196
+ pageNo: i + 1,
197
+ loadStatus: this.pageLoadStatus.WAIT,
198
+ pdfPage: null,
199
+ dom: null
200
+ });
201
+ }
202
+ },
203
+ async fetchPdfFragment (pageIndex) {
204
+ // 置换加签后的文件地址。
205
+ let obj = {}
206
+ await this.$http.post(
207
+ '/knowledge-api/temporary-certificate/or-origin?expired=30',
208
+ this.pdfUrl + pageIndex + '.pdf',
209
+ {
210
+ headers: {
211
+ "Content-Type": "application/json",
212
+ },
213
+ }).then(async res => {
214
+ if(res.bodyText) {
215
+ // 最后返回一个 包含这4个参数的对象
216
+ obj = await {
217
+ "startPage": pageIndex, // 分片的开始页码
218
+ "endPage": pageIndex + 5, // 分片结束页码
219
+ "totalPage": this.totalPageCount, // pdf 总页数
220
+ "url": res.bodyText // 分片内容下载地址
221
+ }
222
+ }
223
+ if (res.data) {
224
+ // 最后返回一个 包含这4个参数的对象
225
+ obj = await {
226
+ "startPage": pageIndex, // 分片的开始页码
227
+ "endPage": pageIndex + 5, // 分片结束页码
228
+ "totalPage": this.totalPageCount, // pdf 总页数
229
+ "url": res.data // 分片内容下载地址
230
+ }
231
+ }
232
+ })
233
+ return obj
234
+ },
235
+ startRenderPages (pdfPage, page, pageIndex) {
236
+ if(Object.keys(this.pageSize).length == 0) {
237
+ const viewport = pdfPage.getViewport({
238
+ scale: this.scale, // 缩放的比例
239
+ rotation: this.rotation, // 旋转的角度
240
+ });
241
+ // 记录pdf页面高度
242
+ const pageSize = {
243
+ width: viewport.width,
244
+ height: viewport.height,
245
+ }
246
+ this.pageSize = pageSize
247
+ // 创建内容绘制区,并设置大小
248
+ if(this.$refs.pdfView.clientWidth / this.pageSize.width >= 1 || this.isMessageRecord) {
249
+ this.contentView.style.width = `${pageSize.width - 10 }px`;
250
+ this.contentView.style.height = `${(this.totalPageCount * (pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
251
+ } else {
252
+ this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
253
+ this.contentView.style.width = `${pageSize.width * this.transformSalce - 10}px`;
254
+ this.contentView.style.height = `${(this.totalPageCount * (pageSize.height * (this.transformSalce) + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
255
+ }
256
+ this.contentView.style.margin = '0 auto 0'
257
+ this.contentView.style.position = 'relative'
258
+ this.contentView.style.paddingBottom = '60px'
259
+ // contentView.style.overflowY = 'auto'
260
+ this.$refs.pdfView.appendChild(this.contentView);
261
+ }
262
+ this.renderPages(pageIndex)
263
+ },
264
+ renderPageContent (page, pageIndex) {
265
+ const { pdfPage, pageNo, dom } = page;
266
+ // dom 元素已存在,无须重新渲染,直接返回
267
+ if (dom && dom.children.length != 0) {
268
+ return;
269
+ }
270
+ const viewport = pdfPage.getViewport({
271
+ scale: this.scale,
272
+ rotation: this.rotation,
273
+ });
274
+ // 创建新的canvas
275
+ const canvas = document.createElement('canvas');
276
+ const context = canvas.getContext('2d');
277
+ // canvas.getContext('2d');
278
+ canvas.height = this.pageSize.height;
279
+ canvas.width = this.pageSize.width;
280
+ // 创建渲染的dom
281
+ const pageDom = document.createElement('div');
282
+ pageDom.style.position = 'absolute';
283
+ pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
284
+ pageDom.style.width = `${this.pageSize.width}px`;
285
+ pageDom.style.height = `${this.pageSize.height}px`;
286
+ pageDom.appendChild(canvas);
287
+ // 渲染内容
288
+ let renderContext = {
289
+ canvasContext: context,
290
+ viewport: viewport,
291
+ }
292
+ pdfPage.render(renderContext).promise.then(() => {
293
+ console.log(pdfPage.getTextContent(), 'getTextContent');
294
+ return pdfPage.getTextContent()
295
+ }).then((textContent) => {
296
+ const textLayerDiv = document.createElement('div');
297
+ textLayerDiv.setAttribute('class', 'textLayer');
298
+ // 将文本图层div添加至每页pdf的div中
299
+ // 创建新的TextLayerBuilder实例
300
+ let textLayer = new TextLayerBuilder({
301
+ textLayerDiv: textLayerDiv,
302
+ pageIndex: pdfPage._pageIndex,
303
+ viewport: viewport,
304
+ });
305
+ let findPage = this.currentPageAllLine.find(l => { return l.page == pageIndex })
306
+ let rectdomTop = 0
307
+ if (findPage) {
308
+ let AllLines = findPage.allLines
309
+ // setTimeout(() => {
310
+ console.log(findPage,'findPage');
311
+ if (AllLines.length > 0) {
312
+ for (let j = 0; j < AllLines.length; j++) {
313
+ let lines = AllLines[j].lines
314
+ let rectdom = document.createElement('div')
315
+ rectdom.setAttribute('react-count', AllLines[j].pageCount);
316
+ rectdom.style.position = 'absolute';
317
+ rectdom.style.top = 0
318
+ rectdom.style.left = 0
319
+ rectdom.classList.add('rectdom')
320
+ for (let index = 0; index < lines.length; index++) {
321
+ if (!/^\s+$/g.test(lines[index].content)) {
322
+ let postionArr = lines[index].location
323
+ let div = document.createElement('div')
324
+ div.style.position = 'absolute';
325
+ div.style.left = postionArr[0] * this.scale + 'px',
326
+ // 后端返回的坐标有基线对齐的问题,top 值是后端算好(基线top - 文字高度),在此加上文字高度的 1/9 (大致比例)为实际展示出文字的top值
327
+ div.style.top = (postionArr[1] + postionArr[3] / 9) * this.scale + 'px'
328
+ div.style.height = postionArr[3] * this.scale + 'px';
329
+ div.style.width = postionArr[2] * this.scale + 'px'
330
+ div.style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
331
+ div.classList.add('lineHeight')
332
+ rectdom.appendChild(div)
333
+ if(index == 0 && j == 0) {
334
+ if(this.transformSalce !== null) {
335
+ rectdomTop = (postionArr[1] + postionArr[3] / 9) * this.scale * this.transformSalce
336
+ } else {
337
+ rectdomTop = (postionArr[1] + postionArr[3] / 9) * this.scale
338
+ }
339
+ // if(this.isPC) {
340
+ // rectdomTop = rectdomTop - 50 < 0 ? 0 : rectdomTop - 50
341
+ // }
342
+ // console.log(rectdomTop,div.style.top, (postionArr[1] + postionArr[3] / 9) * this.scale);
343
+ }
344
+ }
345
+ }
346
+ if (rectdom.children.length > 0) {
347
+ pageDom.appendChild(rectdom)
348
+ }
349
+ }
350
+ }
351
+ }
352
+ textLayer.setTextContent(textContent);
353
+ textLayer.render()
354
+ pageDom.appendChild(textLayer.textLayerDiv);
355
+ page.dom = pageDom;
356
+ page.loading = false
357
+ this.contentView.appendChild(pageDom);
358
+ if(this.transformSalce !== null) {
359
+ this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
360
+ }
361
+ if (this.changetoolbar) {
362
+ setTimeout(() => {
363
+ this.renderHighlights()
364
+ this.changetoolbar = false
365
+ }, 500)
366
+ }
367
+ // console.log(this.fisrtLoad,'this.fisrtLoad');
368
+ if (this.fisrtLoad) {
369
+ setTimeout(() => {
370
+ let pageoffsetHeight = 0
371
+ if(this.transformSalce !== null) {
372
+ pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce
373
+ } else {
374
+ pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL)
375
+ }
376
+ if (this.$refs.pdfView.clientHeight - pageoffsetHeight > 0 && pageIndex == 1) {
377
+ const height = this.$refs.pdfView.clientHeight;
378
+ let startNum = 0
379
+ let endNum = 0
380
+ if(this.transformSalce !== null) {
381
+ startNum = Math.ceil(this.$refs.pdfView.scrollTop / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
382
+ endNum = startNum + Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
383
+ console.log( Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce)),this.pageSize.height , this.PAGE_INTVERVAL, height, this.transformSalce,'startNum');
384
+
385
+ } else {
386
+ startNum = Math.ceil(this.$refs.pdfView.scrollTop / (this.pageSize.height + this.PAGE_INTVERVAL))
387
+ endNum = startNum + Math.ceil(height / (this.pageSize.height + this.PAGE_INTVERVAL))
388
+
389
+ }
390
+ for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
391
+ if(pageIndex > 0 && pageIndex <= this.pages.length) {
392
+ this.loadPdfData(pageIndex)
393
+ }
394
+ }
395
+ }
396
+ if (this.$refs.pdfView.scrollTop == Math.floor((pageNo - 1) * pageoffsetHeight)) {
397
+ this.$refs.pdfView.scrollTop = rectdomTop
398
+ this.fisrtLoad = false
399
+ } else {
400
+ this.$refs.pdfView.scrollTop = `${((pageNo - 1) * pageoffsetHeight) + rectdomTop - this.PAGE_INTVERVAL}`
401
+ this.fisrtLoad = false
402
+ }
403
+ this.renderHighlights()
404
+ // zoomElement(this.contentView)
405
+ }, 100)
406
+ }
407
+ })
408
+ },
409
+ // 监听容器的滚动事件,触发 scrollPdf 方法
410
+ // 这里加了防抖保证不会一次产生过多请求
411
+ debounceScrollPdf: _.debounce(function (e, that) {
412
+ if (this.fisrtLoad) {
413
+ this.fisrtLoad = false
414
+ return
415
+ }
416
+ const scrollTop = e.target.scrollTop;
417
+ const height = e.target.clientHeight;
418
+ let startNum = 0
419
+ let endNum = 0
420
+ if(this.transformSalce !== null) {
421
+ startNum = Math.ceil(scrollTop / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
422
+ endNum = startNum + Math.ceil(height / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
423
+ } else {
424
+ startNum = Math.ceil(scrollTop / (that.pageSize.height + that.PAGE_INTVERVAL))
425
+ endNum = startNum + Math.ceil(height / (that.pageSize.height + that.PAGE_INTVERVAL))
426
+ }
427
+ for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
428
+ if(pageIndex > 0 && pageIndex <= that.pages.length) {
429
+ that.loadPdfData(pageIndex)
430
+ }
431
+ }
432
+ console.log('=======');
433
+ }, 200),
434
+ directScrolling (e, that) {
435
+ if (this.fisrtLoad) {
436
+ this.fisrtLoad = false
437
+ return
438
+ }
439
+ const scrollTop = e.target.scrollTop;
440
+ const height = e.target.clientHeight;
441
+ // 根据内容可视区域中心点计算页码, 没有滚动时,指向第一页
442
+ const pageIndex = scrollTop > 0 ?
443
+ Math.ceil((scrollTop + (height / 2)) / (that.pageSize.height + that.PAGE_INTVERVAL)) :
444
+ 1;
445
+ this.loadPdfData(pageIndex)
446
+ },
447
+ pdfScroll (e) {
448
+ if(this.preViewType !== 'pdf' || this.isTouchMoved) {
449
+ return
450
+ }
451
+ if(this.scrollLeft != e.target.scrollLeft) {
452
+ this.scrollLeft = e.target.scrollLeft
453
+ }
454
+ if(this.scrollTop != e.target.scrollTop) {
455
+ this.scrollTop = e.target.scrollTop
456
+ this.debounceScrollPdf(e, this)
457
+ }
458
+ },
459
+ // 分片每次只做一次处理,所以不考虑多片情况
460
+ loadBefore (pageIndex) {
461
+ this.loadPdfData(pageIndex)
462
+ },
463
+ loadAfter (pageIndex) {
464
+ this.loadPdfData(pageIndex)
465
+ },
466
+ // 首先我们获取到需要渲染的范围
467
+ // 根据当前的可视范围内的页码,我们前后只保留 8 页
468
+ getRenderScope (pageIndex) {
469
+ const pagesToRender = [];
470
+ let i = pageIndex - 1;
471
+ let j = pageIndex + 1;
472
+ // pageIndex - 1 表示当前页码数 对应的下标位置
473
+ pagesToRender.push(this.pages[pageIndex - 1]);
474
+ while (pagesToRender.length < 8 && pagesToRender.length < this.pages.length) {
475
+ if (i > 0) {
476
+ pagesToRender.push(this.pages[i - 1]);
477
+ i -= 1;
478
+ }
479
+ if (pagesToRender.length >= 8) {
480
+ break;
481
+ }
482
+ if (j <= this.pages.length) {
483
+ pagesToRender.push(this.pages[j - 1]);
484
+ j += 1;
485
+ }
486
+ }
487
+ return pagesToRender;
488
+ },
489
+ // 渲染需要展示的页面,不需展示的页码将其清除
490
+ renderPages (pageIndex) {
491
+ const pagesToRender = this.getRenderScope(pageIndex);
492
+ for (const i of this.pages) {
493
+ if (pagesToRender.includes(i)) {
494
+ i.loadStatus === this.pageLoadStatus.LOADED ?
495
+ this.renderPageContent(i, pageIndex) :
496
+ this.renderPageLoading(i);
497
+ } else {
498
+ this.clearPage(i);
499
+ }
500
+ }
501
+ },
502
+ // 清除页面 dom
503
+ clearPage (page) {
504
+ if (page.dom) {
505
+ this.contentView.removeChild(page.dom);
506
+ page.loadStatus = 0
507
+ page.loading = false
508
+ page.dom = undefined;
509
+ }
510
+ },
511
+ // 页面正在下载时渲染loading视图
512
+ renderPageLoading (page) {
513
+ const { pageNo, dom } = page;
514
+ if (dom && dom.children.length != 0) {
515
+ return;
516
+ }
517
+ const pageDom = document.createElement('div');
518
+ pageDom.style.width = `${this.pageSize.width}px`;
519
+ pageDom.style.height = `${this.pageSize.height}px`;
520
+ pageDom.style.position = 'absolute';
521
+ pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL
522
+ }px`;
523
+ pageDom.style.backgroundImage = `url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif')`
524
+ pageDom.style.backgroundPosition = 'center'
525
+ pageDom.style.backgroundRepeat = 'no-repeat'
526
+ pageDom.style.backgroundColor = '#FFF'
527
+ page.dom = pageDom;
528
+ this.contentView.appendChild(pageDom);
529
+ },
530
+ prev () {
531
+ this.currentPage--
532
+ if (this.currentPage < 0) {
533
+ this.currentPage = 0
534
+ if(!this.isPC) {
535
+ this.$toast({
536
+ message:'当前已经是第一段了',
537
+ duration:2000,
538
+ })
539
+ return
540
+ }
541
+ }
542
+ if(this.preViewType == 'pdf') {
543
+ this.scrollToUplaodePage(this.currentPage)
544
+ } else {
545
+ this.scrollToExcalTop(this.currentPage)
546
+ }
547
+ // this.getpdfResloutePage(this.cachePdf[this.currentPage - 1])
548
+ },
549
+ next () {
550
+ this.currentPage++
551
+ if (this.currentPage >= this.tagIds.length) {
552
+ this.currentPage = this.tagIds.length - 1
553
+ if(!this.isPC) {
554
+ this.$toast({
555
+ message:'当前已经是最后一段了',
556
+ duration:2000,
557
+ })
558
+ return
559
+ }
560
+ }
561
+ if(this.preViewType == 'pdf') {
562
+ this.scrollToUplaodePage(this.currentPage)
563
+ } else {
564
+ this.scrollToExcalTop(this.currentPage)
565
+ }
566
+ },
567
+ currentChange (value) {
568
+ this.currentPage = value - 1
569
+ if(this.preViewType == 'pdf') {
570
+ this.scrollToUplaodePage(this.currentPage)
571
+ } else {
572
+ this.scrollToExcalTop(this.currentPage)
573
+ }
574
+ },
575
+ scrollToUplaodePage (currentPage) {
576
+ this.changetoolbar = true
577
+ if(this.preViewType !== 'pdf') {
578
+ return
579
+ }
580
+
581
+ let pdfResloute = this.cachePdf[currentPage]
582
+ this.identifyTextPostion.extractInfo = pdfResloute.extractInfo
583
+ this.identifyTextPostion.left = pdfResloute.extractInfo.location[0]
584
+ this.identifyTextPostion.top = pdfResloute.extractInfo.location[1]
585
+ this.identifyTextPostion.width = pdfResloute.extractInfo.location[2]
586
+ this.identifyTextPostion.height = pdfResloute.extractInfo.location[3]
587
+ this.identifyTextPostion.page = pdfResloute.page
588
+ this.identifyTextPostion.pageHeight = pdfResloute.pageHeight
589
+ this.identifyTextPostion.pageWidth = pdfResloute.pageWidth
590
+ // 在当前段落在最后一页pdf时,根据计算的高度并不能触发滚动,在此执行重新渲染方法,非次情况会执行两次,待优化
591
+ this.$nextTick(() => {
592
+ this.renderHighlights()
593
+ })
594
+ if(this.transformSalce !== null) {
595
+ this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce) + (this.identifyTextPostion.top * this.scale * this.transformSalce)}`
596
+ } else {
597
+ this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + (this.identifyTextPostion.top * this.scale * this.transformSalce)}`
598
+ }
599
+ },
600
+ scrollToExcalTop(currentPage) {
601
+ for (let index = 0; index < this.allTr.length; index++) {
602
+ if(index == currentPage) {
603
+ Array.from(this.allTr[index].children).forEach(item =>{
604
+ item.style.background = 'rgba(255, 136, 0, 0.6)'
605
+ item.classList.add('animation')
606
+ setTimeout(() =>{
607
+ item.classList.remove('animation')
608
+ }, 4000)
609
+ })
610
+ // getBoundingClientRect().top 当前元素距离屏幕顶部的高度 + 弹窗header 高度
611
+ if(!this.isPC) {
612
+ let top = this.allTr[index].getBoundingClientRect().top - this.$refs.pdfView.getBoundingClientRect().top
613
+ this.$refs.pdfView.scrollTop = top
614
+ } else {
615
+ let top = this.allTr[index].getBoundingClientRect().top
616
+ this.$refs.pdfView.scrollTop = top - 50
617
+ }
618
+ } else {
619
+ Array.from(this.allTr[index].children).forEach(item =>{
620
+ item.style.background = 'rgba(54, 106, 255, 0.6)'
621
+ item.classList.remove('animation')
622
+ })
623
+ }
624
+ }
625
+ },
626
+ // pdf是否需要重新渲染高亮位置
627
+ renderHighlights () {
628
+ let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
629
+ console.log(lineHeightDom, this.currentPage, 'this.currentPage');
630
+ if (lineHeightDom) {
631
+ lineHeightDom.forEach((d) => {
632
+ for (let i = 0; i < d.children.length; i++) {
633
+ if (d.getAttribute('react-count') == this.currentPage) {
634
+ d.children[i].style.backgroundColor = 'rgba(255, 136, 0, 0.3)'
635
+ d.children[i].classList.add('animation')
636
+ setTimeout(() =>{
637
+ d.children[i].classList.remove('animation')
638
+ }, 4000)
639
+ } else {
640
+ d.children[i].style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
641
+ d.children[i].classList.remove('animation')
642
+ }
643
+ }
644
+ })
645
+ }
646
+ },
647
+ displayHiglight (pageIndex) {
648
+ let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
649
+ if (lineHeightDom) {
650
+ lineHeightDom.forEach((d) => {
651
+ if (d.getAttribute('page-index') == pageIndex) {
652
+ d.style.display = 'none'
653
+ }
654
+ })
655
+ }
656
+ },
657
+ // 前端暂时缓存多页
658
+ autoLoadMore (pageIndex) {
659
+ let pdfResloute = this.cachePdf.find(cache => {
660
+ return cache.page == pageIndex
661
+ })
662
+ if (pdfResloute) {
663
+ this.getpdfResloutePage(pdfResloute)
664
+ } else {
665
+ this.loadPdfData(pageIndex)
666
+ }
667
+ },
668
+ setPageAllLine (arr) {
669
+ this.currentPageAllLine = []
670
+ arr.forEach((item, index) => {
671
+ let i = this.currentPageAllLine.findIndex(l => { return l.page && l.page == item.page })
672
+ if (i != -1) {
673
+ // this.currentPageAllLine[i].allLines.lines.push(item.extractInfo.lines)
674
+ this.currentPageAllLine[i].allLines.push({
675
+ pageCount: index,
676
+ lines: item.extractInfo.lines
677
+ })
678
+ } else {
679
+ this.currentPageAllLine.push({
680
+ page: item.page,
681
+ allLines: [{
682
+ pageCount: index,
683
+ lines: item.extractInfo.lines
684
+ }],
685
+ })
686
+ }
687
+ })
688
+ },
689
+ openTouch() {
690
+ // this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
691
+ let that = this;
692
+ this.$nextTick(() => {
693
+ // setInterval(() => {
694
+ // this.scale = this.scale + 0.1
695
+ // that.pages.forEach((item, index) =>{
696
+ // if(item.dom) {
697
+ // item.dom.children.forEach( childDom =>{
698
+ // if(childDom.getAttribute('react-count')) {
699
+ // childDom.style.transform = "scale(" + this.scale + ")";
700
+ // childDom.style.transformOrigin = "0px 0px 0px";
701
+ // } else {
702
+ // item.dom = null
703
+ // this.startRenderPages(item.pdfPage, null, index)
704
+ // }
705
+ // } )
706
+ // }
707
+ // })
708
+ // }, 100);
709
+ // 获取放大或缩小的区域DOM
710
+ let matrix_box = this.contentView
711
+ matrix_box.addEventListener("touchstart", function (event) {
712
+ this.isTouchMoved = true
713
+ let touches = event.touches;
714
+ let events = touches[0];
715
+ let events2 = touches[1];
716
+
717
+ // event.preventDefault();
718
+
719
+ // 第一个触摸点的坐标
720
+ that.displacement.pageX = events.pageX;
721
+ that.displacement.pageY = events.pageY;
722
+
723
+ that.displacement.moveable = true;
724
+
725
+ if (events2) {
726
+ that.displacement.pageX2 = events2.pageX;
727
+ that.displacement.pageY2 = events2.pageY;
728
+ }
729
+
730
+ that.displacement.originScale = this.scale || 1;
731
+ // console.log(that.displacement);
732
+ });
733
+ document.addEventListener("touchmove", function (event) {
734
+ if (!that.displacement.moveable) {
735
+ return;
736
+ }
737
+ // event.preventDefault();
738
+ let touches = event.touches;
739
+ let events = touches[0];
740
+ let events2 = touches[1];
741
+ // 双指移动
742
+ if (events2) {
743
+ // 第2个指头坐标在touchmove时候获取
744
+ if (!that.displacement.pageX2) {
745
+ that.displacement.pageX2 = events2.pageX;
746
+ }
747
+ if (!that.displacement.pageY2) {
748
+ that.displacement.pageY2 = events2.pageY;
749
+ }
750
+ // 双指缩放比例计算
751
+ let zoom = that.getDistance({
752
+ x: events.pageX,
753
+ y: events.pageY
754
+ },
755
+ {
756
+ x: events2.pageX,
757
+ y: events2.pageY
758
+ }
759
+ ) / that.getDistance(
760
+ {
761
+ x: that.displacement.pageX,
762
+ y: that.displacement.pageY
763
+ },
764
+ {
765
+ x: that.displacement.pageX2,
766
+ y: that.displacement.pageY2
767
+ }
768
+ );
769
+ // 应用在元素上的缩放比例
770
+ let newScale = that.displacement.originScale * zoom;
771
+ console.log(zoom, newScale , this.scale, 'newScale');
772
+ // 最大缩放比例限制
773
+ if (newScale > 2) {
774
+ newScale = 2;
775
+ }
776
+ // 最大缩放比例限制
777
+ if(newScale < 1) {
778
+ newScale = 1;
779
+ }
780
+ // 记住使用的缩放值
781
+ that.displacement.scale = newScale;
782
+ // console.log(newScale);
783
+ matrix_box.style.transform = "scale(" + newScale + ")";
784
+ // 设置旋转元素的基点位置
785
+ matrix_box.style.transformOrigin = "0px 0px 0px";
786
+ }
787
+ },{ passive: false });
788
+ document.addEventListener('touchend',function() {
789
+ that.isTouchMoved = false
790
+ },{ passive: false })
791
+ });
792
+ },
793
+ getDistance(start, stop) {
794
+ // Math.hypot()计算参数的平方根
795
+ return Math.hypot(stop.x - start.x, stop.y - start.y);
796
+ },
797
+ setupCanvas(canvas, width, height) {
798
+ const dpr = 1;
799
+ // const rect = canvas.getBoundingClientRect();
800
+ canvas.width = width
801
+ canvas.height = height
802
+ const ctx = canvas.getContext('2d');
803
+ console.log(canvas.width, canvas.height, dpr, this.scale);
804
+ ctx?.scale(dpr, dpr );
805
+ return ctx;
806
+ },
807
+ changeScale(value) {
808
+ if(value == 'zoom') {
809
+ this.handScale = 'auto'
810
+ this.transformSalce = (this.transformSalce + 0.2).toFixed(1)
811
+ } else if(value == 'reduce') {
812
+ if((this.transformSalce - 0.2).toFixed(1) <= 0) {
813
+ return
814
+ }
815
+ this.handScale = 'auto'
816
+ this.transformSalce = (this.transformSalce - 0.2).toFixed(1)
817
+ } else if(value == 'auto') {
818
+ this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
819
+ } else if(value == 'reality') {
820
+ this.transformSalce = 0.5
821
+ } else {
822
+ this.transformSalce = (value / 2).toFixed(1)
823
+ }
824
+ this.transformSalce = Number(this.transformSalce)
825
+ this.contentView.style.transform = 'scale(' + this.transformSalce + ')';
826
+ // this.getpdfResloutePage(this.cachePdf[0])
827
+ },
828
+ },
829
+ computed:{
830
+ perviewUrl() {
831
+ return '/web/viewer.html?file=' + '/pdflist/pdf4split-1.pdf'
832
+ },
833
+ setHeight() {
834
+ if(this.tagIds.length > 1 ) {
835
+ if(this.isPC) {
836
+ return 'calc(100% - 110px)'
837
+ } else {
838
+ return 'calc(100% - 60px)'
839
+ }
840
+ } else {
841
+ if(this.isPC) {
842
+ return 'calc(100% - 50px)'
843
+ } else {
844
+ return '100%'
845
+ }
846
+ }
847
+ }
848
+ },
849
+ watch:{
850
+ tagIds: {
851
+ handler(value) {
852
+ if(value && value.length) {
853
+ // 在 pdf_view 下创建 所有canvs的容器
854
+ this.contentView = document.createElement('div')
855
+ this.contentView.style.transformOrigin = '0px 0px 0px'
856
+ this.$http.get('/knowledge-api/knowledge/knowledge-part-location-info/list?ids=' + value.join(',')).then(res =>{
857
+ // 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}
858
+ // 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}
859
+ // 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}
860
+ // 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}
861
+ // 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}
862
+ // if(value.length === 1) {
863
+ // this.$refs.pdfView.style.height = 'calc(100% - 50px)'
864
+ // }
865
+ // res.data = {
866
+ // "data": [
867
+ // {
868
+ // "id": "6501ae851169c35ace9739f7",
869
+ // "knowledgeId": "6501ae444f324a70bf677cce",
870
+ // "mainId": "b3cec709ed904d56b29cb95362dc181f",
871
+ // "page": 5,
872
+ // "total": 118,
873
+ // "pageHeight": 540.0,
874
+ // "pageWidth": 960.00946,
875
+ // "publicPageFileUrl": "https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/b3cec709ed904d56b29cb95362dc181f/2023/09/13/08/43/12/6501ae451169c35ace9739b7/5.pdf",
876
+ // "extractInfo": {
877
+ // "location": [
878
+ // 42.208,
879
+ // 297.014,
880
+ // 723.56104,
881
+ // 41.18799
882
+ // ],
883
+ // "content": "体验整体提升,推出全渠道、智能化知识管理平台,面向员工智能服务,业务自动化,知识智能搜索与问答场景。成为飞书ISVAI交互专利发布国家高新技术企业北京市科技型中小企业认证北京市创新型中小企业认证AAA企业信用评价认证优衣库",
884
+ // "lines": [
885
+ // {
886
+ // "content": "体验整体提升,推出全",
887
+ // "location": [
888
+ // 42.208,
889
+ // 297.014,
890
+ // 119.874016,
891
+ // 11.990997
892
+ // ]
893
+ // },
894
+ // {
895
+ // "content": "渠道、智能化知识管理",
896
+ // "location": [
897
+ // 42.208,
898
+ // 314.50302,
899
+ // 119.874016,
900
+ // 11.990997
901
+ // ]
902
+ // },
903
+ // {
904
+ // "content": "平台,面向员工智能服",
905
+ // "location": [
906
+ // 42.208,
907
+ // 332.022,
908
+ // 119.874016,
909
+ // 11.990997
910
+ // ]
911
+ // },
912
+ // {
913
+ // "content": "务,业务自动化,知识",
914
+ // "location": [
915
+ // 42.208,
916
+ // 349.398,
917
+ // 119.874016,
918
+ // 11.990997
919
+ // ]
920
+ // },
921
+ // {
922
+ // "content": "智能搜索与问答场景。",
923
+ // "location": [
924
+ // 42.208,
925
+ // 366.916,
926
+ // 119.874016,
927
+ // 11.990997
928
+ // ]
929
+ // },
930
+ // {
931
+ // "content": "成为飞书",
932
+ // "location": [
933
+ // 362.409,
934
+ // 270.311,
935
+ // 47.951996,
936
+ // 11.990997
937
+ // ]
938
+ // },
939
+ // {
940
+ // "content": "ISV",
941
+ // "location": [
942
+ // 362.409,
943
+ // 284.711,
944
+ // 18.47815,
945
+ // 11.990997
946
+ // ]
947
+ // },
948
+ // {
949
+ // "content": "AI交互专利发",
950
+ // "location": [
951
+ // 362.409,
952
+ // 300.018,
953
+ // 74.64407,
954
+ // 11.990997
955
+ // ]
956
+ // },
957
+ // {
958
+ // "content": "布",
959
+ // "location": [
960
+ // 362.409,
961
+ // 314.418,
962
+ // 11.990997,
963
+ // 11.990997
964
+ // ]
965
+ // },
966
+ // {
967
+ // "content": "国家高新技术企",
968
+ // "location": [
969
+ // 363.713,
970
+ // 330.009,
971
+ // 83.93698,
972
+ // 11.990997
973
+ // ]
974
+ // },
975
+ // {
976
+ // "content": "业",
977
+ // "location": [
978
+ // 363.713,
979
+ // 344.409,
980
+ // 11.990997,
981
+ // 11.990997
982
+ // ]
983
+ // },
984
+ // {
985
+ // "content": "北京市科技型中小企业认",
986
+ // "location": [
987
+ // 363.798,
988
+ // 359.915,
989
+ // 131.90097,
990
+ // 11.990997
991
+ // ]
992
+ // },
993
+ // {
994
+ // "content": "证",
995
+ // "location": [
996
+ // 363.798,
997
+ // 374.315,
998
+ // 11.990997,
999
+ // 11.990997
1000
+ // ]
1001
+ // },
1002
+ // {
1003
+ // "content": "北京市创新型中小企业认",
1004
+ // "location": [
1005
+ // 363.798,
1006
+ // 389.905,
1007
+ // 131.90097,
1008
+ // 11.990997
1009
+ // ]
1010
+ // },
1011
+ // {
1012
+ // "content": "证",
1013
+ // "location": [
1014
+ // 363.798,
1015
+ // 404.22,
1016
+ // 11.990997,
1017
+ // 11.990997
1018
+ // ]
1019
+ // },
1020
+ // {
1021
+ // "content": "AAA企业信用评价认",
1022
+ // "location": [
1023
+ // 362.409,
1024
+ // 419.811,
1025
+ // 112.02899,
1026
+ // 11.990997
1027
+ // ]
1028
+ // },
1029
+ // {
1030
+ // "content": "证",
1031
+ // "location": [
1032
+ // 362.409,
1033
+ // 434.09702,
1034
+ // 11.990997,
1035
+ // 11.990997
1036
+ // ]
1037
+ // },
1038
+ // {
1039
+ // "content": "优衣库",
1040
+ // "location": [
1041
+ // 729.808,
1042
+ // 326.211,
1043
+ // 35.96106,
1044
+ // 11.990997
1045
+ // ]
1046
+ // }
1047
+ // ],
1048
+ // "tagId": null
1049
+ // },
1050
+ // "block": {
1051
+ // "type": "TEXT",
1052
+ // "location": [
1053
+ // 42.208,
1054
+ // 297.014,
1055
+ // 723.56104,
1056
+ // 41.18799
1057
+ // ],
1058
+ // "color": null,
1059
+ // "flowChart": null,
1060
+ // "image": null,
1061
+ // "table": null,
1062
+ // "text": {
1063
+ // "originText": "体验整体提升,推出全渠道、智能化知识管理平台,面向员工智能服务,业务自动化,知识智能搜索与问答场景。成为飞书ISVAI交互专利发布国家高新技术企业北京市科技型中小企业认证北京市创新型中小企业认证AAA企业信用评价认证优衣库",
1064
+ // "indexText": "体验整体提升,推出全渠道、智能化知识管理平台,面向员工智能服务,业务自动化,知识智能搜索与问答场景。成为飞书ISVAI交互专利发布国家高新技术企业北京市科技型中小企业认证北京市创新型中小企业认证AAA企业信用评价认证优衣库",
1065
+ // "lines": [
1066
+ // {
1067
+ // "location": [
1068
+ // 42.208,
1069
+ // 297.014,
1070
+ // 119.874016,
1071
+ // 11.990997
1072
+ // ]
1073
+ // },
1074
+ // {
1075
+ // "location": [
1076
+ // 42.208,
1077
+ // 314.50302,
1078
+ // 119.874016,
1079
+ // 11.990997
1080
+ // ]
1081
+ // },
1082
+ // {
1083
+ // "location": [
1084
+ // 42.208,
1085
+ // 332.022,
1086
+ // 119.874016,
1087
+ // 11.990997
1088
+ // ]
1089
+ // },
1090
+ // {
1091
+ // "location": [
1092
+ // 42.208,
1093
+ // 349.398,
1094
+ // 119.874016,
1095
+ // 11.990997
1096
+ // ]
1097
+ // },
1098
+ // {
1099
+ // "location": [
1100
+ // 42.208,
1101
+ // 366.916,
1102
+ // 119.874016,
1103
+ // 11.990997
1104
+ // ]
1105
+ // },
1106
+ // {
1107
+ // "location": [
1108
+ // 362.409,
1109
+ // 270.311,
1110
+ // 47.951996,
1111
+ // 11.990997
1112
+ // ]
1113
+ // },
1114
+ // {
1115
+ // "location": [
1116
+ // 362.409,
1117
+ // 284.711,
1118
+ // 18.47815,
1119
+ // 11.990997
1120
+ // ]
1121
+ // },
1122
+ // {
1123
+ // "location": [
1124
+ // 362.409,
1125
+ // 300.018,
1126
+ // 74.64407,
1127
+ // 11.990997
1128
+ // ]
1129
+ // },
1130
+ // {
1131
+ // "location": [
1132
+ // 362.409,
1133
+ // 314.418,
1134
+ // 11.990997,
1135
+ // 11.990997
1136
+ // ]
1137
+ // },
1138
+ // {
1139
+ // "location": [
1140
+ // 363.713,
1141
+ // 330.009,
1142
+ // 83.93698,
1143
+ // 11.990997
1144
+ // ]
1145
+ // },
1146
+ // {
1147
+ // "location": [
1148
+ // 363.713,
1149
+ // 344.409,
1150
+ // 11.990997,
1151
+ // 11.990997
1152
+ // ]
1153
+ // },
1154
+ // {
1155
+ // "location": [
1156
+ // 363.798,
1157
+ // 359.915,
1158
+ // 131.90097,
1159
+ // 11.990997
1160
+ // ]
1161
+ // },
1162
+ // {
1163
+ // "location": [
1164
+ // 363.798,
1165
+ // 374.315,
1166
+ // 11.990997,
1167
+ // 11.990997
1168
+ // ]
1169
+ // },
1170
+ // {
1171
+ // "location": [
1172
+ // 363.798,
1173
+ // 389.905,
1174
+ // 131.90097,
1175
+ // 11.990997
1176
+ // ]
1177
+ // },
1178
+ // {
1179
+ // "location": [
1180
+ // 363.798,
1181
+ // 404.22,
1182
+ // 11.990997,
1183
+ // 11.990997
1184
+ // ]
1185
+ // },
1186
+ // {
1187
+ // "location": [
1188
+ // 362.409,
1189
+ // 419.811,
1190
+ // 112.02899,
1191
+ // 11.990997
1192
+ // ]
1193
+ // },
1194
+ // {
1195
+ // "location": [
1196
+ // 362.409,
1197
+ // 434.09702,
1198
+ // 11.990997,
1199
+ // 11.990997
1200
+ // ]
1201
+ // },
1202
+ // {
1203
+ // "location": [
1204
+ // 729.808,
1205
+ // 326.211,
1206
+ // 35.96106,
1207
+ // 11.990997
1208
+ // ]
1209
+ // }
1210
+ // ]
1211
+ // }
1212
+ // }
1213
+ // },
1214
+ // {
1215
+ // "id": "6501ae871169c35ace973a87",
1216
+ // "knowledgeId": "6501ae444f324a70bf677cce",
1217
+ // "mainId": "b3cec709ed904d56b29cb95362dc181f",
1218
+ // "page": 32,
1219
+ // "total": 118,
1220
+ // "pageHeight": 540.0,
1221
+ // "pageWidth": 960.00946,
1222
+ // "publicPageFileUrl": "https://askbot-pdf-all.oss-cn-zhangjiakou.aliyuncs.com/b3cec709ed904d56b29cb95362dc181f/2023/09/13/08/43/12/6501ae451169c35ace9739b7/32.pdf",
1223
+ // "extractInfo": {
1224
+ // "location": [
1225
+ // 28.913,
1226
+ // 30.983013,
1227
+ // 307.587,
1228
+ // 28.006
1229
+ // ],
1230
+ // "content": "智能化知识管理价值体现",
1231
+ // "lines": [
1232
+ // {
1233
+ // "content": "智能化知识管理价值体现",
1234
+ // "location": [
1235
+ // 28.913,
1236
+ // 30.983013,
1237
+ // 307.587,
1238
+ // 28.006
1239
+ // ]
1240
+ // }
1241
+ // ],
1242
+ // "tagId": null
1243
+ // },
1244
+ // "block": {
1245
+ // "type": "TEXT",
1246
+ // "location": [
1247
+ // 28.913,
1248
+ // 30.983013,
1249
+ // 307.587,
1250
+ // 28.006
1251
+ // ],
1252
+ // "color": null,
1253
+ // "flowChart": null,
1254
+ // "image": null,
1255
+ // "table": null,
1256
+ // "text": {
1257
+ // "originText": "智能化知识管理价值体现",
1258
+ // "indexText": "智能化知识管理价值体现",
1259
+ // "lines": [
1260
+ // {
1261
+ // "location": [
1262
+ // 28.913,
1263
+ // 30.983013,
1264
+ // 307.587,
1265
+ // 28.006
1266
+ // ]
1267
+ // }
1268
+ // ]
1269
+ // }
1270
+ // }
1271
+ // }
1272
+ // ],
1273
+ // "code": "0",
1274
+ // "msg": null,
1275
+ // "traceId": null
1276
+ // }
1277
+ if (res.data.code == 0) {
1278
+ // tagIds 会按照gpt识别的生成有序的数组,前端直接按照下标的顺序取就可以了
1279
+ // 缓存拿到的所有数据
1280
+ this.cachePdf = res.data.data
1281
+ let publicPageFileUrl = res.data.data[0].publicPageFileUrl
1282
+ this.currentPage = 0
1283
+ // console.log(publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')));
1284
+ if (publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')) === '.pdf') {
1285
+ this.preViewType = 'pdf'
1286
+ this.setPageAllLine(this.cachePdf)
1287
+ this.getpdfResloutePage(res.data.data[0])
1288
+ } else {
1289
+ this.preViewType = 'excal'
1290
+ this.$http.post(
1291
+ '/knowledge-api/temporary-certificate/or-origin?expired=30',
1292
+ publicPageFileUrl,
1293
+ {
1294
+ headers: {
1295
+ "Content-Type": "application/json",
1296
+ },
1297
+ }).then(res => {
1298
+ // 使用原声请求方式 axios会带有不需要的请求头
1299
+ let xhr = new XMLHttpRequest();
1300
+ xhr.open('GET', res.data || res.bodyText , true);
1301
+ // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
1302
+ xhr.onload = ({ currentTarget }) => {
1303
+ // 请求完成
1304
+ if (currentTarget.status === 200) { // 返回200
1305
+ this.contentView.innerHTML = currentTarget.response
1306
+ this.contentView.style.padding = '10px'
1307
+ // this.contentView.style.position = 'relative'
1308
+ this.$refs.pdfView.style.backgroundColor = '#FFFFFF'
1309
+ this.$refs.pdfView.appendChild(this.contentView)
1310
+ let allTr = Array.from(this.$refs.pdfView.getElementsByTagName('tr'))
1311
+ this.allTr = []
1312
+ for (let index = 0; index < allTr.length; index++) {
1313
+ if(value.includes(allTr[index].getAttribute('tag-id'))) {
1314
+ this.allTr.push(allTr[index])
1315
+ }
1316
+ }
1317
+ this.currentChange(1)
1318
+
1319
+ }
1320
+ }
1321
+ xhr.send();
1322
+ })
1323
+ }
1324
+ } else {
1325
+ let div = document.createElement('div')
1326
+ div.innerText = '文件加载异常'
1327
+ this.contentView.appendChild(div)
1328
+ this.$refs.pdfView.appendChild(this.contentView)
1329
+ }
1330
+ })
1331
+ }
1332
+ },
1333
+ deep:true,
1334
+ immediate:true
1335
+ }
1336
+ },
1337
+ mounted () {
1338
+ if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
1339
+ this.isPC = false
1340
+ } else {
1341
+ this.isPC = true
1342
+ }
1343
+ }
1344
+ }
1345
+ </script>
1346
+
1347
+ <style lang="less" scoped>
1348
+ .pdf_view {
1349
+ width: 100%;
1350
+ height: calc(100% - 110px);
1351
+ overflow: auto;
1352
+ background-color: #f5f7fb;
1353
+ // margin-bottom: 60px;
1354
+ box-sizing: border-box;
1355
+ // position: relative;
1356
+ // > div {
1357
+ // width: 100%;
1358
+ // height: 100%;
1359
+ // overflow: hidden;
1360
+ // overflow-y: auto;
1361
+ // position: relative;
1362
+ // }
1363
+ > iframe {
1364
+ width: 100%;
1365
+ height: 100%;
1366
+ }
1367
+ a:link {
1368
+ color: none;
1369
+ }
1370
+ a:visited {
1371
+ color: none;
1372
+ }
1373
+ a:hover {
1374
+ color: none;
1375
+ }
1376
+ a:active {
1377
+ color: none;
1378
+ }
1379
+ .btn_footer {
1380
+ width: 100%;
1381
+ height: 60px;
1382
+ display: flex;
1383
+ align-items: center;
1384
+ justify-content: space-around;
1385
+ position: absolute;
1386
+ bottom: 0px;
1387
+ left: 0;
1388
+ z-index: 999;
1389
+ background: #ffffff;
1390
+ .prev, .next {
1391
+ width: 35%;
1392
+ height: 40px;
1393
+ display: flex;
1394
+ align-items: center;
1395
+ justify-content: center;
1396
+ border-radius: 50px;
1397
+ cursor: pointer;
1398
+ }
1399
+ .prev {
1400
+ background: #F2F5FA;
1401
+ color: #000;
1402
+ }
1403
+ .next {
1404
+ background: #366aff;
1405
+ color: #ffffff;
1406
+ }
1407
+ }
1408
+ #pagination {
1409
+ .total-class {
1410
+ margin-right: 13px;
1411
+ font-weight: 400;
1412
+ }
1413
+
1414
+ position: absolute;
1415
+ bottom: 0px;
1416
+ right: 0;
1417
+ width: 100%;
1418
+ display: flex;
1419
+ align-items: center;
1420
+ justify-content: center;
1421
+ height: 50px;
1422
+ background-color: white;
1423
+ box-shadow: 0px 0px 18px 0px rgba(29, 55, 129, 0.07);
1424
+ border-radius: 5px;
1425
+ z-index: 1000;
1426
+
1427
+ /deep/.el-pagination {
1428
+ margin-right: 110px;
1429
+ }
1430
+
1431
+ /deep/.el-pager {
1432
+ background: #EDF0F6;
1433
+ border-radius: 15px;
1434
+ }
1435
+
1436
+ /deep/.el-pagination.is-background .btn-next {
1437
+ width: 30px;
1438
+ height: 30px;
1439
+ background: #EDF0F6;
1440
+ border-radius: 50%;
1441
+ }
1442
+
1443
+ /deep/.el-pagination .btn-next {
1444
+ width: 30px;
1445
+ height: 30px;
1446
+ background: #EDF0F6;
1447
+ border-radius: 50%;
1448
+ padding-left: 0;
1449
+ margin-left: 5px;
1450
+ }
1451
+
1452
+ /deep/.el-pagination .btn-prev {
1453
+ width: 30px;
1454
+ height: 30px;
1455
+ background: #EDF0F6;
1456
+ border-radius: 50%;
1457
+ padding-right: 0;
1458
+ margin-right: 5px;
1459
+ }
1460
+
1461
+ /deep/.el-pagination button {
1462
+ padding: 0;
1463
+ min-width: 30px;
1464
+ }
1465
+
1466
+ /deep/.el-pager li {
1467
+ background: #EDF0F6;
1468
+ height: 30px;
1469
+ min-width: 30px;
1470
+ line-height: 30px;
1471
+ font-size: 12px;
1472
+ color: #717b90;
1473
+ }
1474
+
1475
+ /deep/.el-pager li:first-child {
1476
+ border-bottom-left-radius: 15px !important;
1477
+ border-top-left-radius: 15px !important;
1478
+ }
1479
+
1480
+ /deep/.el-pager li:last-child {
1481
+ border-top-right-radius: 15px !important;
1482
+ border-bottom-right-radius: 15px !important;
1483
+ }
1484
+
1485
+ /deep/.el-pager li.active {
1486
+ width: 30px;
1487
+ height: 30px;
1488
+ min-width: 30px;
1489
+ background: #366AFF;
1490
+ border: 3px solid #A1B9FF;
1491
+ border-radius: 50%;
1492
+ line-height: 24px;
1493
+ color: white;
1494
+ }
1495
+
1496
+ /deep/.el-pagination.is-background .el-pager li:not(.disabled).active {
1497
+ background: #366AFF;
1498
+ }
1499
+ }
1500
+ .change_scale {
1501
+ width: 100%;
1502
+ height: 50px;
1503
+ position: absolute;
1504
+ top: 50px;
1505
+ left: 0;
1506
+ background: #ffffff;
1507
+ display: flex;
1508
+ align-items: center;
1509
+ padding: 0 10px;
1510
+ box-sizing: border-box;
1511
+ section {
1512
+ cursor: pointer;
1513
+ width: 30px;
1514
+ height: 30px;
1515
+ margin-right: 5px;
1516
+ border-radius: 5px;
1517
+ display: flex;
1518
+ align-items: center;
1519
+ justify-content: center;
1520
+ i {
1521
+ font-weight: 900;
1522
+ }
1523
+ }
1524
+ section:hover {
1525
+ background: rgba(221, 222, 223, 1);
1526
+ }
1527
+ }
1528
+ }
1529
+
1530
+ </style>
1531
+ <style lang="less">
1532
+ .animation {
1533
+ animation-name: highlight;
1534
+ animation-duration: 4s;
1535
+ }
1536
+ @keyframes highlight {
1537
+ 0% {
1538
+ background:rgba(255, 136, 0, 0.3);
1539
+ }
1540
+ 25% {
1541
+ background:rgba(255, 136, 0, 0.6);
1542
+ }
1543
+ 50% {
1544
+ background:rgba(255, 136, 0, 0.3);
1545
+ }
1546
+ 75% {
1547
+ background:rgba(255, 136, 0, 0.6);
1548
+ }
1549
+ 100% {
1550
+ background:rgba(255, 136, 0, 0.3);
1551
+ }
1552
+ }
1141
1553
  </style>