askbot-dragon 1.4.96 → 1.4.97

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 (85) 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 +211 -211
  20. package/src/components/ActionAlertIframe.vue +112 -112
  21. package/src/components/AiGuide.vue +467 -467
  22. package/src/components/AnswerDocknowledge.vue +490 -490
  23. package/src/components/AnswerVoice.vue +285 -285
  24. package/src/components/AskIFrame.vue +15 -15
  25. package/src/components/ConversationContainer.vue +4660 -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 +3558 -3558
  46. package/src/components/loadingProcess.vue +164 -164
  47. package/src/components/message/ActionAlertIframe.vue +112 -112
  48. package/src/components/message/ShopMessage.vue +164 -164
  49. package/src/components/message/TextMessage.vue +924 -924
  50. package/src/components/message/TicketMessage.vue +177 -177
  51. package/src/components/message/swiper/index.js +4 -4
  52. package/src/components/message/swiper/ticketSwiper.vue +503 -503
  53. package/src/components/message/swiper/ticketSwiperItem.vue +61 -61
  54. package/src/components/msgLoading.vue +231 -231
  55. package/src/components/myPopup.vue +70 -70
  56. package/src/components/pdfPosition.vue +1113 -1110
  57. package/src/components/popup.vue +227 -227
  58. package/src/components/previewDoc.vue +228 -228
  59. package/src/components/previewPdf.vue +290 -290
  60. package/src/components/receiverMessagePlatform.vue +65 -65
  61. package/src/components/recommend.vue +89 -89
  62. package/src/components/selector/hOption.vue +20 -20
  63. package/src/components/selector/hSelector.vue +199 -199
  64. package/src/components/selector/hWrapper.vue +216 -216
  65. package/src/components/senderMessagePlatform.vue +50 -50
  66. package/src/components/source/BotMessage.vue +24 -24
  67. package/src/components/source/CustomMessage.vue +24 -24
  68. package/src/components/test.vue +260 -260
  69. package/src/components/tree.vue +294 -294
  70. package/src/components/utils/AliyunIssUtil.js +81 -81
  71. package/src/components/utils/ckeditor.js +174 -174
  72. package/src/components/utils/ckeditorImageUpload/command.js +109 -109
  73. package/src/components/utils/ckeditorImageUpload/editing.js +11 -11
  74. package/src/components/utils/ckeditorImageUpload/plugin-image.js +11 -11
  75. package/src/components/utils/ckeditorImageUpload/toolbar-ui.js +40 -40
  76. package/src/components/utils/ckeditorfileUpload/common.js +180 -180
  77. package/src/components/utils/ckeditorfileUpload/editing.js +11 -11
  78. package/src/components/utils/ckeditorfileUpload/plugin_file.js +11 -11
  79. package/src/components/utils/ckeditorfileUpload/toolbar_ui.js +34 -34
  80. package/src/components/utils/format_date.js +25 -25
  81. package/src/components/utils/index.js +6 -6
  82. package/src/components/utils/math_utils.js +29 -29
  83. package/src/components/voiceComponent.vue +119 -119
  84. package/src/main.js +60 -60
  85. package/vue.config.js +55 -55
@@ -1,1111 +1,1114 @@
1
- <template>
2
- <div
3
- class="pdf_view"
4
- ref="pdfView"
5
- @scroll="pdfScroll"
6
- :style="{
7
- marginTop: isPC ? '50px' : ''
8
- }">
9
- <div class="change_scale" v-if="isPC">
10
- <section @click="changeScale('reduce')">
11
- <i class="el-icon-minus"></i>
12
- </section>
13
- <el-divider direction="vertical"></el-divider>
14
- <section @click="changeScale('zoom')">
15
- <i class="el-icon-plus"></i>
16
- </section>
17
- <el-select size="small" v-model="handScale" @change="changeScale" placeholder="请选择">
18
- <el-option
19
- v-for="item in scaleList"
20
- :key="item.value"
21
- :label="item.label"
22
- :value="item.value">
23
- </el-option>
24
- </el-select>
25
- </div>
26
- <div class="btn_footer" v-if="tagIds.length > 1 && !isPC">
27
- <div class="prev" @click="prev">上一段</div>
28
- <div class="next" @click="next">下一段</div>
29
- </div>
30
- <div id="pagination" v-if="tagIds.length > 1 && isPC">
31
- <el-pagination :current-page="currentPage + 1" @current-change="currentChange" @prev-click="prev"
32
- @next-click="next" layout="slot, prev, pager, next" :page-size="1" :total="tagIds.length">
33
- <span class="total-class">答案由{{ tagIds.length }}段内容生成</span>
34
- </el-pagination>
35
- </div>
36
- </div>
37
- </template>
38
-
39
- <script>
40
- import _ from 'lodash'
41
- // import * as pdfjsLib from 'pdfjs-dist'
42
- // pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker';
43
- // import { TextLayerBuilder } from "pdfjs-dist/web/pdf_viewer";
44
- // EventBus pdf_viewer 支持绑定自定义事件,一版不做
45
- // import 'pdfjs-dist/web/pdf_viewer.css'
46
- /* eslint-disable */
47
- const pdfjsLib = window['pdfjsLib']
48
- if(pdfjsLib) {
49
- pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
50
- // 'pdfjs-dist/build/pdf.worker';
51
- }
52
- const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
53
- // import { zoomElement } from '../assets/js/hammer'
54
- export default {
55
- name: 'pdfView',
56
- props:['tagIds','isMessageRecord'],
57
- data() {
58
- return {
59
- url: '',
60
- pages: [],
61
- pageLoadStatus: {
62
- WAIT: 0,
63
- LOADED: 1,
64
- },
65
- scale: 1,
66
- rotation: 0,
67
- pageSize: {},
68
- PAGE_INTVERVAL: 15,
69
- SLICE_COUNT: 5,
70
- contentView: null,
71
- fisrtLoad: true,
72
- TextLayerBuilder: null,
73
- totalPageCount: 0,
74
- identifyTextPostion: {
75
- top: 0,
76
- left: 0,
77
- width: 100,
78
- height: 0,
79
- page: 1,
80
- pageHeight: 0,
81
- pageWidth: 0,
82
- extractInfo: {},
83
- currentPageAllLine: []
84
- },
85
- currentPageAllLine: [],
86
- pdfUrl: '',
87
- cachePdf: [],
88
- newViewer: null,
89
- currentPage: 0,
90
- changetoolbar: false,
91
- allTr:[],
92
- preViewType: 'pdf',
93
- displacement:{
94
- pageX: 0,
95
- pageY: 0,
96
- moveable: false,
97
- pageX2: 0,
98
- pageY2: 0,
99
- originScale: 1,
100
- },
101
- isTouchMoved: false,
102
- transformSalce: null,
103
- isPC: false,
104
- handScale: 'auto',
105
- scaleList:[
106
- {
107
- label:'自动缩放',
108
- value:'auto'
109
- },
110
- {
111
- label:'实际比例',
112
- value:'reality'
113
- },
114
- {
115
- label:'100%',
116
- value: 1
117
- },
118
- {
119
- label:'120%',
120
- value: 1.2
121
- },
122
- {
123
- label:'150%',
124
- value: 1.5
125
- },
126
- {
127
- label:'170%',
128
- value: 1.7
129
- }
130
- ,
131
- {
132
- label:'200%',
133
- value: 2
134
- }
135
- ],
136
- scrollTop:0,
137
- scrollLeft:0
138
- }
139
- },
140
- methods: {
141
- getpdfResloutePage (pdfResloute) {
142
- // 根据当前页面宽度设置缩放比例
143
- // this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
144
- // console.log(this.scale,'this.scale');
145
- if(this.isMessageRecord) {
146
- this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
147
- } else {
148
- this.scale = 2
149
- }
150
- // 从后端获取到当前分片后所有的pdf页码,初始化数组,数组下{} 对应每页pdf文件
151
- this.pdfUrl = pdfResloute.publicPageFileUrl.substring(0, pdfResloute.publicPageFileUrl.lastIndexOf('/') + 1)
152
- this.initPages(pdfResloute.total)
153
- // 定位功能,加载对应页码位置
154
- this.loadPdfData(pdfResloute.page)
155
- },
156
- async loadPdfData (loadPage) {
157
- if(this.pages[loadPage - 1] && this.pages[loadPage - 1].dom && this.pages[loadPage - 1].dom.children.length > 0) {
158
- return
159
- }
160
- // pdfjsLib.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/legacy/build/pdf.worker.entry.js");
161
- // 拿到第一个分片
162
- const { startPage, url } = await this.fetchPdfFragment(loadPage);
163
- let loadingTask = pdfjsLib.getDocument(url)
164
- loadingTask.promise.then((pdfDoc) => {
165
- // 将已经下载的分片保存到 pages 数组中
166
- for (let i = 0; i < pdfDoc.numPages; i += 1) {
167
- const pageIndex = startPage + i;
168
- const page = this.pages[pageIndex - 1];
169
- // 不在缓存列表内,重新获取本页pdf
170
- if (page.loadStatus !== this.pageLoadStatus.LOADED) {
171
- pdfDoc.getPage(i + 1).then((pdfPage) => {
172
- page.pdfPage = pdfPage;
173
- page.loadStatus = this.pageLoadStatus.LOADED;
174
- // 通知可以进行渲染了
175
- this.startRenderPages(pdfPage, page, pageIndex)
176
- });
177
- } else {
178
- if (this.changetoolbar) {
179
- this.$nextTick(() => {
180
- this.renderHighlights()
181
- })
182
- this.changetoolbar = false
183
- }
184
- }
185
- }
186
- });
187
- },
188
- initPages (totalPage) {
189
- // const pages = [];
190
- this.totalPageCount = totalPage
191
- for (let i = 0; i < totalPage; i += 1) {
192
- this.pages.push({
193
- pageNo: i + 1,
194
- loadStatus: this.pageLoadStatus.WAIT,
195
- pdfPage: null,
196
- dom: null
197
- });
198
- }
199
- },
200
- async fetchPdfFragment (pageIndex) {
201
- // 置换加签后的文件地址。
202
- let obj = {}
203
- await this.$http.post(
204
- '/knowledge-api/temporary-certificate/or-origin?expired=30',
205
- this.pdfUrl + pageIndex + '.pdf',
206
- {
207
- headers: {
208
- "Content-Type": "application/json",
209
- },
210
- }).then(async res => {
211
- if(res.bodyText) {
212
- // 最后返回一个 包含这4个参数的对象
213
- obj = await {
214
- "startPage": pageIndex, // 分片的开始页码
215
- "endPage": pageIndex + 5, // 分片结束页码
216
- "totalPage": this.totalPageCount, // pdf 总页数
217
- "url": res.bodyText // 分片内容下载地址
218
- }
219
- }
220
- if (res.data) {
221
- // 最后返回一个 包含这4个参数的对象
222
- obj = await {
223
- "startPage": pageIndex, // 分片的开始页码
224
- "endPage": pageIndex + 5, // 分片结束页码
225
- "totalPage": this.totalPageCount, // pdf 总页数
226
- "url": res.data // 分片内容下载地址
227
- }
228
- }
229
- })
230
- return obj
231
- },
232
- startRenderPages (pdfPage, page, pageIndex) {
233
- const viewport = pdfPage.getViewport({
234
- scale: this.scale, // 缩放的比例
235
- rotation: this.rotation, // 旋转的角度
236
- });
237
- // 记录pdf页面高度
238
- const pageSize = {
239
- width: viewport.width,
240
- height: viewport.height,
241
- }
242
- this.pageSize = pageSize
243
- // 创建内容绘制区,并设置大小
244
- if(this.$refs.pdfView.clientWidth / this.pageSize.width >= 1 || this.isMessageRecord) {
245
- this.contentView.style.width = `${pageSize.width }px`;
246
- this.contentView.style.height = `${(this.totalPageCount * (pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
247
- } else {
248
- this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
249
- this.contentView.style.width = `${pageSize.width * this.transformSalce}px`;
250
- this.contentView.style.height = `${(this.totalPageCount * (pageSize.height * (this.transformSalce) + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
251
- }
252
- this.contentView.style.margin = '0 auto 0'
253
- console.log(this.transformSalce);
254
- this.contentView.style.position = 'relative'
255
- this.contentView.style.paddingBottom = '60px'
256
- // contentView.style.overflowY = 'auto'
257
- this.$refs.pdfView.appendChild(this.contentView);
258
- this.renderPages(pageIndex)
259
- },
260
- renderPageContent (page, pageIndex) {
261
- const { pdfPage, pageNo, dom } = page;
262
- // dom 元素已存在,无须重新渲染,直接返回
263
- console.log(dom, 'dom');
264
- if (dom && dom.children.length != 0) {
265
- return;
266
- }
267
- const viewport = pdfPage.getViewport({
268
- scale: this.scale,
269
- rotation: this.rotation,
270
- });
271
- // 创建新的canvas
272
- const canvas = document.createElement('canvas');
273
- const context = canvas.getContext('2d');
274
- // canvas.getContext('2d');
275
- canvas.height = this.pageSize.height;
276
- canvas.width = this.pageSize.width;
277
- // 创建渲染的dom
278
- const pageDom = document.createElement('div');
279
- pageDom.style.position = 'absolute';
280
- pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
281
- pageDom.style.width = `${this.pageSize.width}px`;
282
- pageDom.style.height = `${this.pageSize.height}px`;
283
- pageDom.appendChild(canvas);
284
- // 渲染内容
285
- let renderContext = {
286
- canvasContext: context,
287
- viewport: viewport,
288
- }
289
- pdfPage.render(renderContext).promise.then(() => {
290
- console.log(pdfPage.getTextContent(), 'getTextContent');
291
- return pdfPage.getTextContent()
292
- }).then((textContent) => {
293
- const textLayerDiv = document.createElement('div');
294
- textLayerDiv.setAttribute('class', 'textLayer');
295
- // 将文本图层div添加至每页pdf的div中
296
- // 创建新的TextLayerBuilder实例
297
- let textLayer = new TextLayerBuilder({
298
- textLayerDiv: textLayerDiv,
299
- pageIndex: pdfPage._pageIndex,
300
- viewport: viewport,
301
- });
302
- let findPage = this.currentPageAllLine.find(l => { return l.page == pageIndex })
303
- let rectdomTop = 0
304
- if (findPage) {
305
- let AllLines = findPage.allLines
306
- // setTimeout(() => {
307
- if (AllLines.length > 0) {
308
- for (let j = 0; j < AllLines.length; j++) {
309
- let lines = AllLines[j].lines
310
- let rectdom = document.createElement('div')
311
- rectdom.setAttribute('react-count', AllLines[j].pageCount);
312
- rectdom.style.position = 'absolute';
313
- rectdom.style.top = 0
314
- rectdom.style.left = 0
315
- rectdom.classList.add('rectdom')
316
- for (let index = 0; index < lines.length; index++) {
317
- if (!/^\s+$/g.test(lines[index].content)) {
318
- let postionArr = lines[index].location
319
- let div = document.createElement('div')
320
- div.style.position = 'absolute';
321
- div.style.left = postionArr[0] * this.scale + 'px',
322
- // 后端返回的坐标有基线对齐的问题,top 值是后端算好(基线top - 文字高度),在此加上文字高度的 1/9 (大致比例)为实际展示出文字的top值
323
- div.style.top = (postionArr[1] + postionArr[3] / 9) * this.scale + 'px'
324
- div.style.height = postionArr[3] * this.scale + 'px';
325
- div.style.width = postionArr[2] * this.scale + 'px'
326
- div.style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
327
- div.classList.add('lineHeight')
328
- rectdom.appendChild(div)
329
- if(index == 0 && j == 0) {
330
- rectdomTop = postionArr[1]
331
- }
332
- }
333
- }
334
- if (rectdom.children.length > 0) {
335
- pageDom.appendChild(rectdom)
336
- }
337
- }
338
- }
339
- }
340
- textLayer.setTextContent(textContent);
341
- textLayer.render()
342
- pageDom.appendChild(textLayer.textLayerDiv);
343
- page.dom = pageDom;
344
- this.contentView.appendChild(pageDom);
345
- if(this.transformSalce !== null) {
346
- this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
347
- }
348
- if (this.changetoolbar) {
349
- setTimeout(() => {
350
- this.renderHighlights()
351
- this.changetoolbar = false
352
- }, 100)
353
- }
354
- if (this.fisrtLoad) {
355
- setTimeout(() => {
356
- let pageoffsetHeight = 0
357
- if(this.transformSalce !== null) {
358
- pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce
359
- } else {
360
- pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL)
361
- }
362
- if (this.$refs.pdfView.clientHeight - pageoffsetHeight > 0) {
363
- const height = this.$refs.pdfView.clientHeight;
364
- let startNum = 0
365
- let endNum = 0
366
- if(this.transformSalce !== null) {
367
- startNum = Math.ceil(this.$refs.pdfView.scrollTop / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
368
- endNum = startNum + Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
369
- console.log( Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce)),this.pageSize.height , this.PAGE_INTVERVAL, height, this.transformSalce,'startNum');
370
-
371
- } else {
372
- startNum = Math.ceil(this.$refs.pdfView.scrollTop / (this.pageSize.height + this.PAGE_INTVERVAL))
373
- endNum = startNum + Math.ceil(height / (this.pageSize.height + this.PAGE_INTVERVAL))
374
-
375
- }
376
- for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
377
- if(pageIndex > 0 && pageIndex <= this.pages.length) {
378
- this.loadPdfData(pageIndex)
379
- }
380
- }
381
- }
382
-
383
- if (this.$refs.pdfView.scrollTop == Math.floor((pageNo - 1) * pageoffsetHeight)) {
384
- this.fisrtLoad = false
385
- } else {
386
- this.$refs.pdfView.scrollTop = `${((pageNo - 1) * pageoffsetHeight) + rectdomTop - this.PAGE_INTVERVAL}`
387
- this.fisrtLoad = false
388
- }
389
- this.renderHighlights()
390
- // zoomElement(this.contentView)
391
- }, 100)
392
- }
393
- })
394
- },
395
- // 监听容器的滚动事件,触发 scrollPdf 方法
396
- // 这里加了防抖保证不会一次产生过多请求
397
- debounceScrollPdf: _.debounce(function (e, that) {
398
- if (this.fisrtLoad) {
399
- this.fisrtLoad = false
400
- return
401
- }
402
- const scrollTop = e.target.scrollTop;
403
- const height = e.target.clientHeight;
404
- let startNum = 0
405
- let endNum = 0
406
- if(this.transformSalce !== null) {
407
- startNum = Math.ceil(scrollTop / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
408
- endNum = startNum + Math.ceil(height / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
409
- } else {
410
- startNum = Math.ceil(scrollTop / (that.pageSize.height + that.PAGE_INTVERVAL))
411
- endNum = startNum + Math.ceil(height / (that.pageSize.height + that.PAGE_INTVERVAL))
412
- }
413
- for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
414
- console.log(pageIndex,pageIndex >= 0 && pageIndex <= that.pages.length, 'pageIndexpageIndexpageIndex');
415
- if(pageIndex > 0 && pageIndex <= that.pages.length) {
416
- that.loadPdfData(pageIndex)
417
- }
418
- }
419
- console.log('=======');
420
- }, 200),
421
- directScrolling (e, that) {
422
- if (this.fisrtLoad) {
423
- this.fisrtLoad = false
424
- return
425
- }
426
- const scrollTop = e.target.scrollTop;
427
- const height = e.target.clientHeight;
428
- // 根据内容可视区域中心点计算页码, 没有滚动时,指向第一页
429
- const pageIndex = scrollTop > 0 ?
430
- Math.ceil((scrollTop + (height / 2)) / (that.pageSize.height + that.PAGE_INTVERVAL)) :
431
- 1;
432
- this.loadPdfData(pageIndex)
433
- },
434
- pdfScroll (e) {
435
- if(this.preViewType !== 'pdf' || this.isTouchMoved) {
436
- return
437
- }
438
- if(this.scrollLeft != e.target.scrollLeft) {
439
- this.scrollLeft = e.target.scrollLeft
440
- }
441
- if(this.scrollTop != e.target.scrollTop) {
442
- this.scrollTop = e.target.scrollTop
443
- this.debounceScrollPdf(e, this)
444
- }
445
- },
446
- // 分片每次只做一次处理,所以不考虑多片情况
447
- loadBefore (pageIndex) {
448
- this.loadPdfData(pageIndex)
449
- },
450
- loadAfter (pageIndex) {
451
- this.loadPdfData(pageIndex)
452
- },
453
- // 首先我们获取到需要渲染的范围
454
- // 根据当前的可视范围内的页码,我们前后只保留 8 页
455
- getRenderScope (pageIndex) {
456
- const pagesToRender = [];
457
- let i = pageIndex - 1;
458
- let j = pageIndex + 1;
459
- // pageIndex - 1 表示当前页码数 对应的下标位置
460
- pagesToRender.push(this.pages[pageIndex - 1]);
461
- while (pagesToRender.length < 8 && pagesToRender.length < this.pages.length) {
462
- if (i > 0) {
463
- pagesToRender.push(this.pages[i - 1]);
464
- i -= 1;
465
- }
466
- if (pagesToRender.length >= 8) {
467
- break;
468
- }
469
- if (j <= this.pages.length) {
470
- pagesToRender.push(this.pages[j - 1]);
471
- j += 1;
472
- }
473
- }
474
- return pagesToRender;
475
- },
476
- // 渲染需要展示的页面,不需展示的页码将其清除
477
- renderPages (pageIndex) {
478
- const pagesToRender = this.getRenderScope(pageIndex);
479
- for (const i of this.pages) {
480
- if (pagesToRender.includes(i)) {
481
- i.loadStatus === this.pageLoadStatus.LOADED ?
482
- this.renderPageContent(i, pageIndex) :
483
- this.renderPageLoading(i);
484
- } else {
485
- this.clearPage(i);
486
- }
487
- }
488
- },
489
- // 清除页面 dom
490
- clearPage (page) {
491
- if (page.dom) {
492
- this.contentView.removeChild(page.dom);
493
- page.loadStatus = 0
494
- page.dom = undefined;
495
- }
496
- },
497
- // 页面正在下载时渲染loading视图
498
- renderPageLoading (page) {
499
- const { pageNo, dom } = page;
500
- if (dom && dom.children.length != 0) {
501
- return;
502
- }
503
- const pageDom = document.createElement('div');
504
- pageDom.style.width = `${this.pageSize.width}px`;
505
- pageDom.style.height = `${this.pageSize.height}px`;
506
- pageDom.style.position = 'absolute';
507
- pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL
508
- }px`;
509
- pageDom.style.backgroundImage = `url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif')`
510
- pageDom.style.backgroundPosition = 'center'
511
- pageDom.style.backgroundRepeat = 'no-repeat'
512
- pageDom.style.backgroundColor = '#FFF'
513
- page.dom = pageDom;
514
- this.contentView.appendChild(pageDom);
515
- },
516
- prev () {
517
- this.currentPage--
518
- if (this.currentPage < 0) {
519
- this.currentPage = 0
520
- if(!this.isPC) {
521
- this.$toast({
522
- message:'当前已经是第一段了',
523
- duration:2000,
524
- })
525
- return
526
- }
527
- }
528
- if(this.preViewType == 'pdf') {
529
- this.scrollToUplaodePage(this.currentPage)
530
- } else {
531
- this.scrollToExcalTop(this.currentPage)
532
- }
533
- // this.getpdfResloutePage(this.cachePdf[this.currentPage - 1])
534
- },
535
- next () {
536
- this.currentPage++
537
- if (this.currentPage >= this.tagIds.length) {
538
- this.currentPage = this.tagIds.length - 1
539
- if(!this.isPC) {
540
- this.$toast({
541
- message:'当前已经是最后一段了',
542
- duration:2000,
543
- })
544
- return
545
- }
546
- }
547
- if(this.preViewType == 'pdf') {
548
- this.scrollToUplaodePage(this.currentPage)
549
- } else {
550
- this.scrollToExcalTop(this.currentPage)
551
- }
552
- },
553
- currentChange (value) {
554
- this.currentPage = value - 1
555
- if(this.preViewType == 'pdf') {
556
- this.scrollToUplaodePage(this.currentPage)
557
- } else {
558
- this.scrollToExcalTop(this.currentPage)
559
- }
560
- },
561
- scrollToUplaodePage (currentPage) {
562
- this.changetoolbar = true
563
- if(this.preViewType !== 'pdf') {
564
- return
565
- }
566
- let pdfResloute = this.cachePdf[currentPage]
567
- this.identifyTextPostion.extractInfo = pdfResloute.extractInfo
568
- this.identifyTextPostion.left = pdfResloute.extractInfo.location[0]
569
- this.identifyTextPostion.top = pdfResloute.extractInfo.location[1]
570
- this.identifyTextPostion.width = pdfResloute.extractInfo.location[2]
571
- this.identifyTextPostion.height = pdfResloute.extractInfo.location[3]
572
- this.identifyTextPostion.page = pdfResloute.page
573
- this.identifyTextPostion.pageHeight = pdfResloute.pageHeight
574
- this.identifyTextPostion.pageWidth = pdfResloute.pageWidth
575
- // 在当前段落在最后一页pdf时,根据计算的高度并不能触发滚动,在此执行重新渲染方法,非次情况会执行两次,待优化
576
- this.$nextTick(() => {
577
- this.renderHighlights()
578
- })
579
- if(this.transformSalce !== null) {
580
- this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce) + this.identifyTextPostion.top}`
581
- } else {
582
- this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.identifyTextPostion.top}`
583
- }
584
- },
585
- scrollToExcalTop(currentPage) {
586
- for (let index = 0; index < this.allTr.length; index++) {
587
- if(index == currentPage) {
588
- Array.from(this.allTr[index].children).forEach(item =>{
589
- item.style.background = 'rgba(255, 136, 0, 0.6)'
590
- item.classList.add('animation')
591
- setTimeout(() =>{
592
- item.classList.remove('animation')
593
- }, 4000)
594
- })
595
- // getBoundingClientRect().top 当前元素距离屏幕顶部的高度 + 弹窗header 高度
596
- if(!this.isPC) {
597
- let top = this.allTr[index].getBoundingClientRect().top - this.$refs.pdfView.getBoundingClientRect().top
598
- this.$refs.pdfView.scrollTop = top
599
- } else {
600
- let top = this.allTr[index].getBoundingClientRect().top
601
- this.$refs.pdfView.scrollTop = top - 50
602
- }
603
- } else {
604
- Array.from(this.allTr[index].children).forEach(item =>{
605
- item.style.background = 'rgba(54, 106, 255, 0.6)'
606
- item.classList.remove('animation')
607
- })
608
- }
609
- }
610
- },
611
- // pdf是否需要重新渲染高亮位置
612
- renderHighlights () {
613
- let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
614
- console.log(lineHeightDom, this.currentPage, 'this.currentPage');
615
- if (lineHeightDom) {
616
- lineHeightDom.forEach((d) => {
617
- for (let i = 0; i < d.children.length; i++) {
618
- if (d.getAttribute('react-count') == this.currentPage) {
619
- d.children[i].style.backgroundColor = 'rgba(255, 136, 0, 0.3)'
620
- d.children[i].classList.add('animation')
621
- setTimeout(() =>{
622
- d.children[i].classList.remove('animation')
623
- }, 4000)
624
- } else {
625
- d.children[i].style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
626
- d.children[i].classList.remove('animation')
627
- }
628
- }
629
- })
630
- }
631
- },
632
- displayHiglight (pageIndex) {
633
- let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
634
- if (lineHeightDom) {
635
- lineHeightDom.forEach((d) => {
636
- if (d.getAttribute('page-index') == pageIndex) {
637
- d.style.display = 'none'
638
- }
639
- })
640
- }
641
- },
642
- // 前端暂时缓存多页
643
- autoLoadMore (pageIndex) {
644
- let pdfResloute = this.cachePdf.find(cache => {
645
- return cache.page == pageIndex
646
- })
647
- if (pdfResloute) {
648
- this.getpdfResloutePage(pdfResloute)
649
- } else {
650
- this.loadPdfData(pageIndex)
651
- }
652
- },
653
- setPageAllLine (arr) {
654
- this.currentPageAllLine = []
655
- arr.forEach((item, index) => {
656
- let i = this.currentPageAllLine.findIndex(l => { return l.page && l.page == item.page })
657
- if (i != -1) {
658
- // this.currentPageAllLine[i].allLines.lines.push(item.extractInfo.lines)
659
- this.currentPageAllLine[i].allLines.push({
660
- pageCount: index,
661
- lines: item.extractInfo.lines
662
- })
663
- } else {
664
- this.currentPageAllLine.push({
665
- page: item.page,
666
- allLines: [{
667
- pageCount: index,
668
- lines: item.extractInfo.lines
669
- }],
670
- })
671
- }
672
- })
673
- },
674
- openTouch() {
675
- // this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
676
- let that = this;
677
- this.$nextTick(() => {
678
- // setInterval(() => {
679
- // this.scale = this.scale + 0.1
680
- // that.pages.forEach((item, index) =>{
681
- // if(item.dom) {
682
- // item.dom.children.forEach( childDom =>{
683
- // if(childDom.getAttribute('react-count')) {
684
- // childDom.style.transform = "scale(" + this.scale + ")";
685
- // childDom.style.transformOrigin = "0px 0px 0px";
686
- // } else {
687
- // item.dom = null
688
- // this.startRenderPages(item.pdfPage, null, index)
689
- // }
690
- // } )
691
- // }
692
- // })
693
- // }, 100);
694
- // 获取放大或缩小的区域DOM
695
- let matrix_box = this.contentView
696
- matrix_box.addEventListener("touchstart", function (event) {
697
- this.isTouchMoved = true
698
- let touches = event.touches;
699
- let events = touches[0];
700
- let events2 = touches[1];
701
-
702
- // event.preventDefault();
703
-
704
- // 第一个触摸点的坐标
705
- that.displacement.pageX = events.pageX;
706
- that.displacement.pageY = events.pageY;
707
-
708
- that.displacement.moveable = true;
709
-
710
- if (events2) {
711
- that.displacement.pageX2 = events2.pageX;
712
- that.displacement.pageY2 = events2.pageY;
713
- }
714
-
715
- that.displacement.originScale = this.scale || 1;
716
- // console.log(that.displacement);
717
- });
718
- document.addEventListener("touchmove", function (event) {
719
- if (!that.displacement.moveable) {
720
- return;
721
- }
722
- // event.preventDefault();
723
- let touches = event.touches;
724
- let events = touches[0];
725
- let events2 = touches[1];
726
- // 双指移动
727
- if (events2) {
728
- // 第2个指头坐标在touchmove时候获取
729
- if (!that.displacement.pageX2) {
730
- that.displacement.pageX2 = events2.pageX;
731
- }
732
- if (!that.displacement.pageY2) {
733
- that.displacement.pageY2 = events2.pageY;
734
- }
735
- // 双指缩放比例计算
736
- let zoom = that.getDistance({
737
- x: events.pageX,
738
- y: events.pageY
739
- },
740
- {
741
- x: events2.pageX,
742
- y: events2.pageY
743
- }
744
- ) / that.getDistance(
745
- {
746
- x: that.displacement.pageX,
747
- y: that.displacement.pageY
748
- },
749
- {
750
- x: that.displacement.pageX2,
751
- y: that.displacement.pageY2
752
- }
753
- );
754
- // 应用在元素上的缩放比例
755
- let newScale = that.displacement.originScale * zoom;
756
- console.log(zoom, newScale , this.scale, 'newScale');
757
- // 最大缩放比例限制
758
- if (newScale > 2) {
759
- newScale = 2;
760
- }
761
- // 最大缩放比例限制
762
- if(newScale < 1) {
763
- newScale = 1;
764
- }
765
- // 记住使用的缩放值
766
- that.displacement.scale = newScale;
767
- // console.log(newScale);
768
- matrix_box.style.transform = "scale(" + newScale + ")";
769
- // 设置旋转元素的基点位置
770
- matrix_box.style.transformOrigin = "0px 0px 0px";
771
- }
772
- },{ passive: false });
773
- document.addEventListener('touchend',function() {
774
- that.isTouchMoved = false
775
- },{ passive: false })
776
- });
777
- },
778
- getDistance(start, stop) {
779
- // Math.hypot()计算参数的平方根
780
- return Math.hypot(stop.x - start.x, stop.y - start.y);
781
- },
782
- setupCanvas(canvas, width, height) {
783
- const dpr = 1;
784
- // const rect = canvas.getBoundingClientRect();
785
- canvas.width = width
786
- canvas.height = height
787
- const ctx = canvas.getContext('2d');
788
- console.log(canvas.width, canvas.height, dpr, this.scale);
789
- ctx?.scale(dpr, dpr );
790
- return ctx;
791
- },
792
- changeScale(value) {
793
- if(value == 'zoom') {
794
- this.handScale = 'auto'
795
- this.transformSalce = (this.transformSalce + 0.2).toFixed(1)
796
- } else if(value == 'reduce') {
797
- if((this.transformSalce - 0.2).toFixed(1) <= 0) {
798
- return
799
- }
800
- this.handScale = 'auto'
801
- this.transformSalce = (this.transformSalce - 0.2).toFixed(1)
802
- } else if(value == 'auto') {
803
- this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
804
- } else if(value == 'reality') {
805
- this.transformSalce = 0.5
806
- } else {
807
- this.transformSalce = (value / 2).toFixed(1)
808
- }
809
- this.transformSalce = Number(this.transformSalce)
810
- this.contentView.style.transform = 'scale(' + this.transformSalce + ')';
811
- // this.getpdfResloutePage(this.cachePdf[0])
812
- },
813
- },
814
- computed:{
815
- perviewUrl() {
816
- return '/web/viewer.html?file=' + '/pdflist/pdf4split-1.pdf'
817
- }
818
- },
819
- watch:{
820
- tagIds: {
821
- handler(value) {
822
- if(value && value.length) {
823
- // 在 pdf_view 下创建 所有canvs的容器
824
- this.contentView = document.createElement('div')
825
- this.contentView.style.transformOrigin = '0px 0px 0px'
826
- this.$http.get('/knowledge-api/knowledge/knowledge-part-location-info/list?ids=' + value.join(',')).then(res =>{
827
- // 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}
828
- // 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}
829
- // 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}
830
- // 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}
831
- // 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}
832
- // if(value.length === 1) {
833
- // this.$refs.pdfView.style.height = 'calc(100% - 50px)'
834
- // }
835
- if (res.data.code == 0) {
836
- // tagIds 会按照gpt识别的生成有序的数组,前端直接按照下标的顺序取就可以了
837
- // 缓存拿到的所有数据
838
- this.cachePdf = res.data.data
839
- let publicPageFileUrl = res.data.data[0].publicPageFileUrl
840
- this.currentPage = 0
841
- // console.log(publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')));
842
- if (publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')) === '.pdf') {
843
- this.preViewType = 'pdf'
844
- this.setPageAllLine(this.cachePdf)
845
- this.getpdfResloutePage(res.data.data[0])
846
- } else {
847
- this.preViewType = 'excal'
848
- this.$http.post(
849
- '/knowledge-api/temporary-certificate/or-origin?expired=30',
850
- publicPageFileUrl,
851
- {
852
- headers: {
853
- "Content-Type": "application/json",
854
- },
855
- }).then(res => {
856
- // 使用原声请求方式 axios会带有不需要的请求头
857
- let xhr = new XMLHttpRequest();
858
- xhr.open('GET', res.data || res.bodyText , true);
859
- // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
860
- xhr.onload = ({ currentTarget }) => {
861
- // 请求完成
862
- if (currentTarget.status === 200) { // 返回200
863
- this.contentView.innerHTML = currentTarget.response
864
- this.contentView.style.padding = '10px'
865
- // this.contentView.style.position = 'relative'
866
- this.$refs.pdfView.style.backgroundColor = '#FFFFFF'
867
- this.$refs.pdfView.appendChild(this.contentView)
868
- let allTr = Array.from(this.$refs.pdfView.getElementsByTagName('tr'))
869
- this.allTr = []
870
- for (let index = 0; index < allTr.length; index++) {
871
- if(value.includes(allTr[index].getAttribute('tag-id'))) {
872
- this.allTr.push(allTr[index])
873
- }
874
- }
875
- this.currentChange(1)
876
-
877
- }
878
- }
879
- xhr.send();
880
- })
881
- }
882
- } else {
883
- let div = document.createElement('div')
884
- div.innerText = '文件加载异常'
885
- this.contentView.appendChild(div)
886
- this.$refs.pdfView.appendChild(this.contentView)
887
- }
888
- })
889
- }
890
- },
891
- deep:true,
892
- immediate:true
893
- }
894
- },
895
- mounted () {
896
- if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
897
- this.isPC = false
898
- } else {
899
- this.isPC = true
900
- }
901
- }
902
- }
903
- </script>
904
-
905
- <style lang="less" scoped>
906
- .pdf_view {
907
- width: 100%;
908
- height: calc(100% - 110px);
909
- overflow: auto;
910
- background-color: #f5f7fb;
911
- margin-bottom: 60px;
912
- box-sizing: border-box;
913
- // position: relative;
914
- // > div {
915
- // width: 100%;
916
- // height: 100%;
917
- // overflow: hidden;
918
- // overflow-y: auto;
919
- // position: relative;
920
- // }
921
- > iframe {
922
- width: 100%;
923
- height: 100%;
924
- }
925
- a:link {
926
- color: none;
927
- }
928
- a:visited {
929
- color: none;
930
- }
931
- a:hover {
932
- color: none;
933
- }
934
- a:active {
935
- color: none;
936
- }
937
- .btn_footer {
938
- width: 100%;
939
- height: 60px;
940
- display: flex;
941
- align-items: center;
942
- justify-content: space-around;
943
- position: absolute;
944
- bottom: 0px;
945
- left: 0;
946
- z-index: 999;
947
- background: #ffffff;
948
- .prev, .next {
949
- width: 35%;
950
- height: 40px;
951
- display: flex;
952
- align-items: center;
953
- justify-content: center;
954
- border-radius: 50px;
955
- cursor: pointer;
956
- }
957
- .prev {
958
- background: #F2F5FA;
959
- color: #000;
960
- }
961
- .next {
962
- background: #366aff;
963
- color: #ffffff;
964
- }
965
- }
966
- #pagination {
967
- .total-class {
968
- margin-right: 13px;
969
- font-weight: 400;
970
- }
971
-
972
- position: absolute;
973
- bottom: 0px;
974
- right: 0;
975
- width: 100%;
976
- display: flex;
977
- align-items: center;
978
- justify-content: center;
979
- height: 50px;
980
- background-color: white;
981
- box-shadow: 0px 0px 18px 0px rgba(29, 55, 129, 0.07);
982
- border-radius: 5px;
983
- z-index: 1000;
984
-
985
- /deep/.el-pagination {
986
- margin-right: 110px;
987
- }
988
-
989
- /deep/.el-pager {
990
- background: #EDF0F6;
991
- border-radius: 15px;
992
- }
993
-
994
- /deep/.el-pagination.is-background .btn-next {
995
- width: 30px;
996
- height: 30px;
997
- background: #EDF0F6;
998
- border-radius: 50%;
999
- }
1000
-
1001
- /deep/.el-pagination .btn-next {
1002
- width: 30px;
1003
- height: 30px;
1004
- background: #EDF0F6;
1005
- border-radius: 50%;
1006
- padding-left: 0;
1007
- margin-left: 5px;
1008
- }
1009
-
1010
- /deep/.el-pagination .btn-prev {
1011
- width: 30px;
1012
- height: 30px;
1013
- background: #EDF0F6;
1014
- border-radius: 50%;
1015
- padding-right: 0;
1016
- margin-right: 5px;
1017
- }
1018
-
1019
- /deep/.el-pagination button {
1020
- padding: 0;
1021
- min-width: 30px;
1022
- }
1023
-
1024
- /deep/.el-pager li {
1025
- background: #EDF0F6;
1026
- height: 30px;
1027
- min-width: 30px;
1028
- line-height: 30px;
1029
- font-size: 12px;
1030
- color: #717b90;
1031
- }
1032
-
1033
- /deep/.el-pager li:first-child {
1034
- border-bottom-left-radius: 15px !important;
1035
- border-top-left-radius: 15px !important;
1036
- }
1037
-
1038
- /deep/.el-pager li:last-child {
1039
- border-top-right-radius: 15px !important;
1040
- border-bottom-right-radius: 15px !important;
1041
- }
1042
-
1043
- /deep/.el-pager li.active {
1044
- width: 30px;
1045
- height: 30px;
1046
- min-width: 30px;
1047
- background: #366AFF;
1048
- border: 3px solid #A1B9FF;
1049
- border-radius: 50%;
1050
- line-height: 24px;
1051
- color: white;
1052
- }
1053
-
1054
- /deep/.el-pagination.is-background .el-pager li:not(.disabled).active {
1055
- background: #366AFF;
1056
- }
1057
- }
1058
- .change_scale {
1059
- width: 100%;
1060
- height: 50px;
1061
- position: absolute;
1062
- top: 50px;
1063
- left: 0;
1064
- background: #ffffff;
1065
- display: flex;
1066
- align-items: center;
1067
- padding: 0 10px;
1068
- box-sizing: border-box;
1069
- section {
1070
- cursor: pointer;
1071
- width: 30px;
1072
- height: 30px;
1073
- margin-right: 5px;
1074
- border-radius: 5px;
1075
- display: flex;
1076
- align-items: center;
1077
- justify-content: center;
1078
- i {
1079
- font-weight: 900;
1080
- }
1081
- }
1082
- section:hover {
1083
- background: rgba(221, 222, 223, 1);
1084
- }
1085
- }
1086
- }
1087
-
1088
- </style>
1089
- <style lang="less">
1090
- .animation {
1091
- animation-name: highlight;
1092
- animation-duration: 4s;
1093
- }
1094
- @keyframes highlight {
1095
- 0% {
1096
- background:rgba(255, 136, 0, 0.3);
1097
- }
1098
- 25% {
1099
- background:rgba(255, 136, 0, 0.6);
1100
- }
1101
- 50% {
1102
- background:rgba(255, 136, 0, 0.3);
1103
- }
1104
- 75% {
1105
- background:rgba(255, 136, 0, 0.6);
1106
- }
1107
- 100% {
1108
- background:rgba(255, 136, 0, 0.3);
1109
- }
1110
- }
1
+ <template>
2
+ <div
3
+ class="pdf_view"
4
+ ref="pdfView"
5
+ @scroll="pdfScroll"
6
+ :style="{
7
+ marginTop: isPC ? '50px' : ''
8
+ }">
9
+ <div class="change_scale" v-if="isPC">
10
+ <section @click="changeScale('reduce')">
11
+ <i class="el-icon-minus"></i>
12
+ </section>
13
+ <el-divider direction="vertical"></el-divider>
14
+ <section @click="changeScale('zoom')">
15
+ <i class="el-icon-plus"></i>
16
+ </section>
17
+ <el-select size="small" v-model="handScale" @change="changeScale" placeholder="请选择">
18
+ <el-option
19
+ v-for="item in scaleList"
20
+ :key="item.value"
21
+ :label="item.label"
22
+ :value="item.value">
23
+ </el-option>
24
+ </el-select>
25
+ </div>
26
+ <div class="btn_footer" v-if="tagIds.length > 1 && !isPC">
27
+ <div class="prev" @click="prev">上一段</div>
28
+ <div class="next" @click="next">下一段</div>
29
+ </div>
30
+ <div id="pagination" v-if="tagIds.length > 1 && isPC">
31
+ <el-pagination :current-page="currentPage + 1" @current-change="currentChange" @prev-click="prev"
32
+ @next-click="next" layout="slot, prev, pager, next" :page-size="1" :total="tagIds.length">
33
+ <span class="total-class">答案由{{ tagIds.length }}段内容生成</span>
34
+ </el-pagination>
35
+ </div>
36
+ </div>
37
+ </template>
38
+
39
+ <script>
40
+ import _ from 'lodash'
41
+ // import * as pdfjsLib from 'pdfjs-dist'
42
+ // pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs-dist/build/pdf.worker';
43
+ // import { TextLayerBuilder } from "pdfjs-dist/web/pdf_viewer";
44
+ // EventBus pdf_viewer 支持绑定自定义事件,一版不做
45
+ // import 'pdfjs-dist/web/pdf_viewer.css'
46
+ /* eslint-disable */
47
+ const pdfjsLib = window['pdfjsLib']
48
+ if(pdfjsLib) {
49
+ pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
50
+ // 'pdfjs-dist/build/pdf.worker';
51
+ }
52
+ const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
53
+ // import { zoomElement } from '../assets/js/hammer'
54
+ export default {
55
+ name: 'pdfView',
56
+ props:['tagIds','isMessageRecord'],
57
+ data() {
58
+ return {
59
+ url: '',
60
+ pages: [],
61
+ pageLoadStatus: {
62
+ WAIT: 0,
63
+ LOADED: 1,
64
+ },
65
+ scale: 1,
66
+ rotation: 0,
67
+ pageSize: {},
68
+ PAGE_INTVERVAL: 15,
69
+ SLICE_COUNT: 5,
70
+ contentView: null,
71
+ fisrtLoad: true,
72
+ TextLayerBuilder: null,
73
+ totalPageCount: 0,
74
+ identifyTextPostion: {
75
+ top: 0,
76
+ left: 0,
77
+ width: 100,
78
+ height: 0,
79
+ page: 1,
80
+ pageHeight: 0,
81
+ pageWidth: 0,
82
+ extractInfo: {},
83
+ currentPageAllLine: []
84
+ },
85
+ currentPageAllLine: [],
86
+ pdfUrl: '',
87
+ cachePdf: [],
88
+ newViewer: null,
89
+ currentPage: 0,
90
+ changetoolbar: false,
91
+ allTr:[],
92
+ preViewType: 'pdf',
93
+ displacement:{
94
+ pageX: 0,
95
+ pageY: 0,
96
+ moveable: false,
97
+ pageX2: 0,
98
+ pageY2: 0,
99
+ originScale: 1,
100
+ },
101
+ isTouchMoved: false,
102
+ transformSalce: null,
103
+ isPC: false,
104
+ handScale: 'auto',
105
+ scaleList:[
106
+ {
107
+ label:'自动缩放',
108
+ value:'auto'
109
+ },
110
+ {
111
+ label:'实际比例',
112
+ value:'reality'
113
+ },
114
+ {
115
+ label:'100%',
116
+ value: 1
117
+ },
118
+ {
119
+ label:'120%',
120
+ value: 1.2
121
+ },
122
+ {
123
+ label:'150%',
124
+ value: 1.5
125
+ },
126
+ {
127
+ label:'170%',
128
+ value: 1.7
129
+ }
130
+ ,
131
+ {
132
+ label:'200%',
133
+ value: 2
134
+ }
135
+ ],
136
+ scrollTop:0,
137
+ scrollLeft:0
138
+ }
139
+ },
140
+ methods: {
141
+ getpdfResloutePage (pdfResloute) {
142
+ // 根据当前页面宽度设置缩放比例
143
+ // this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
144
+ // console.log(this.scale,'this.scale');
145
+ if(this.isMessageRecord) {
146
+ this.scale = Math.round(this.$refs.pdfView.clientWidth / pdfResloute.pageWidth * 100) / 100
147
+ } else {
148
+ this.scale = 2
149
+ }
150
+ // 从后端获取到当前分片后所有的pdf页码,初始化数组,数组下{} 对应每页pdf文件
151
+ this.pdfUrl = pdfResloute.publicPageFileUrl.substring(0, pdfResloute.publicPageFileUrl.lastIndexOf('/') + 1)
152
+ this.initPages(pdfResloute.total)
153
+ // 定位功能,加载对应页码位置
154
+ this.loadPdfData(pdfResloute.page)
155
+ },
156
+ async loadPdfData (loadPage) {
157
+ if(this.pages[loadPage - 1] && this.pages[loadPage - 1].dom && this.pages[loadPage - 1].dom.children.length > 0) {
158
+ return
159
+ }
160
+ // pdfjsLib.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/legacy/build/pdf.worker.entry.js");
161
+ // 拿到第一个分片
162
+ const { startPage, url } = await this.fetchPdfFragment(loadPage);
163
+ let loadingTask = pdfjsLib.getDocument(url)
164
+ loadingTask.promise.then((pdfDoc) => {
165
+ // 将已经下载的分片保存到 pages 数组中
166
+ for (let i = 0; i < pdfDoc.numPages; i += 1) {
167
+ const pageIndex = startPage + i;
168
+ const page = this.pages[pageIndex - 1];
169
+ // 不在缓存列表内,重新获取本页pdf
170
+ if (page.loadStatus !== this.pageLoadStatus.LOADED) {
171
+ pdfDoc.getPage(i + 1).then((pdfPage) => {
172
+ page.pdfPage = pdfPage;
173
+ page.loadStatus = this.pageLoadStatus.LOADED;
174
+ // 通知可以进行渲染了
175
+ this.startRenderPages(pdfPage, page, pageIndex)
176
+ });
177
+ } else {
178
+ if (this.changetoolbar) {
179
+ this.$nextTick(() => {
180
+ this.renderHighlights()
181
+ })
182
+ this.changetoolbar = false
183
+ }
184
+ }
185
+ }
186
+ });
187
+ },
188
+ initPages (totalPage) {
189
+ // const pages = [];
190
+ this.totalPageCount = totalPage
191
+ for (let i = 0; i < totalPage; i += 1) {
192
+ this.pages.push({
193
+ pageNo: i + 1,
194
+ loadStatus: this.pageLoadStatus.WAIT,
195
+ pdfPage: null,
196
+ dom: null
197
+ });
198
+ }
199
+ },
200
+ async fetchPdfFragment (pageIndex) {
201
+ // 置换加签后的文件地址。
202
+ let obj = {}
203
+ await this.$http.post(
204
+ '/knowledge-api/temporary-certificate/or-origin?expired=30',
205
+ this.pdfUrl + pageIndex + '.pdf',
206
+ {
207
+ headers: {
208
+ "Content-Type": "application/json",
209
+ },
210
+ }).then(async res => {
211
+ if(res.bodyText) {
212
+ // 最后返回一个 包含这4个参数的对象
213
+ obj = await {
214
+ "startPage": pageIndex, // 分片的开始页码
215
+ "endPage": pageIndex + 5, // 分片结束页码
216
+ "totalPage": this.totalPageCount, // pdf 总页数
217
+ "url": res.bodyText // 分片内容下载地址
218
+ }
219
+ }
220
+ if (res.data) {
221
+ // 最后返回一个 包含这4个参数的对象
222
+ obj = await {
223
+ "startPage": pageIndex, // 分片的开始页码
224
+ "endPage": pageIndex + 5, // 分片结束页码
225
+ "totalPage": this.totalPageCount, // pdf 总页数
226
+ "url": res.data // 分片内容下载地址
227
+ }
228
+ }
229
+ })
230
+ return obj
231
+ },
232
+ startRenderPages (pdfPage, page, pageIndex) {
233
+ const viewport = pdfPage.getViewport({
234
+ scale: this.scale, // 缩放的比例
235
+ rotation: this.rotation, // 旋转的角度
236
+ });
237
+ // 记录pdf页面高度
238
+ const pageSize = {
239
+ width: viewport.width,
240
+ height: viewport.height,
241
+ }
242
+ this.pageSize = pageSize
243
+ // 创建内容绘制区,并设置大小
244
+ if(this.$refs.pdfView.clientWidth / this.pageSize.width >= 1 || this.isMessageRecord) {
245
+ this.contentView.style.width = `${pageSize.width }px`;
246
+ this.contentView.style.height = `${(this.totalPageCount * (pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
247
+ } else {
248
+ this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
249
+ this.contentView.style.width = `${pageSize.width * this.transformSalce}px`;
250
+ this.contentView.style.height = `${(this.totalPageCount * (pageSize.height * (this.transformSalce) + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
251
+ }
252
+ this.contentView.style.margin = '0 auto 0'
253
+ console.log(this.transformSalce);
254
+ this.contentView.style.position = 'relative'
255
+ this.contentView.style.paddingBottom = '60px'
256
+ // contentView.style.overflowY = 'auto'
257
+ this.$refs.pdfView.appendChild(this.contentView);
258
+ this.renderPages(pageIndex)
259
+ },
260
+ renderPageContent (page, pageIndex) {
261
+ const { pdfPage, pageNo, dom } = page;
262
+ // dom 元素已存在,无须重新渲染,直接返回
263
+ console.log(dom, 'dom');
264
+ if (dom && dom.children.length != 0) {
265
+ return;
266
+ }
267
+ const viewport = pdfPage.getViewport({
268
+ scale: this.scale,
269
+ rotation: this.rotation,
270
+ });
271
+ // 创建新的canvas
272
+ const canvas = document.createElement('canvas');
273
+ const context = canvas.getContext('2d');
274
+ // canvas.getContext('2d');
275
+ canvas.height = this.pageSize.height;
276
+ canvas.width = this.pageSize.width;
277
+ // 创建渲染的dom
278
+ const pageDom = document.createElement('div');
279
+ pageDom.style.position = 'absolute';
280
+ pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL}px`;
281
+ pageDom.style.width = `${this.pageSize.width}px`;
282
+ pageDom.style.height = `${this.pageSize.height}px`;
283
+ pageDom.appendChild(canvas);
284
+ // 渲染内容
285
+ let renderContext = {
286
+ canvasContext: context,
287
+ viewport: viewport,
288
+ }
289
+ pdfPage.render(renderContext).promise.then(() => {
290
+ console.log(pdfPage.getTextContent(), 'getTextContent');
291
+ return pdfPage.getTextContent()
292
+ }).then((textContent) => {
293
+ const textLayerDiv = document.createElement('div');
294
+ textLayerDiv.setAttribute('class', 'textLayer');
295
+ // 将文本图层div添加至每页pdf的div中
296
+ // 创建新的TextLayerBuilder实例
297
+ let textLayer = new TextLayerBuilder({
298
+ textLayerDiv: textLayerDiv,
299
+ pageIndex: pdfPage._pageIndex,
300
+ viewport: viewport,
301
+ });
302
+ let findPage = this.currentPageAllLine.find(l => { return l.page == pageIndex })
303
+ let rectdomTop = 0
304
+ if (findPage) {
305
+ let AllLines = findPage.allLines
306
+ // setTimeout(() => {
307
+ if (AllLines.length > 0) {
308
+ for (let j = 0; j < AllLines.length; j++) {
309
+ let lines = AllLines[j].lines
310
+ let rectdom = document.createElement('div')
311
+ rectdom.setAttribute('react-count', AllLines[j].pageCount);
312
+ rectdom.style.position = 'absolute';
313
+ rectdom.style.top = 0
314
+ rectdom.style.left = 0
315
+ rectdom.classList.add('rectdom')
316
+ for (let index = 0; index < lines.length; index++) {
317
+ if (!/^\s+$/g.test(lines[index].content)) {
318
+ let postionArr = lines[index].location
319
+ let div = document.createElement('div')
320
+ div.style.position = 'absolute';
321
+ div.style.left = postionArr[0] * this.scale + 'px',
322
+ // 后端返回的坐标有基线对齐的问题,top 值是后端算好(基线top - 文字高度),在此加上文字高度的 1/9 (大致比例)为实际展示出文字的top值
323
+ div.style.top = (postionArr[1] + postionArr[3] / 9) * this.scale + 'px'
324
+ div.style.height = postionArr[3] * this.scale + 'px';
325
+ div.style.width = postionArr[2] * this.scale + 'px'
326
+ div.style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
327
+ div.classList.add('lineHeight')
328
+ rectdom.appendChild(div)
329
+ if(index == 0 && j == 0) {
330
+ rectdomTop = postionArr[1]
331
+ if(this.isPC) {
332
+ rectdomTop = rectdomTop + 50
333
+ }
334
+ }
335
+ }
336
+ }
337
+ if (rectdom.children.length > 0) {
338
+ pageDom.appendChild(rectdom)
339
+ }
340
+ }
341
+ }
342
+ }
343
+ textLayer.setTextContent(textContent);
344
+ textLayer.render()
345
+ pageDom.appendChild(textLayer.textLayerDiv);
346
+ page.dom = pageDom;
347
+ this.contentView.appendChild(pageDom);
348
+ if(this.transformSalce !== null) {
349
+ this.contentView.style.transform = `scale(${this.transformSalce}, ${this.transformSalce})`
350
+ }
351
+ if (this.changetoolbar) {
352
+ setTimeout(() => {
353
+ this.renderHighlights()
354
+ this.changetoolbar = false
355
+ }, 100)
356
+ }
357
+ if (this.fisrtLoad) {
358
+ setTimeout(() => {
359
+ let pageoffsetHeight = 0
360
+ if(this.transformSalce !== null) {
361
+ pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce
362
+ } else {
363
+ pageoffsetHeight = (this.pageSize.height + this.PAGE_INTVERVAL)
364
+ }
365
+ if (this.$refs.pdfView.clientHeight - pageoffsetHeight > 0) {
366
+ const height = this.$refs.pdfView.clientHeight;
367
+ let startNum = 0
368
+ let endNum = 0
369
+ if(this.transformSalce !== null) {
370
+ startNum = Math.ceil(this.$refs.pdfView.scrollTop / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
371
+ endNum = startNum + Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce))
372
+ console.log( Math.ceil(height / ((this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce)),this.pageSize.height , this.PAGE_INTVERVAL, height, this.transformSalce,'startNum');
373
+
374
+ } else {
375
+ startNum = Math.ceil(this.$refs.pdfView.scrollTop / (this.pageSize.height + this.PAGE_INTVERVAL))
376
+ endNum = startNum + Math.ceil(height / (this.pageSize.height + this.PAGE_INTVERVAL))
377
+
378
+ }
379
+ for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
380
+ if(pageIndex > 0 && pageIndex <= this.pages.length) {
381
+ this.loadPdfData(pageIndex)
382
+ }
383
+ }
384
+ }
385
+
386
+ if (this.$refs.pdfView.scrollTop == Math.floor((pageNo - 1) * pageoffsetHeight)) {
387
+ this.fisrtLoad = false
388
+ } else {
389
+ this.$refs.pdfView.scrollTop = `${((pageNo - 1) * pageoffsetHeight) + rectdomTop - this.PAGE_INTVERVAL}`
390
+ this.fisrtLoad = false
391
+ }
392
+ this.renderHighlights()
393
+ // zoomElement(this.contentView)
394
+ }, 100)
395
+ }
396
+ })
397
+ },
398
+ // 监听容器的滚动事件,触发 scrollPdf 方法
399
+ // 这里加了防抖保证不会一次产生过多请求
400
+ debounceScrollPdf: _.debounce(function (e, that) {
401
+ if (this.fisrtLoad) {
402
+ this.fisrtLoad = false
403
+ return
404
+ }
405
+ const scrollTop = e.target.scrollTop;
406
+ const height = e.target.clientHeight;
407
+ let startNum = 0
408
+ let endNum = 0
409
+ if(this.transformSalce !== null) {
410
+ startNum = Math.ceil(scrollTop / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
411
+ endNum = startNum + Math.ceil(height / ((that.pageSize.height + that.PAGE_INTVERVAL) * this.transformSalce))
412
+ } else {
413
+ startNum = Math.ceil(scrollTop / (that.pageSize.height + that.PAGE_INTVERVAL))
414
+ endNum = startNum + Math.ceil(height / (that.pageSize.height + that.PAGE_INTVERVAL))
415
+ }
416
+ for (let pageIndex = startNum; pageIndex <= endNum; pageIndex++) {
417
+ console.log(pageIndex,pageIndex >= 0 && pageIndex <= that.pages.length, 'pageIndexpageIndexpageIndex');
418
+ if(pageIndex > 0 && pageIndex <= that.pages.length) {
419
+ that.loadPdfData(pageIndex)
420
+ }
421
+ }
422
+ console.log('=======');
423
+ }, 200),
424
+ directScrolling (e, that) {
425
+ if (this.fisrtLoad) {
426
+ this.fisrtLoad = false
427
+ return
428
+ }
429
+ const scrollTop = e.target.scrollTop;
430
+ const height = e.target.clientHeight;
431
+ // 根据内容可视区域中心点计算页码, 没有滚动时,指向第一页
432
+ const pageIndex = scrollTop > 0 ?
433
+ Math.ceil((scrollTop + (height / 2)) / (that.pageSize.height + that.PAGE_INTVERVAL)) :
434
+ 1;
435
+ this.loadPdfData(pageIndex)
436
+ },
437
+ pdfScroll (e) {
438
+ if(this.preViewType !== 'pdf' || this.isTouchMoved) {
439
+ return
440
+ }
441
+ if(this.scrollLeft != e.target.scrollLeft) {
442
+ this.scrollLeft = e.target.scrollLeft
443
+ }
444
+ if(this.scrollTop != e.target.scrollTop) {
445
+ this.scrollTop = e.target.scrollTop
446
+ this.debounceScrollPdf(e, this)
447
+ }
448
+ },
449
+ // 分片每次只做一次处理,所以不考虑多片情况
450
+ loadBefore (pageIndex) {
451
+ this.loadPdfData(pageIndex)
452
+ },
453
+ loadAfter (pageIndex) {
454
+ this.loadPdfData(pageIndex)
455
+ },
456
+ // 首先我们获取到需要渲染的范围
457
+ // 根据当前的可视范围内的页码,我们前后只保留 8
458
+ getRenderScope (pageIndex) {
459
+ const pagesToRender = [];
460
+ let i = pageIndex - 1;
461
+ let j = pageIndex + 1;
462
+ // pageIndex - 1 表示当前页码数 对应的下标位置
463
+ pagesToRender.push(this.pages[pageIndex - 1]);
464
+ while (pagesToRender.length < 8 && pagesToRender.length < this.pages.length) {
465
+ if (i > 0) {
466
+ pagesToRender.push(this.pages[i - 1]);
467
+ i -= 1;
468
+ }
469
+ if (pagesToRender.length >= 8) {
470
+ break;
471
+ }
472
+ if (j <= this.pages.length) {
473
+ pagesToRender.push(this.pages[j - 1]);
474
+ j += 1;
475
+ }
476
+ }
477
+ return pagesToRender;
478
+ },
479
+ // 渲染需要展示的页面,不需展示的页码将其清除
480
+ renderPages (pageIndex) {
481
+ const pagesToRender = this.getRenderScope(pageIndex);
482
+ for (const i of this.pages) {
483
+ if (pagesToRender.includes(i)) {
484
+ i.loadStatus === this.pageLoadStatus.LOADED ?
485
+ this.renderPageContent(i, pageIndex) :
486
+ this.renderPageLoading(i);
487
+ } else {
488
+ this.clearPage(i);
489
+ }
490
+ }
491
+ },
492
+ // 清除页面 dom
493
+ clearPage (page) {
494
+ if (page.dom) {
495
+ this.contentView.removeChild(page.dom);
496
+ page.loadStatus = 0
497
+ page.dom = undefined;
498
+ }
499
+ },
500
+ // 页面正在下载时渲染loading视图
501
+ renderPageLoading (page) {
502
+ const { pageNo, dom } = page;
503
+ if (dom && dom.children.length != 0) {
504
+ return;
505
+ }
506
+ const pageDom = document.createElement('div');
507
+ pageDom.style.width = `${this.pageSize.width}px`;
508
+ pageDom.style.height = `${this.pageSize.height}px`;
509
+ pageDom.style.position = 'absolute';
510
+ pageDom.style.top = `${((pageNo - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.PAGE_INTVERVAL
511
+ }px`;
512
+ pageDom.style.backgroundImage = `url('https://guoranopen-zjk.oss-cn-zhangjiakou.aliyuncs.com/cdn-common/images/loading.gif')`
513
+ pageDom.style.backgroundPosition = 'center'
514
+ pageDom.style.backgroundRepeat = 'no-repeat'
515
+ pageDom.style.backgroundColor = '#FFF'
516
+ page.dom = pageDom;
517
+ this.contentView.appendChild(pageDom);
518
+ },
519
+ prev () {
520
+ this.currentPage--
521
+ if (this.currentPage < 0) {
522
+ this.currentPage = 0
523
+ if(!this.isPC) {
524
+ this.$toast({
525
+ message:'当前已经是第一段了',
526
+ duration:2000,
527
+ })
528
+ return
529
+ }
530
+ }
531
+ if(this.preViewType == 'pdf') {
532
+ this.scrollToUplaodePage(this.currentPage)
533
+ } else {
534
+ this.scrollToExcalTop(this.currentPage)
535
+ }
536
+ // this.getpdfResloutePage(this.cachePdf[this.currentPage - 1])
537
+ },
538
+ next () {
539
+ this.currentPage++
540
+ if (this.currentPage >= this.tagIds.length) {
541
+ this.currentPage = this.tagIds.length - 1
542
+ if(!this.isPC) {
543
+ this.$toast({
544
+ message:'当前已经是最后一段了',
545
+ duration:2000,
546
+ })
547
+ return
548
+ }
549
+ }
550
+ if(this.preViewType == 'pdf') {
551
+ this.scrollToUplaodePage(this.currentPage)
552
+ } else {
553
+ this.scrollToExcalTop(this.currentPage)
554
+ }
555
+ },
556
+ currentChange (value) {
557
+ this.currentPage = value - 1
558
+ if(this.preViewType == 'pdf') {
559
+ this.scrollToUplaodePage(this.currentPage)
560
+ } else {
561
+ this.scrollToExcalTop(this.currentPage)
562
+ }
563
+ },
564
+ scrollToUplaodePage (currentPage) {
565
+ this.changetoolbar = true
566
+ if(this.preViewType !== 'pdf') {
567
+ return
568
+ }
569
+ let pdfResloute = this.cachePdf[currentPage]
570
+ this.identifyTextPostion.extractInfo = pdfResloute.extractInfo
571
+ this.identifyTextPostion.left = pdfResloute.extractInfo.location[0]
572
+ this.identifyTextPostion.top = pdfResloute.extractInfo.location[1]
573
+ this.identifyTextPostion.width = pdfResloute.extractInfo.location[2]
574
+ this.identifyTextPostion.height = pdfResloute.extractInfo.location[3]
575
+ this.identifyTextPostion.page = pdfResloute.page
576
+ this.identifyTextPostion.pageHeight = pdfResloute.pageHeight
577
+ this.identifyTextPostion.pageWidth = pdfResloute.pageWidth
578
+ // 在当前段落在最后一页pdf时,根据计算的高度并不能触发滚动,在此执行重新渲染方法,非次情况会执行两次,待优化
579
+ this.$nextTick(() => {
580
+ this.renderHighlights()
581
+ })
582
+ if(this.transformSalce !== null) {
583
+ this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL) * this.transformSalce) + this.identifyTextPostion.top}`
584
+ } else {
585
+ this.$refs.pdfView.scrollTop = `${((pdfResloute.page - 1) * (this.pageSize.height + this.PAGE_INTVERVAL)) + this.identifyTextPostion.top}`
586
+ }
587
+ },
588
+ scrollToExcalTop(currentPage) {
589
+ for (let index = 0; index < this.allTr.length; index++) {
590
+ if(index == currentPage) {
591
+ Array.from(this.allTr[index].children).forEach(item =>{
592
+ item.style.background = 'rgba(255, 136, 0, 0.6)'
593
+ item.classList.add('animation')
594
+ setTimeout(() =>{
595
+ item.classList.remove('animation')
596
+ }, 4000)
597
+ })
598
+ // getBoundingClientRect().top 当前元素距离屏幕顶部的高度 + 弹窗header 高度
599
+ if(!this.isPC) {
600
+ let top = this.allTr[index].getBoundingClientRect().top - this.$refs.pdfView.getBoundingClientRect().top
601
+ this.$refs.pdfView.scrollTop = top
602
+ } else {
603
+ let top = this.allTr[index].getBoundingClientRect().top
604
+ this.$refs.pdfView.scrollTop = top - 50
605
+ }
606
+ } else {
607
+ Array.from(this.allTr[index].children).forEach(item =>{
608
+ item.style.background = 'rgba(54, 106, 255, 0.6)'
609
+ item.classList.remove('animation')
610
+ })
611
+ }
612
+ }
613
+ },
614
+ // pdf是否需要重新渲染高亮位置
615
+ renderHighlights () {
616
+ let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
617
+ console.log(lineHeightDom, this.currentPage, 'this.currentPage');
618
+ if (lineHeightDom) {
619
+ lineHeightDom.forEach((d) => {
620
+ for (let i = 0; i < d.children.length; i++) {
621
+ if (d.getAttribute('react-count') == this.currentPage) {
622
+ d.children[i].style.backgroundColor = 'rgba(255, 136, 0, 0.3)'
623
+ d.children[i].classList.add('animation')
624
+ setTimeout(() =>{
625
+ d.children[i].classList.remove('animation')
626
+ }, 4000)
627
+ } else {
628
+ d.children[i].style.backgroundColor = 'rgba(54, 106, 255, 0.3)'
629
+ d.children[i].classList.remove('animation')
630
+ }
631
+ }
632
+ })
633
+ }
634
+ },
635
+ displayHiglight (pageIndex) {
636
+ let lineHeightDom = Array.from(document.getElementsByClassName('rectdom'))
637
+ if (lineHeightDom) {
638
+ lineHeightDom.forEach((d) => {
639
+ if (d.getAttribute('page-index') == pageIndex) {
640
+ d.style.display = 'none'
641
+ }
642
+ })
643
+ }
644
+ },
645
+ // 前端暂时缓存多页
646
+ autoLoadMore (pageIndex) {
647
+ let pdfResloute = this.cachePdf.find(cache => {
648
+ return cache.page == pageIndex
649
+ })
650
+ if (pdfResloute) {
651
+ this.getpdfResloutePage(pdfResloute)
652
+ } else {
653
+ this.loadPdfData(pageIndex)
654
+ }
655
+ },
656
+ setPageAllLine (arr) {
657
+ this.currentPageAllLine = []
658
+ arr.forEach((item, index) => {
659
+ let i = this.currentPageAllLine.findIndex(l => { return l.page && l.page == item.page })
660
+ if (i != -1) {
661
+ // this.currentPageAllLine[i].allLines.lines.push(item.extractInfo.lines)
662
+ this.currentPageAllLine[i].allLines.push({
663
+ pageCount: index,
664
+ lines: item.extractInfo.lines
665
+ })
666
+ } else {
667
+ this.currentPageAllLine.push({
668
+ page: item.page,
669
+ allLines: [{
670
+ pageCount: index,
671
+ lines: item.extractInfo.lines
672
+ }],
673
+ })
674
+ }
675
+ })
676
+ },
677
+ openTouch() {
678
+ // this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行
679
+ let that = this;
680
+ this.$nextTick(() => {
681
+ // setInterval(() => {
682
+ // this.scale = this.scale + 0.1
683
+ // that.pages.forEach((item, index) =>{
684
+ // if(item.dom) {
685
+ // item.dom.children.forEach( childDom =>{
686
+ // if(childDom.getAttribute('react-count')) {
687
+ // childDom.style.transform = "scale(" + this.scale + ")";
688
+ // childDom.style.transformOrigin = "0px 0px 0px";
689
+ // } else {
690
+ // item.dom = null
691
+ // this.startRenderPages(item.pdfPage, null, index)
692
+ // }
693
+ // } )
694
+ // }
695
+ // })
696
+ // }, 100);
697
+ // 获取放大或缩小的区域DOM
698
+ let matrix_box = this.contentView
699
+ matrix_box.addEventListener("touchstart", function (event) {
700
+ this.isTouchMoved = true
701
+ let touches = event.touches;
702
+ let events = touches[0];
703
+ let events2 = touches[1];
704
+
705
+ // event.preventDefault();
706
+
707
+ // 第一个触摸点的坐标
708
+ that.displacement.pageX = events.pageX;
709
+ that.displacement.pageY = events.pageY;
710
+
711
+ that.displacement.moveable = true;
712
+
713
+ if (events2) {
714
+ that.displacement.pageX2 = events2.pageX;
715
+ that.displacement.pageY2 = events2.pageY;
716
+ }
717
+
718
+ that.displacement.originScale = this.scale || 1;
719
+ // console.log(that.displacement);
720
+ });
721
+ document.addEventListener("touchmove", function (event) {
722
+ if (!that.displacement.moveable) {
723
+ return;
724
+ }
725
+ // event.preventDefault();
726
+ let touches = event.touches;
727
+ let events = touches[0];
728
+ let events2 = touches[1];
729
+ // 双指移动
730
+ if (events2) {
731
+ // 第2个指头坐标在touchmove时候获取
732
+ if (!that.displacement.pageX2) {
733
+ that.displacement.pageX2 = events2.pageX;
734
+ }
735
+ if (!that.displacement.pageY2) {
736
+ that.displacement.pageY2 = events2.pageY;
737
+ }
738
+ // 双指缩放比例计算
739
+ let zoom = that.getDistance({
740
+ x: events.pageX,
741
+ y: events.pageY
742
+ },
743
+ {
744
+ x: events2.pageX,
745
+ y: events2.pageY
746
+ }
747
+ ) / that.getDistance(
748
+ {
749
+ x: that.displacement.pageX,
750
+ y: that.displacement.pageY
751
+ },
752
+ {
753
+ x: that.displacement.pageX2,
754
+ y: that.displacement.pageY2
755
+ }
756
+ );
757
+ // 应用在元素上的缩放比例
758
+ let newScale = that.displacement.originScale * zoom;
759
+ console.log(zoom, newScale , this.scale, 'newScale');
760
+ // 最大缩放比例限制
761
+ if (newScale > 2) {
762
+ newScale = 2;
763
+ }
764
+ // 最大缩放比例限制
765
+ if(newScale < 1) {
766
+ newScale = 1;
767
+ }
768
+ // 记住使用的缩放值
769
+ that.displacement.scale = newScale;
770
+ // console.log(newScale);
771
+ matrix_box.style.transform = "scale(" + newScale + ")";
772
+ // 设置旋转元素的基点位置
773
+ matrix_box.style.transformOrigin = "0px 0px 0px";
774
+ }
775
+ },{ passive: false });
776
+ document.addEventListener('touchend',function() {
777
+ that.isTouchMoved = false
778
+ },{ passive: false })
779
+ });
780
+ },
781
+ getDistance(start, stop) {
782
+ // Math.hypot()计算参数的平方根
783
+ return Math.hypot(stop.x - start.x, stop.y - start.y);
784
+ },
785
+ setupCanvas(canvas, width, height) {
786
+ const dpr = 1;
787
+ // const rect = canvas.getBoundingClientRect();
788
+ canvas.width = width
789
+ canvas.height = height
790
+ const ctx = canvas.getContext('2d');
791
+ console.log(canvas.width, canvas.height, dpr, this.scale);
792
+ ctx?.scale(dpr, dpr );
793
+ return ctx;
794
+ },
795
+ changeScale(value) {
796
+ if(value == 'zoom') {
797
+ this.handScale = 'auto'
798
+ this.transformSalce = (this.transformSalce + 0.2).toFixed(1)
799
+ } else if(value == 'reduce') {
800
+ if((this.transformSalce - 0.2).toFixed(1) <= 0) {
801
+ return
802
+ }
803
+ this.handScale = 'auto'
804
+ this.transformSalce = (this.transformSalce - 0.2).toFixed(1)
805
+ } else if(value == 'auto') {
806
+ this.transformSalce = this.$refs.pdfView.clientWidth / this.pageSize.width
807
+ } else if(value == 'reality') {
808
+ this.transformSalce = 0.5
809
+ } else {
810
+ this.transformSalce = (value / 2).toFixed(1)
811
+ }
812
+ this.transformSalce = Number(this.transformSalce)
813
+ this.contentView.style.transform = 'scale(' + this.transformSalce + ')';
814
+ // this.getpdfResloutePage(this.cachePdf[0])
815
+ },
816
+ },
817
+ computed:{
818
+ perviewUrl() {
819
+ return '/web/viewer.html?file=' + '/pdflist/pdf4split-1.pdf'
820
+ }
821
+ },
822
+ watch:{
823
+ tagIds: {
824
+ handler(value) {
825
+ if(value && value.length) {
826
+ // pdf_view 下创建 所有canvs的容器
827
+ this.contentView = document.createElement('div')
828
+ this.contentView.style.transformOrigin = '0px 0px 0px'
829
+ this.$http.get('/knowledge-api/knowledge/knowledge-part-location-info/list?ids=' + value.join(',')).then(res =>{
830
+ // 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}
831
+ // 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}
832
+ // 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}
833
+ // 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}
834
+ // 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}
835
+ // if(value.length === 1) {
836
+ // this.$refs.pdfView.style.height = 'calc(100% - 50px)'
837
+ // }
838
+ if (res.data.code == 0) {
839
+ // tagIds 会按照gpt识别的生成有序的数组,前端直接按照下标的顺序取就可以了
840
+ // 缓存拿到的所有数据
841
+ this.cachePdf = res.data.data
842
+ let publicPageFileUrl = res.data.data[0].publicPageFileUrl
843
+ this.currentPage = 0
844
+ // console.log(publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')));
845
+ if (publicPageFileUrl.substring(publicPageFileUrl.lastIndexOf('.')) === '.pdf') {
846
+ this.preViewType = 'pdf'
847
+ this.setPageAllLine(this.cachePdf)
848
+ this.getpdfResloutePage(res.data.data[0])
849
+ } else {
850
+ this.preViewType = 'excal'
851
+ this.$http.post(
852
+ '/knowledge-api/temporary-certificate/or-origin?expired=30',
853
+ publicPageFileUrl,
854
+ {
855
+ headers: {
856
+ "Content-Type": "application/json",
857
+ },
858
+ }).then(res => {
859
+ // 使用原声请求方式 axios会带有不需要的请求头
860
+ let xhr = new XMLHttpRequest();
861
+ xhr.open('GET', res.data || res.bodyText , true);
862
+ // 定义请求完成的处理函数,请求前也可以增加加载框/禁用下载按钮逻辑
863
+ xhr.onload = ({ currentTarget }) => {
864
+ // 请求完成
865
+ if (currentTarget.status === 200) { // 返回200
866
+ this.contentView.innerHTML = currentTarget.response
867
+ this.contentView.style.padding = '10px'
868
+ // this.contentView.style.position = 'relative'
869
+ this.$refs.pdfView.style.backgroundColor = '#FFFFFF'
870
+ this.$refs.pdfView.appendChild(this.contentView)
871
+ let allTr = Array.from(this.$refs.pdfView.getElementsByTagName('tr'))
872
+ this.allTr = []
873
+ for (let index = 0; index < allTr.length; index++) {
874
+ if(value.includes(allTr[index].getAttribute('tag-id'))) {
875
+ this.allTr.push(allTr[index])
876
+ }
877
+ }
878
+ this.currentChange(1)
879
+
880
+ }
881
+ }
882
+ xhr.send();
883
+ })
884
+ }
885
+ } else {
886
+ let div = document.createElement('div')
887
+ div.innerText = '文件加载异常'
888
+ this.contentView.appendChild(div)
889
+ this.$refs.pdfView.appendChild(this.contentView)
890
+ }
891
+ })
892
+ }
893
+ },
894
+ deep:true,
895
+ immediate:true
896
+ }
897
+ },
898
+ mounted () {
899
+ if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) {
900
+ this.isPC = false
901
+ } else {
902
+ this.isPC = true
903
+ }
904
+ }
905
+ }
906
+ </script>
907
+
908
+ <style lang="less" scoped>
909
+ .pdf_view {
910
+ width: 100%;
911
+ height: calc(100% - 110px);
912
+ overflow: auto;
913
+ background-color: #f5f7fb;
914
+ margin-bottom: 60px;
915
+ box-sizing: border-box;
916
+ // position: relative;
917
+ // > div {
918
+ // width: 100%;
919
+ // height: 100%;
920
+ // overflow: hidden;
921
+ // overflow-y: auto;
922
+ // position: relative;
923
+ // }
924
+ > iframe {
925
+ width: 100%;
926
+ height: 100%;
927
+ }
928
+ a:link {
929
+ color: none;
930
+ }
931
+ a:visited {
932
+ color: none;
933
+ }
934
+ a:hover {
935
+ color: none;
936
+ }
937
+ a:active {
938
+ color: none;
939
+ }
940
+ .btn_footer {
941
+ width: 100%;
942
+ height: 60px;
943
+ display: flex;
944
+ align-items: center;
945
+ justify-content: space-around;
946
+ position: absolute;
947
+ bottom: 0px;
948
+ left: 0;
949
+ z-index: 999;
950
+ background: #ffffff;
951
+ .prev, .next {
952
+ width: 35%;
953
+ height: 40px;
954
+ display: flex;
955
+ align-items: center;
956
+ justify-content: center;
957
+ border-radius: 50px;
958
+ cursor: pointer;
959
+ }
960
+ .prev {
961
+ background: #F2F5FA;
962
+ color: #000;
963
+ }
964
+ .next {
965
+ background: #366aff;
966
+ color: #ffffff;
967
+ }
968
+ }
969
+ #pagination {
970
+ .total-class {
971
+ margin-right: 13px;
972
+ font-weight: 400;
973
+ }
974
+
975
+ position: absolute;
976
+ bottom: 0px;
977
+ right: 0;
978
+ width: 100%;
979
+ display: flex;
980
+ align-items: center;
981
+ justify-content: center;
982
+ height: 50px;
983
+ background-color: white;
984
+ box-shadow: 0px 0px 18px 0px rgba(29, 55, 129, 0.07);
985
+ border-radius: 5px;
986
+ z-index: 1000;
987
+
988
+ /deep/.el-pagination {
989
+ margin-right: 110px;
990
+ }
991
+
992
+ /deep/.el-pager {
993
+ background: #EDF0F6;
994
+ border-radius: 15px;
995
+ }
996
+
997
+ /deep/.el-pagination.is-background .btn-next {
998
+ width: 30px;
999
+ height: 30px;
1000
+ background: #EDF0F6;
1001
+ border-radius: 50%;
1002
+ }
1003
+
1004
+ /deep/.el-pagination .btn-next {
1005
+ width: 30px;
1006
+ height: 30px;
1007
+ background: #EDF0F6;
1008
+ border-radius: 50%;
1009
+ padding-left: 0;
1010
+ margin-left: 5px;
1011
+ }
1012
+
1013
+ /deep/.el-pagination .btn-prev {
1014
+ width: 30px;
1015
+ height: 30px;
1016
+ background: #EDF0F6;
1017
+ border-radius: 50%;
1018
+ padding-right: 0;
1019
+ margin-right: 5px;
1020
+ }
1021
+
1022
+ /deep/.el-pagination button {
1023
+ padding: 0;
1024
+ min-width: 30px;
1025
+ }
1026
+
1027
+ /deep/.el-pager li {
1028
+ background: #EDF0F6;
1029
+ height: 30px;
1030
+ min-width: 30px;
1031
+ line-height: 30px;
1032
+ font-size: 12px;
1033
+ color: #717b90;
1034
+ }
1035
+
1036
+ /deep/.el-pager li:first-child {
1037
+ border-bottom-left-radius: 15px !important;
1038
+ border-top-left-radius: 15px !important;
1039
+ }
1040
+
1041
+ /deep/.el-pager li:last-child {
1042
+ border-top-right-radius: 15px !important;
1043
+ border-bottom-right-radius: 15px !important;
1044
+ }
1045
+
1046
+ /deep/.el-pager li.active {
1047
+ width: 30px;
1048
+ height: 30px;
1049
+ min-width: 30px;
1050
+ background: #366AFF;
1051
+ border: 3px solid #A1B9FF;
1052
+ border-radius: 50%;
1053
+ line-height: 24px;
1054
+ color: white;
1055
+ }
1056
+
1057
+ /deep/.el-pagination.is-background .el-pager li:not(.disabled).active {
1058
+ background: #366AFF;
1059
+ }
1060
+ }
1061
+ .change_scale {
1062
+ width: 100%;
1063
+ height: 50px;
1064
+ position: absolute;
1065
+ top: 50px;
1066
+ left: 0;
1067
+ background: #ffffff;
1068
+ display: flex;
1069
+ align-items: center;
1070
+ padding: 0 10px;
1071
+ box-sizing: border-box;
1072
+ section {
1073
+ cursor: pointer;
1074
+ width: 30px;
1075
+ height: 30px;
1076
+ margin-right: 5px;
1077
+ border-radius: 5px;
1078
+ display: flex;
1079
+ align-items: center;
1080
+ justify-content: center;
1081
+ i {
1082
+ font-weight: 900;
1083
+ }
1084
+ }
1085
+ section:hover {
1086
+ background: rgba(221, 222, 223, 1);
1087
+ }
1088
+ }
1089
+ }
1090
+
1091
+ </style>
1092
+ <style lang="less">
1093
+ .animation {
1094
+ animation-name: highlight;
1095
+ animation-duration: 4s;
1096
+ }
1097
+ @keyframes highlight {
1098
+ 0% {
1099
+ background:rgba(255, 136, 0, 0.3);
1100
+ }
1101
+ 25% {
1102
+ background:rgba(255, 136, 0, 0.6);
1103
+ }
1104
+ 50% {
1105
+ background:rgba(255, 136, 0, 0.3);
1106
+ }
1107
+ 75% {
1108
+ background:rgba(255, 136, 0, 0.6);
1109
+ }
1110
+ 100% {
1111
+ background:rgba(255, 136, 0, 0.3);
1112
+ }
1113
+ }
1111
1114
  </style>