askbot-dragon 1.6.76-beta → 1.6.76

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 (308) 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 -55
  5. package/public/index.html +75 -72
  6. package/public/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  7. package/public/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  8. package/public/pdfjs/cmaps/78-H.bcmap +0 -0
  9. package/public/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  10. package/public/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  11. package/public/pdfjs/cmaps/78-V.bcmap +0 -0
  12. package/public/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  13. package/public/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  14. package/public/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  15. package/public/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  16. package/public/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  17. package/public/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  18. package/public/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  19. package/public/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  20. package/public/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  21. package/public/pdfjs/cmaps/Add-H.bcmap +0 -0
  22. package/public/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  23. package/public/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  24. package/public/pdfjs/cmaps/Add-V.bcmap +0 -0
  25. package/public/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  26. package/public/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  27. package/public/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  28. package/public/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  29. package/public/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  30. package/public/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  31. package/public/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  32. package/public/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  33. package/public/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  34. package/public/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  35. package/public/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  36. package/public/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  37. package/public/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  38. package/public/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  39. package/public/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  40. package/public/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  41. package/public/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  42. package/public/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  43. package/public/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  44. package/public/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  45. package/public/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  46. package/public/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  47. package/public/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  48. package/public/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  49. package/public/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  50. package/public/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  51. package/public/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  52. package/public/pdfjs/cmaps/B5-H.bcmap +0 -0
  53. package/public/pdfjs/cmaps/B5-V.bcmap +0 -0
  54. package/public/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  55. package/public/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  56. package/public/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  57. package/public/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  58. package/public/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  59. package/public/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  60. package/public/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  61. package/public/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  62. package/public/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  63. package/public/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  64. package/public/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  65. package/public/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  66. package/public/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  67. package/public/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  68. package/public/pdfjs/cmaps/EUC-H.bcmap +0 -0
  69. package/public/pdfjs/cmaps/EUC-V.bcmap +0 -0
  70. package/public/pdfjs/cmaps/Ext-H.bcmap +0 -0
  71. package/public/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  72. package/public/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  73. package/public/pdfjs/cmaps/Ext-V.bcmap +0 -0
  74. package/public/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  75. package/public/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  76. package/public/pdfjs/cmaps/GB-H.bcmap +4 -0
  77. package/public/pdfjs/cmaps/GB-V.bcmap +0 -0
  78. package/public/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  79. package/public/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  80. package/public/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  81. package/public/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  82. package/public/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  83. package/public/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  84. package/public/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  85. package/public/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  86. package/public/pdfjs/cmaps/GBT-H.bcmap +0 -0
  87. package/public/pdfjs/cmaps/GBT-V.bcmap +0 -0
  88. package/public/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  89. package/public/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  90. package/public/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  91. package/public/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  92. package/public/pdfjs/cmaps/H.bcmap +0 -0
  93. package/public/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  94. package/public/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  95. package/public/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  96. package/public/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  97. package/public/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  98. package/public/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  99. package/public/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  100. package/public/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  101. package/public/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  102. package/public/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  103. package/public/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  104. package/public/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  105. package/public/pdfjs/cmaps/Hankaku.bcmap +0 -0
  106. package/public/pdfjs/cmaps/Hiragana.bcmap +0 -0
  107. package/public/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  108. package/public/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  109. package/public/pdfjs/cmaps/KSC-H.bcmap +0 -0
  110. package/public/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  111. package/public/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  112. package/public/pdfjs/cmaps/KSC-V.bcmap +0 -0
  113. package/public/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  114. package/public/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  115. package/public/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  116. package/public/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  117. package/public/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  118. package/public/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  119. package/public/pdfjs/cmaps/Katakana.bcmap +0 -0
  120. package/public/pdfjs/cmaps/LICENSE +36 -0
  121. package/public/pdfjs/cmaps/NWP-H.bcmap +0 -0
  122. package/public/pdfjs/cmaps/NWP-V.bcmap +0 -0
  123. package/public/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  124. package/public/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  125. package/public/pdfjs/cmaps/Roman.bcmap +0 -0
  126. package/public/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  127. package/public/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  128. package/public/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  129. package/public/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  130. package/public/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  131. package/public/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  132. package/public/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  133. package/public/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  134. package/public/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  135. package/public/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  136. package/public/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  137. package/public/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  138. package/public/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  139. package/public/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  140. package/public/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  141. package/public/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  142. package/public/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  143. package/public/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  144. package/public/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  145. package/public/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  146. package/public/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  147. package/public/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  148. package/public/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  149. package/public/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  150. package/public/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  151. package/public/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  152. package/public/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  153. package/public/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  154. package/public/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  155. package/public/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  156. package/public/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  157. package/public/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  158. package/public/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  159. package/public/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  160. package/public/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  161. package/public/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  162. package/public/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  163. package/public/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  164. package/public/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  165. package/public/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  166. package/public/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  167. package/public/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  168. package/public/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  169. package/public/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  170. package/public/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  171. package/public/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  172. package/public/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  173. package/public/pdfjs/cmaps/V.bcmap +0 -0
  174. package/public/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  175. package/public/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  176. package/public/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  177. package/public/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  178. package/public/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  179. package/public/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  180. package/public/pdfjs/standard_fonts/FoxitSans.pfb +0 -0
  181. package/public/pdfjs/standard_fonts/FoxitSansBold.pfb +0 -0
  182. package/public/pdfjs/standard_fonts/FoxitSansBoldItalic.pfb +0 -0
  183. package/public/pdfjs/standard_fonts/FoxitSansItalic.pfb +0 -0
  184. package/public/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  185. package/public/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  186. package/public/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  187. package/public/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  188. package/public/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  189. package/public/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  190. package/public/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
  191. package/public/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  192. package/public/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  193. package/public/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  194. package/public/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  195. package/src/App.vue +31 -31
  196. package/src/api/index.js +1 -1
  197. package/src/api/mock.http +2 -2
  198. package/src/api/requestUrl.js +185 -185
  199. package/src/assets/image/default_avt_ui.png +0 -0
  200. package/src/assets/image/filtType/audio.png +0 -0
  201. package/src/assets/image/filtType/excel1.png +0 -0
  202. package/src/assets/image/filtType/general.png +0 -0
  203. package/src/assets/image/filtType/html.png +0 -0
  204. package/src/assets/image/filtType/image1.png +0 -0
  205. package/src/assets/image/filtType/link.png +0 -0
  206. package/src/assets/image/filtType/md2.png +0 -0
  207. package/src/assets/image/filtType/mode.png +0 -0
  208. package/src/assets/image/filtType/news.png +0 -0
  209. package/src/assets/image/filtType/pdf1.png +0 -0
  210. package/src/assets/image/filtType/ppt1.png +0 -0
  211. package/src/assets/image/filtType/selfadd1.png +0 -0
  212. package/src/assets/image/filtType/txt1.png +0 -0
  213. package/src/assets/image/filtType/video.png +0 -0
  214. package/src/assets/image/filtType/wechat.png +0 -0
  215. package/src/assets/image/filtType/word1.png +0 -0
  216. package/src/assets/image/loading.gif +0 -0
  217. package/src/assets/js/AliyunlssUtil.js +117 -92
  218. package/src/assets/js/Base64Util.js +22 -22
  219. package/src/assets/js/common.js +287 -252
  220. package/src/assets/js/hammer.js +89 -100
  221. package/src/assets/js/script.js +36 -36
  222. package/src/assets/less/common.css +6773 -6773
  223. package/src/assets/less/converSationContainer/common.less +192 -199
  224. package/src/assets/less/converSationContainer/converSatonContainer.less +486 -493
  225. package/src/assets/less/iconfont.css +37 -37
  226. package/src/assets/less/ticketMessage.less +294 -294
  227. package/src/assets/less/variables.less +122 -0
  228. package/src/components/ActionAlertIframe.vue +155 -177
  229. package/src/components/AiGuide.vue +473 -466
  230. package/src/components/AnswerDocknowledge.vue +1207 -1059
  231. package/src/components/AnswerVoice.vue +286 -285
  232. package/src/components/AskIFrame.vue +15 -15
  233. package/src/components/ConversationContainer.vue +10880 -4934
  234. package/src/components/FileType.vue +86 -86
  235. package/src/components/Message.vue +27 -27
  236. package/src/components/MyEditor.vue +343 -351
  237. package/src/components/QwFeedback.vue +304 -0
  238. package/src/components/actionSatisfaction.vue +109 -107
  239. package/src/components/actionSendToBot.vue +64 -62
  240. package/src/components/answerDissatisfaction.vue +64 -62
  241. package/src/components/answerRadio.vue +261 -186
  242. package/src/components/ask-components/DissatisfactionOptions.vue +58 -57
  243. package/src/components/ask-components/Msgloading.vue +38 -37
  244. package/src/components/ask-components/SatisfactionV2.vue +15 -15
  245. package/src/components/askVideo.vue +214 -162
  246. package/src/components/assetDetails.vue +379 -378
  247. package/src/components/assetMessage.vue +231 -228
  248. package/src/components/associationIntention.vue +414 -355
  249. package/src/components/attachmentPreview.vue +92 -90
  250. package/src/components/botActionSatisfactor.vue +70 -68
  251. package/src/components/chatContent.vue +514 -513
  252. package/src/components/feedBack.vue +138 -136
  253. package/src/components/fielListView.vue +352 -351
  254. package/src/components/file/AliyunOssComponents.vue +108 -108
  255. package/src/components/formTemplate.vue +3517 -3572
  256. package/src/components/imgView.vue +32 -0
  257. package/src/components/intelligentSummary.vue +232 -227
  258. package/src/components/interruptComponents/imageSelectionAnswer.vue +203 -0
  259. package/src/components/interruptComponents/multipleChoiceAnswer.vue +134 -0
  260. package/src/components/interruptComponents/singleChoiceAnswer.vue +82 -0
  261. package/src/components/kkview.vue +1130 -1138
  262. package/src/components/loadingProcess.vue +164 -164
  263. package/src/components/markDownText.vue +961 -0
  264. package/src/components/message/ActionAlertIframe.vue +112 -112
  265. package/src/components/message/ShopMessage.vue +164 -164
  266. package/src/components/message/TextMessage.vue +926 -924
  267. package/src/components/message/TicketMessage.vue +201 -201
  268. package/src/components/message/swiper/index.js +4 -4
  269. package/src/components/message/swiper/ticketSwiper.vue +503 -503
  270. package/src/components/message/swiper/ticketSwiperItem.vue +61 -61
  271. package/src/components/msgLoading.vue +231 -231
  272. package/src/components/myPopup.vue +75 -70
  273. package/src/components/outputComponents/outputCom.vue +149 -0
  274. package/src/components/pagination.vue +130 -0
  275. package/src/components/pdfPosition.vue +1337 -1506
  276. package/src/components/popup.vue +230 -227
  277. package/src/components/preview/docView.vue +263 -0
  278. package/src/components/preview/excelView.vue +260 -0
  279. package/src/components/preview/markDownView.vue +70 -0
  280. package/src/components/preview/newPositionPreview.vue +601 -0
  281. package/src/components/preview/pdfView.vue +973 -0
  282. package/src/components/previewDoc.vue +253 -247
  283. package/src/components/previewPdf.vue +1106 -757
  284. package/src/components/previewWisdom.vue +252 -0
  285. package/src/components/receiverMessagePlatform.vue +71 -65
  286. package/src/components/recommend.vue +82 -80
  287. package/src/components/selector/hOption.vue +20 -20
  288. package/src/components/selector/hSelector.vue +199 -199
  289. package/src/components/selector/hWrapper.vue +216 -216
  290. package/src/components/senderMessagePlatform.vue +60 -50
  291. package/src/components/source/BotMessage.vue +24 -24
  292. package/src/components/source/CustomMessage.vue +24 -24
  293. package/src/components/test.vue +260 -260
  294. package/src/components/tree.vue +310 -295
  295. package/src/components/utils/AliyunIssUtil.js +103 -81
  296. package/src/components/utils/ckeditor.js +185 -174
  297. package/src/components/utils/format_date.js +25 -25
  298. package/src/components/utils/index.js +6 -6
  299. package/src/components/utils/math_utils.js +29 -29
  300. package/src/components/voiceComponent.vue +122 -119
  301. package/src/components/welcomeKnowledgeFile.vue +346 -340
  302. package/src/components/welcomeLlmCard.vue +142 -140
  303. package/src/components/welcomeSuggest.vue +99 -97
  304. package/src/locales/cn.json +100 -0
  305. package/src/locales/en.json +99 -0
  306. package/src/main.js +76 -57
  307. package/vue.config.js +54 -54
  308. package/src/components/newPdfPosition.vue +0 -878
@@ -0,0 +1,973 @@
1
+ <template>
2
+ <div class="pdfViewPage" id="pdfViewPage">
3
+ <!-- 按钮容器 -->
4
+ <div class="button-container" v-if="false">
5
+ <div class="change_scale">
6
+ <section @click="zoomOut">
7
+ <i class="el-icon-minus"></i>
8
+ </section>
9
+ <el-divider direction="vertical"></el-divider>
10
+ <section @click="zoomIn">
11
+ <i class="el-icon-plus"></i>
12
+ </section>
13
+ </div>
14
+ <!-- 文件上传 -->
15
+ <!-- <label for="file-upload" class="file-upload-label">-->
16
+ <!-- 上传 PDF 文件-->
17
+ <!-- <input-->
18
+ <!-- id="file-upload"-->
19
+ <!-- type="file"-->
20
+ <!-- accept="application/pdf"-->
21
+ <!-- @change="handleFileUpload"-->
22
+ <!-- class="file-input"-->
23
+ <!-- />-->
24
+ <!-- </label>-->
25
+
26
+ <!-- &lt;!&ndash; 跳转按钮(已有高亮) &ndash;&gt;-->
27
+ <!-- <button @click="jumpToHighlight" class="action-button">-->
28
+ <!-- 跳转到第一个高亮区域-->
29
+ <!-- </button>-->
30
+ <!-- -->
31
+ <!-- &lt;!&ndash; 缩放按钮 &ndash;&gt;-->
32
+ <!-- <button @click="zoomIn" class="action-button">放大</button>-->
33
+ <!-- <button @click="zoomOut" class="action-button">缩小</button>-->
34
+ <!-- -->
35
+ <!-- &lt;!&ndash; 搜索框和按钮 &ndash;&gt;-->
36
+ <!-- <input v-model="searchQuery" placeholder="输入搜索关键词" type="text" />-->
37
+ <!-- <button @click="doSearch">搜索</button>-->
38
+ <!-- -->
39
+ <!-- &lt;!&ndash; 搜索结果导航 &ndash;&gt;-->
40
+ <!-- <div v-if="searchTermCount > 0" class="search-nav">-->
41
+ <!-- <span>共找到 {{ searchTermCount }} 个匹配</span>-->
42
+ <!-- <template v-if="searchTermCount > 1">-->
43
+ <!-- <button @click="prevSearchResult">上一个</button>-->
44
+ <!-- <button @click="nextSearchResult">下一个</button>-->
45
+ <!-- </template>-->
46
+ <!-- </div>-->
47
+ </div>
48
+
49
+ <!-- PDF 渲染容器 -->
50
+ <div class="pdf-container" ref="pdfContainer" id="pdf-container">
51
+ <div
52
+ v-for="(page, index) in pages"
53
+ :key="index"
54
+ class="page-container"
55
+ >
56
+ <div class="canvas-wrapper" :id="'canvas-wrapper' + index">
57
+ <canvas ref="canvases"></canvas>
58
+ <!-- 在页面渲染中时显示loading -->
59
+ <div v-if="!page.loaded && !page.loading" class="page-loading-overlay">
60
+ <div class="spinner"></div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </div>
65
+
66
+ <div class="change_scale">
67
+ <i class="iconfont guoran-suoxiao1" @click="zoomOut"></i>
68
+ <i class="iconfont guoran-fangda1" @click="zoomIn"></i>
69
+ </div>
70
+ </div>
71
+ </template>
72
+
73
+ <script>
74
+ // import { getDocument } from "pdfjs-dist/webpack";
75
+ // import pdfWorker from "pdfjs-dist/build/pdf.worker.entry";
76
+
77
+ const pdfjsLib = window['pdfjsLib']
78
+ if(pdfjsLib) {
79
+ pdfjsLib.GlobalWorkerOptions.workerSrc = window['pdfjs-dist/build/pdf.worker']
80
+ }
81
+ const { TextLayerBuilder } = window['pdfjs-dist/web/pdf_viewer']
82
+ import { newInitWaterMark,setTimestamp } from "../../assets/js/common.js";
83
+ import Vue from 'vue';
84
+ export default {
85
+ name: "PdfViewer",
86
+ data() {
87
+ return {
88
+ pdfFile: null,
89
+ pdf: null,
90
+ numPages: 0,
91
+ scale: 1, // 初始缩小比例
92
+ renderInProgress: false,
93
+ pages: [], // { pageNumber: number, loaded: boolean, canvas: ref, loading: boolean }
94
+ // 静态高亮(坐标采用顶部为原点)
95
+ highlights: [],
96
+ searchQuery: "",
97
+ searchHighlights: [], // 搜索高亮(PDF文本坐标,自下往上)
98
+ observer: null,
99
+ currentPage: 1, // 当前可视区最接近顶部的页面
100
+ resizeTimeout: null,
101
+ currentSearchIndex: 0,
102
+ searchTermCount: 0,
103
+ loadingTask:null,
104
+ context:null,
105
+ viewport:null,
106
+ colors: ['0, 245, 255', '54, 106, 255', '33, 136, 104','255, 255, 51','0, 255, 127'],
107
+ pageNumber:1,
108
+ mergedGroupsList:[]
109
+ };
110
+ },
111
+ props:{
112
+ split_paragraphs:{
113
+ type:Array,
114
+ default(){
115
+ return []
116
+ }
117
+ },
118
+ ossPath:{
119
+ type:String,
120
+ default:""
121
+ },
122
+ isPC:{
123
+ type:Boolean,
124
+ default:true
125
+ },
126
+ textWatermarkStr:{
127
+ type:String,
128
+ default:""
129
+ }
130
+ },
131
+ methods: {
132
+ setHighlights(arr){
133
+ this.highlights = [];
134
+ for (let i =0;i<arr.length;i++){
135
+ if (arr[i].original_paragraph){
136
+ for (let j=0;j<arr[i].original_paragraph.length;j++){
137
+ let item = arr[i].original_paragraph[j];
138
+ let obj = {
139
+ position:item.position,
140
+ pageNumber: i+1,
141
+ page:item.page
142
+ }
143
+ this.highlights.push(obj);
144
+ }
145
+ }
146
+ }
147
+ },
148
+ mergedGroups(arr) {
149
+ const groupsMap = {};
150
+ let newArr = arr.filter(item => item.position && item.page)
151
+ newArr.forEach(group => {
152
+ if (!groupsMap[group.pageNumber]) {
153
+ groupsMap[group.pageNumber] = {
154
+ pageNumber: group.pageNumber,
155
+ position: [],
156
+ page:group.page
157
+ };
158
+ }
159
+ groupsMap[group.pageNumber].position = [
160
+ ...groupsMap[group.pageNumber].position,
161
+ ...group.position
162
+ ];
163
+ });
164
+ return Object.values(groupsMap);
165
+ },
166
+ async initPdf() {
167
+ if (!this.pdfFile) return;
168
+ this.pdfFile = setTimestamp(this.pdfFile)
169
+ // this.pdf = await pdfjsLib.getDocument(this.pdfFile).promise;
170
+ this.loadingTask = pdfjsLib.getDocument({
171
+ url: this.pdfFile,
172
+ cMapUrl: '/pdfjs/cmaps/',
173
+ cMapPacked: true,
174
+ standardFontDataUrl: '/pdfjs/standard_fonts/',
175
+ });
176
+ await this.loadingTask.promise.then(async pdf => {
177
+ // 获取PDF的第一页
178
+ this.pdf = pdf;
179
+ // this.numPages = pdf._transport.numPages;
180
+ let lazySize = pdf._transport.numPages;
181
+ this.numPages = Math.min(pdf._transport.numPages, lazySize);
182
+ // 初始化页面数据
183
+ this.pages = Array.from({ length: this.numPages }, (_, i) => ({
184
+ pageNumber: i + 1,
185
+ loaded: false,
186
+ canvas: null,
187
+ loading: false,
188
+ }));
189
+ // 清空搜索高亮
190
+ this.searchHighlights = [];
191
+ this.searchTermCount = 0;
192
+ this.currentSearchIndex = 0;
193
+ // 确保 DOM 更新完成后再设置 canvas 引用
194
+ await this.$nextTick();
195
+ await this.setCanvasRef();
196
+ }).catch(error => {
197
+ console.error('PDF 加载失败:', error);
198
+ })
199
+
200
+ },
201
+ async loadPdf() {
202
+ if (!this.pdfFile) return;
203
+ await this.initPdf();
204
+ // 确保 canvas 引用设置完成后再初始化观察器
205
+ await this.$nextTick();
206
+ // 延迟初始化观察器,确保所有 canvas 都已准备好
207
+ setTimeout(() => {
208
+ this.initObserver();
209
+ }, 200);
210
+ },
211
+ initObserver(type) {
212
+ if (this.observer) {
213
+ this.observer.disconnect();
214
+ }
215
+ this.observer = new IntersectionObserver(
216
+ (entries) => {
217
+ entries.forEach( (entry) => {
218
+ if (entry.isIntersecting) {
219
+ const index = Number(entry.target.getAttribute('data-index'));
220
+ const page = this.pages[index];
221
+ if (page && !page.loaded && !page.loading) {
222
+ this.renderPage(page.pageNumber);
223
+ }
224
+ this.updateCurrentPage();
225
+ }
226
+ });
227
+ },
228
+ {
229
+ root: this.$refs.pdfContainer,
230
+ rootMargin: '0px 0px 0px 0px',
231
+ threshold: 0.1,
232
+ }
233
+ );
234
+ // 确保 canvas 引用都已设置好后再开始观察
235
+ this.$nextTick(() => {
236
+ // 增加延迟确保所有 canvas 引用都已设置
237
+ setTimeout(() => {
238
+ this.pages.forEach((page, index) => {
239
+ const canvas = page.canvas;
240
+ if (canvas) {
241
+ canvas.setAttribute('data-index', index);
242
+ this.observer.observe(canvas);
243
+ }
244
+ });
245
+ },500)
246
+ if (type !== 'changeScale' && type !== 'onResize'){
247
+ setTimeout(async () => {
248
+ let currentPage = this.split_paragraphs.length > 0 ? this.split_paragraphs[0] : null;
249
+ let page = 1;
250
+ if (currentPage){
251
+ page = currentPage.original_paragraph[0].page
252
+ }
253
+ await this.loadPage(page);
254
+ this.jumpToHighlight(0);
255
+ },1300)
256
+ }
257
+ });
258
+ },
259
+ async loadPage(number){
260
+ for (let i=0;i<number;i++){
261
+ const page = this.pages[i];
262
+ if (!page.loaded && !page.loading) {
263
+ await this.renderPage(page.pageNumber);
264
+ }
265
+ await this.updateCurrentPage();
266
+ }
267
+ },
268
+ async renderPage(pageNumber) {
269
+ if (!this.pdf) return;
270
+ const pageIndex = pageNumber - 1;
271
+ const pageData = this.pages[pageIndex];
272
+ if (!pageData) return;
273
+ // 如果已经在加载或已加载,避免重复渲染
274
+ if (pageData.loaded || pageData.loading) return;
275
+
276
+ this.pageNumber = pageNumber;
277
+
278
+ try {
279
+ // 标记为加载中,防止重复渲染
280
+ this.$set(pageData, 'loading', true);
281
+
282
+ const page = await this.pdf.getPage(pageNumber);
283
+ let pdfWidth = page.getViewport({ scale: 1 }).width;
284
+ const displayScale = this.calculateScale(pdfWidth);
285
+ const viewport = page.getViewport({ scale: displayScale });
286
+ this.viewport = viewport;
287
+
288
+ const canvas = pageData.canvas;
289
+ if (!canvas) {
290
+ console.warn(`页面 ${pageNumber} 的 canvas 引用不存在`);
291
+ this.$set(pageData, 'loading', false);
292
+ return;
293
+ }
294
+
295
+ const context = canvas.getContext("2d");
296
+ if (!context) {
297
+ console.warn(`页面 ${pageNumber} 无法获取 canvas context`);
298
+ this.$set(pageData, 'loading', false);
299
+ return;
300
+ }
301
+
302
+ this.context = context;
303
+
304
+ // 计算输出缩放比例(与 vuePdf 保持一致)
305
+ const outputScale = this.getOutputScale();
306
+
307
+ // 计算实际显示的尺寸
308
+ let domWidth = Math.floor(viewport.width);
309
+ let domHeight = Math.floor(viewport.height);
310
+
311
+ // 设置 canvas 尺寸(与 vuePdf 保持一致,使用 outputScale)
312
+ // 注意:vuePdf 不使用 devicePixelRatio,为了保持一致,我们也只使用 outputScale
313
+ canvas.width = Math.floor(viewport.width * outputScale);
314
+ canvas.height = Math.floor(viewport.height * outputScale);
315
+ canvas.style.width = `${domWidth}px`;
316
+ canvas.style.height = `${domHeight}px`;
317
+
318
+ // 创建 transform 矩阵(与 vuePdf 保持一致)
319
+ let transform = outputScale !== 1
320
+ ? [outputScale, 0, 0, outputScale, 0, 0]
321
+ : null;
322
+
323
+ // 清除旧的文本层
324
+ let hasDoc = document.getElementById('textLayer' + pageNumber);
325
+ if (hasDoc) {
326
+ hasDoc.parentNode.removeChild(hasDoc);
327
+ }
328
+
329
+ // 渲染 PDF 页面到 canvas(传入 transform 确保正确渲染)
330
+ const renderTask = page.render({
331
+ canvasContext: context,
332
+ viewport: viewport,
333
+ transform: transform
334
+ });
335
+ await renderTask.promise;
336
+ transform = null;
337
+
338
+ // 渲染文本层(必须在高亮渲染之前,确保文本层在最上层)
339
+ try {
340
+ const textContent = await page.getTextContent();
341
+ const textDiv = document.createElement('div');
342
+ textDiv.setAttribute('class', 'textLayer');
343
+ textDiv.setAttribute('id', 'textLayer' + pageNumber);
344
+ // 关键:TextLayerBuilder 也需要传入 transform,确保文本位置正确
345
+ let textLayer = new TextLayerBuilder({
346
+ textLayerDiv: textDiv,
347
+ pageIndex: pageIndex,
348
+ viewport: viewport,
349
+ transform: transform, // 添加 transform 参数
350
+ });
351
+ // 使用 domWidth 和 domHeight(与 vuePdf 保持一致)
352
+ textDiv.style.width = `${domWidth}px`;
353
+ textDiv.style.height = `${domHeight}px`;
354
+ // 使用 hidden 但确保尺寸正确(与 vuePdf 保持一致)
355
+ textDiv.style.overflow = 'hidden';
356
+ textDiv.style.whiteSpace = 'pre-wrap';
357
+ textDiv.style.position = 'absolute';
358
+ textDiv.style.top = '0';
359
+ textDiv.style.left = '0';
360
+ textDiv.style.fontSize = '20px';
361
+ textDiv.style.color = 'black';
362
+ textLayer.setTextContent(textContent);
363
+ textLayer.render();
364
+
365
+ // 渲染完成后,检查文本层实际内容高度,如果超出则调整
366
+ await this.$nextTick();
367
+ const textLayerSpans = textDiv.querySelectorAll('span');
368
+ if (textLayerSpans.length > 0) {
369
+ let maxBottom = 0;
370
+ textLayerSpans.forEach(span => {
371
+ const rect = span.getBoundingClientRect();
372
+ const parentRect = textDiv.getBoundingClientRect();
373
+ const relativeBottom = rect.bottom - parentRect.top;
374
+ if (relativeBottom > maxBottom) {
375
+ maxBottom = relativeBottom;
376
+ }
377
+ });
378
+ // 如果文本内容超出当前高度,增加文本层高度(增加一些边距)
379
+ if (maxBottom > domHeight) {
380
+ textDiv.style.height = `${Math.ceil(maxBottom + 10)}px`;
381
+ }
382
+ }
383
+
384
+ // 将文本 div 添加到覆盖层中
385
+ let pagesDiv = document.getElementById('canvas-wrapper' + pageIndex);
386
+ if (pagesDiv) {
387
+ pagesDiv.appendChild(textDiv);
388
+ }
389
+ } catch (textError) {
390
+ console.warn(`页面 ${pageNumber} 文本层渲染失败:`, textError);
391
+ // 文本层渲染失败不影响页面继续渲染
392
+ }
393
+
394
+ // 渲染已有高亮区域(静态highlights)
395
+ // 注意:高亮是在 canvas 上绘制的,不会覆盖文本层(文本层在 canvas 上方)
396
+ // 需要传入 outputScale,因为 canvas 使用了 transform 渲染
397
+ try {
398
+ this.renderHighlights(context, pageNumber, viewport, outputScale);
399
+ } catch (highlightError) {
400
+ console.warn(`页面 ${pageNumber} 高亮渲染失败:`, highlightError);
401
+ }
402
+
403
+ // 渲染搜索高亮区域
404
+ try {
405
+ this.renderSearchHighlights(context, pageNumber, viewport, outputScale);
406
+ } catch (searchHighlightError) {
407
+ console.warn(`页面 ${pageNumber} 搜索高亮渲染失败:`, searchHighlightError);
408
+ }
409
+
410
+ // 标记为已加载
411
+ this.$set(pageData, 'loading', false);
412
+ this.$set(pageData, 'loaded', true);
413
+ } catch (error) {
414
+ console.error(`页面 ${pageNumber} 渲染失败:`, error);
415
+ // 渲染失败时重置状态,允许重试
416
+ this.$set(pageData, 'loading', false);
417
+ this.$set(pageData, 'loaded', false);
418
+ }
419
+ },
420
+ calculateScale(pdfWidth) {
421
+ const pdfViewPage = document.getElementById('pdfViewPage');
422
+ if (!pdfViewPage || !pdfWidth) return this.scale;
423
+ const horizontalPadding = this.isPC ? 50 : 16;
424
+ const containerWidth = Math.max(pdfViewPage.clientWidth - horizontalPadding, 1);
425
+ return (containerWidth / pdfWidth) * this.scale;
426
+ },
427
+ getOutputScale() {
428
+ return Math.min(window.devicePixelRatio || 1, 2);
429
+ },
430
+ async renderHighlights(context, number, viewport, outputScale = 1) {
431
+ const pageHighlights = this.highlights.filter(item => (item.page === number ))
432
+ let highlights = this.mergedGroups(pageHighlights);
433
+ this.mergedGroupsList = this.mergedGroupsList.concat(highlights)
434
+ if (context){
435
+ highlights.forEach(({ position,pageNumber }) => {
436
+ // this.drawHighlight(context, viewport, position, fillStyle, false);
437
+ const groups = [];
438
+ const colorIndex = pageNumber % this.colors.length;
439
+ let fillStyle = 'rgba(' + this.colors[colorIndex] + ',0.1)';
440
+ for (let i = 0; i < position.length; i += 4) {
441
+ groups.push(position.slice(i, i + 4));
442
+ }
443
+ for (let i = 0;i<groups.length;i++){
444
+ this.drawHighlight(context, viewport, groups[i], fillStyle, false, outputScale);
445
+ }
446
+ });
447
+ }
448
+ },
449
+ renderSearchHighlights(context, pageNumber, viewport, outputScale = 1) {
450
+ const pageHighlights = this.searchHighlights.filter(h => h.pageNumber === pageNumber);
451
+ pageHighlights.forEach(({ position }) => {
452
+ this.drawHighlight(context, viewport, position, "rgba(255, 255, 0, 0.4)", true, outputScale);
453
+ });
454
+ },
455
+ drawHighlight(context, viewport, position, fillStyle, fromSearch = false, outputScale = 1) {
456
+ const [x1, y1, x2, y2] = position;
457
+ // 使用 viewport.scale 计算 PDF 坐标到 viewport 坐标的转换
458
+ const scale = viewport.scale;
459
+ // PDF 页面的实际高度(未缩放)
460
+ const pageHeight = viewport.height / viewport.scale;
461
+
462
+ // 计算在 viewport 坐标系中的位置(PDF 坐标 → viewport 坐标)
463
+ let viewportX1 = x1 * scale;
464
+ let viewportX2 = x2 * scale;
465
+ let viewportY1, viewportY2;
466
+
467
+ if (fromSearch) {
468
+ // 搜索高亮:PDF坐标系(左下原点),需要转换为顶部原点
469
+ viewportY1 = (pageHeight - y1) * scale;
470
+ viewportY2 = (pageHeight - y2) * scale;
471
+ } else {
472
+ // 静态 highlights:顶部坐标原点,直接使用
473
+ viewportY1 = y1 * scale;
474
+ viewportY2 = y2 * scale;
475
+ }
476
+
477
+ // 由于 canvas 使用了 transform 渲染,PDF.js 会在内部应用 transform
478
+ // 但 context 的坐标系统是 canvas 的实际尺寸(viewport.width * outputScale)
479
+ // 而 viewport 坐标是基于 viewport.width 的,所以需要转换为 canvas 坐标
480
+ // 注意:outputScale 和 viewport.scale 是相同的值,所以这里只需要乘以 outputScale
481
+ // 但实际上 viewport.scale 已经应用了,所以这里应该直接使用 viewport 坐标
482
+ // 但 canvas 的实际尺寸是 viewport.width * outputScale,所以需要缩放
483
+ let canvasX1 = viewportX1 * outputScale;
484
+ let canvasX2 = viewportX2 * outputScale;
485
+ let canvasY1 = viewportY1 * outputScale;
486
+ let canvasY2 = viewportY2 * outputScale;
487
+
488
+ // 清除当前路径
489
+ context.beginPath();
490
+
491
+ context.fillStyle = fillStyle;
492
+ context.fillRect(
493
+ Math.min(canvasX1, canvasX2),
494
+ Math.min(canvasY1, canvasY2),
495
+ Math.abs(canvasX2 - canvasX1),
496
+ Math.abs(canvasY2 - canvasY1)
497
+ );
498
+ },
499
+ handleFileUpload(event) {
500
+ const file = event.target.files[0];
501
+ if (file) {
502
+ this.pdfFile = URL.createObjectURL(file);
503
+ this.clearPages();
504
+ this.loadPdf();
505
+ }
506
+ },
507
+ async setCanvasRef() {
508
+ // 等待 DOM 完全更新
509
+ await this.$nextTick();
510
+
511
+ if (!this.$refs.canvases || !Array.isArray(this.$refs.canvases)) {
512
+ console.warn('Canvas 引用未准备好,延迟重试');
513
+ // 如果 canvas 引用还没准备好,延迟重试
514
+ setTimeout(() => {
515
+ this.setCanvasRef();
516
+ }, 100);
517
+ return;
518
+ }
519
+
520
+ // 确保所有 canvas 引用都已设置
521
+ for (let index = 0; index < this.pages.length; index++) {
522
+ if (this.$refs.canvases && this.$refs.canvases[index]) {
523
+ this.$set(this.pages[index], 'canvas', this.$refs.canvases[index]);
524
+ } else {
525
+ console.warn(`页面 ${index + 1} 的 canvas 引用不存在`);
526
+ }
527
+ }
528
+ },
529
+ clearPages() {
530
+ this.pages = [];
531
+ if (this.observer) {
532
+ this.observer.disconnect();
533
+ }
534
+ },
535
+ jumpToHighlight(currentPage) {
536
+ let highlight = null;
537
+ if (this.split_paragraphs[currentPage] && this.split_paragraphs[currentPage].original_paragraph){
538
+ highlight = this.split_paragraphs[currentPage].original_paragraph[0];
539
+ }
540
+ if (!highlight) return;
541
+ this.scrollToHighlight(highlight);
542
+ },
543
+ scrollToHighlight(highlight) {
544
+ if (!highlight) return;
545
+ const { page, position } = highlight;
546
+
547
+ const fromSearch = this.searchHighlights.some(h => h === highlight);
548
+
549
+ this.$nextTick(() => {
550
+ const pageIndex = page - 1;
551
+ const pageData = this.pages[pageIndex];
552
+ const container = this.$refs.pdfContainer;
553
+ const canvas = pageData.canvas;
554
+ if (!canvas || !container) return;
555
+
556
+ const rect = canvas.getBoundingClientRect();
557
+ const containerRect = container.getBoundingClientRect();
558
+ this.pdf.getPage(page).then(pages => {
559
+ let pdfWidth = pages.getViewport({ scale: 1}).width
560
+ const scale = this.calculateScale(pdfWidth);
561
+ const viewport = pages.getViewport({ scale });
562
+ const pageHeight = viewport.height / viewport.scale;
563
+
564
+ const [x1, y1, x2, y2] = position;
565
+ let targetYPdf, targetXPdf;
566
+ if (fromSearch) {
567
+ // 搜索高亮使用上边界作为参考点
568
+ const highlightTopYPdf = Math.max(y1, y2);
569
+ const highlightLeftXPdf = (x1 + x2) / 2;
570
+ targetYPdf = highlightTopYPdf;
571
+ targetXPdf = highlightLeftXPdf;
572
+ } else {
573
+ // 静态高亮使用中心点
574
+ const highlightCenterYPdf = Number(Number(y1) + Number(y2)) / 2;
575
+ const highlightCenterXPdf = Number(Number(x1) + Number(x2)) / 2;
576
+ targetYPdf = highlightCenterYPdf;
577
+ targetXPdf = highlightCenterXPdf;
578
+ }
579
+
580
+ let targetYCanvas, targetXCanvas;
581
+ if (fromSearch) {
582
+ targetYCanvas = (pageHeight - targetYPdf) * scale;
583
+ } else {
584
+ targetYCanvas = targetYPdf * scale;
585
+ }
586
+ targetXCanvas = targetXPdf * scale;
587
+ // 将高亮位置转换为相对于container滚动坐标体系的绝对位置
588
+ // rect.top/left - containerRect.top/left为canvas相对container视口顶部/左侧的偏移
589
+ // 加上container当前的scrollTop/scrollLeft可获得绝对滚动系下的位置
590
+ const highlightAbsoluteY = (rect.top - containerRect.top) + container.scrollTop + targetYCanvas;
591
+ const highlightAbsoluteX = (rect.left - containerRect.left) + container.scrollLeft + targetXCanvas;
592
+
593
+ const topOffset = container.clientHeight / 2;
594
+ const leftOffset = container.clientWidth / 2;
595
+
596
+ const scrollTop = Math.max(0, highlightAbsoluteY - topOffset);
597
+ const scrollLeft = Math.max(0, highlightAbsoluteX - leftOffset);
598
+ container.scrollTo({
599
+ top: scrollTop,
600
+ left: scrollLeft,
601
+ behavior: "smooth",
602
+ });
603
+ });
604
+ });
605
+ },
606
+ zoomIn() {
607
+ this.updateCurrentPage();
608
+ // 检查是否有页面正在加载
609
+ if (this.pages.some(p => p.loading)) return;
610
+ const container = this.$refs.pdfContainer;
611
+ const currentScroll = container.scrollTop;
612
+ this.scale += 0.1;
613
+ this.reloadAllPages(currentScroll);
614
+ },
615
+ zoomOut() {
616
+ this.updateCurrentPage();
617
+ // 检查是否有页面正在加载
618
+ if (this.pages.some(p => p.loading)) return;
619
+ const container = this.$refs.pdfContainer;
620
+ const currentScroll = container.scrollTop;
621
+ this.scale = Math.max(this.scale - 0.1, 0.1);
622
+ this.reloadAllPages(currentScroll);
623
+ },
624
+ reloadAllPages(scrollPosition) {
625
+ const pages = Vue.observable(this.pages)
626
+ pages.forEach((p) => {
627
+ p.loaded = false;
628
+ this.$set(p,'loading',false)
629
+ if (p.canvas) {
630
+ const ctx = p.canvas.getContext('2d');
631
+ ctx.clearRect(0,0,p.canvas.width,p.canvas.height);
632
+ }
633
+ });
634
+
635
+ const container = this.$refs.pdfContainer;
636
+ this.$nextTick(() => {
637
+ container.scrollTop = scrollPosition;
638
+ this.initObserver('changeScale');
639
+ container.scrollTop = container.scrollTop + 1;
640
+ container.scrollTop = container.scrollTop - 1;
641
+ });
642
+ },
643
+ updateCurrentPage() {
644
+ const container = this.$refs.pdfContainer;
645
+ if (!container) return;
646
+ let closestPage = 1;
647
+ let closestDistance = Infinity;
648
+ this.pages.forEach((p) => {
649
+ if (p.canvas) {
650
+ const rect = p.canvas.getBoundingClientRect();
651
+ const containerRect = container.getBoundingClientRect();
652
+ const distance = Math.abs(rect.top - containerRect.top);
653
+ if (distance < closestDistance) {
654
+ closestDistance = distance;
655
+ closestPage = p.pageNumber;
656
+ }
657
+ }
658
+ });
659
+ this.currentPage = closestPage;
660
+ },
661
+ async doSearch() {
662
+ if (!this.pdf || !this.searchQuery) return;
663
+ // 检查是否有页面正在加载
664
+ if (this.pages.some(p => p.loading)) return;
665
+
666
+ this.searchHighlights = [];
667
+ const numPages = this.numPages;
668
+ const searchTerm = this.searchQuery;
669
+
670
+ for (let pageNumber = 1; pageNumber <= numPages; pageNumber++) {
671
+ const page = await this.pdf.getPage(pageNumber);
672
+ const textContent = await page.getTextContent();
673
+ const items = textContent.items;
674
+ let fullText = "";
675
+ let offsetPositions = [];
676
+ let currentPos = 0;
677
+ items.forEach((item) => {
678
+ offsetPositions.push({
679
+ str: item.str,
680
+ start: currentPos,
681
+ end: currentPos + item.str.length,
682
+ transform: item.transform,
683
+ width: item.width,
684
+ });
685
+ currentPos += item.str.length;
686
+ fullText += item.str;
687
+ });
688
+
689
+ let startIndex = 0;
690
+ while ((startIndex = fullText.indexOf(searchTerm, startIndex)) !== -1) {
691
+ const endIndex = startIndex + searchTerm.length;
692
+ const matchedItems = offsetPositions.filter(
693
+ (op) => op.start <= startIndex && op.end >= endIndex
694
+ );
695
+
696
+ if (matchedItems.length > 0) {
697
+ const matchItem = matchedItems[0];
698
+ const substringLength = searchTerm.length;
699
+ const avgCharWidth = matchItem.width / matchItem.str.length;
700
+
701
+ const substringOffset = startIndex - matchItem.start;
702
+
703
+ const lineHeight = Math.abs(matchItem.transform[3]);
704
+ const y1 = matchItem.transform[5];
705
+ const y2 = y1 + lineHeight;
706
+
707
+ const xStart =
708
+ matchItem.transform[4] + substringOffset * avgCharWidth;
709
+ const xEnd = xStart + substringLength * avgCharWidth;
710
+
711
+ this.searchHighlights.push({
712
+ pageNumber,
713
+ position: [xStart, y1, xEnd, y2],
714
+ });
715
+ }
716
+ startIndex = endIndex;
717
+ }
718
+ }
719
+
720
+ this.searchTermCount = this.searchHighlights.length;
721
+ this.currentSearchIndex = 0;
722
+
723
+ const container = this.$refs.pdfContainer;
724
+ const currentScroll = container.scrollTop;
725
+ this.pages.forEach((p) => {
726
+ p.loaded = false;
727
+ this.$set(p,'loading',false)
728
+ if (p.canvas) {
729
+ const ctx = p.canvas.getContext("2d");
730
+ ctx.clearRect(0, 0, p.canvas.width, p.canvas.height);
731
+ }
732
+ });
733
+ this.$nextTick(() => {
734
+ container.scrollTop = currentScroll;
735
+ this.initObserver();
736
+ container.scrollTop = container.scrollTop + 1;
737
+ container.scrollTop = container.scrollTop - 1;
738
+
739
+ if (this.searchTermCount > 0) {
740
+ this.scrollToHighlight(this.searchHighlights[0]);
741
+ }
742
+ });
743
+ },
744
+ prevSearchResult() {
745
+ if (this.searchTermCount <= 1) return;
746
+ this.currentSearchIndex = (this.currentSearchIndex - 1 + this.searchTermCount) % this.searchTermCount;
747
+ this.scrollToHighlight(this.searchHighlights[this.currentSearchIndex]);
748
+ },
749
+ nextSearchResult() {
750
+ if (this.searchTermCount <= 1) return;
751
+ this.currentSearchIndex = (this.currentSearchIndex + 1) % this.searchTermCount;
752
+ this.scrollToHighlight(this.searchHighlights[this.currentSearchIndex]);
753
+ },
754
+ onResize() {
755
+ clearTimeout(this.resizeTimeout);
756
+ this.resizeTimeout = setTimeout(() => {
757
+ // 检查是否有页面正在加载
758
+ if (this.pages.some(p => p.loading)) return;
759
+ const container = this.$refs.pdfContainer;
760
+ const currentScroll = container.scrollTop;
761
+ const pages = Vue.observable(this.pages)
762
+ pages.forEach((p) => {
763
+ p.loaded = false;
764
+ this.$set(p,'loading',false)
765
+ if (p.canvas) {
766
+ const ctx = p.canvas.getContext('2d');
767
+ ctx.clearRect(0,0,p.canvas.width,p.canvas.height);
768
+ }
769
+ });
770
+ this.$nextTick(() => {
771
+ container.scrollTop = currentScroll;
772
+ this.initObserver('onResize');
773
+ container.scrollTop = container.scrollTop + 1;
774
+ container.scrollTop = container.scrollTop - 1;
775
+ });
776
+ }, 300);
777
+ },
778
+ },
779
+ async mounted() {
780
+ window.addEventListener("resize", this.onResize);
781
+ this.pdfFile = this.ossPath;
782
+ console.log('ossPath',this.ossPath)
783
+ // this.clearPages();
784
+ // this.loadPdf();
785
+ if (this.textWatermarkStr){
786
+ newInitWaterMark('pdfViewPage', this.textWatermarkStr)
787
+ }
788
+ },
789
+ beforeDestroy() {
790
+ window.removeEventListener("resize", this.onResize);
791
+ if (this.observer) {
792
+ this.observer.disconnect();
793
+ }
794
+ },
795
+ watch:{
796
+ split_paragraphs:{
797
+ async handler(val){
798
+ this.highlights = [];
799
+ if (val.length > 0){
800
+ await this.setHighlights(val);
801
+ }
802
+ this.clearPages();
803
+ this.loadPdf();
804
+ },
805
+ immediate:true,
806
+ deep:true
807
+ },
808
+ ossPath:{
809
+ handler(val){
810
+ if (val){
811
+ this.pdfFile = this.ossPath;
812
+ }
813
+ },
814
+ immediate:true
815
+ }
816
+ }
817
+ };
818
+ </script>
819
+
820
+ <style lang="less" scoped>
821
+ @import "../../assets/less/variables.less";
822
+
823
+ .pdfViewPage{
824
+ width: 100%;
825
+ height: 100%;
826
+ }
827
+ .pdf-container {
828
+ display: flex;
829
+ flex-direction: column;
830
+ gap: 10px;
831
+ height: 100%;
832
+ overflow-y: auto;
833
+ overflow-x: auto;
834
+ margin: 0 auto;
835
+ position: relative;
836
+ border-radius: 10px;
837
+ background: @background-color-light;
838
+ width: 100%;
839
+ .textLayer{
840
+ span{
841
+ position: absolute;
842
+ color: transparent;
843
+ white-space:pre;
844
+ cursor: text;
845
+ transform-origin:0,0
846
+ }
847
+ }
848
+ }
849
+
850
+ .page-container {
851
+ position: relative;
852
+ display: flex;
853
+ justify-content: center;
854
+ width: 100%;
855
+ }
856
+
857
+ .canvas-wrapper {
858
+ position: relative;
859
+ width: 100%;
860
+ }
861
+
862
+ /* 在loading时覆盖canvas显示加载动画 */
863
+ .page-loading-overlay {
864
+ position: absolute;
865
+ top: 0;
866
+ left: 0;
867
+ right: 0;
868
+ bottom: 0;
869
+ background: rgba(255, 255, 255, 0.6);
870
+ display: flex;
871
+ align-items: center;
872
+ justify-content: center;
873
+ }
874
+
875
+ .spinner {
876
+ border: 6px solid @border-color-r3;
877
+ border-top: 6px solid @border-color-r7;
878
+ border-radius: 50%;
879
+ width: 40px;
880
+ height: 40px;
881
+ animation: spin 1s linear infinite;
882
+ }
883
+
884
+ canvas {
885
+ border: 1px solid @border-color-r5;
886
+ width: 100%;
887
+ height: auto;
888
+ margin-bottom: 10px;
889
+ }
890
+
891
+ .button-container {
892
+ display: flex;
893
+ justify-content: center;
894
+ }
895
+ .change_scale {
896
+ height: 80px;
897
+ //padding: 10px;
898
+ width: 32px;
899
+ border-top-left-radius: 20px;
900
+ border-bottom-left-radius: 20px;
901
+ position: absolute;
902
+ right: 0;
903
+ top: calc(50% - 40px);
904
+ //top: 50px;
905
+ //margin-bottom: 10px;
906
+ //left: 0;
907
+ background: @background-color-light;
908
+ border: 1px solid @border-color-copy;
909
+ display: flex;
910
+ flex-direction: column;
911
+ align-items: center;
912
+ justify-content: space-evenly;
913
+ //padding: 0 10px;
914
+ box-sizing: border-box;
915
+ i{
916
+ color: @font-primary-accent-color;
917
+ font-size: 20px;
918
+ }
919
+ section {
920
+ cursor: pointer;
921
+ width: 30px;
922
+ height: 30px;
923
+ margin-right: 5px;
924
+ border-radius: 5px;
925
+ display: flex;
926
+ align-items: center;
927
+ justify-content: center;
928
+
929
+ i {
930
+ font-weight: 900;
931
+ }
932
+ }
933
+
934
+ section:hover {
935
+ background: rgba(221, 222, 223, 1);
936
+ }
937
+ }
938
+ .search-nav {
939
+ display: flex;
940
+ align-items: center;
941
+ gap: 10px;
942
+ }
943
+
944
+ input[type="file"],
945
+ button,
946
+ input[type="text"] {
947
+ padding: 10px 15px;
948
+ font-size: 16px;
949
+ border: 1px solid @border-color-r4;
950
+ border-radius: 5px;
951
+ background-color: @background-color-custom;
952
+ cursor: pointer;
953
+ transition: all 0.2s ease-in-out;
954
+ }
955
+
956
+ button:hover,
957
+ input[type="file"]:hover,
958
+ input[type="text"]:hover {
959
+ background-color: @background-color-ipt-hover;
960
+ }
961
+
962
+ button:active,
963
+ input[type="file"]:active,
964
+ input[type="text"]:active {
965
+ background-color: @background-color-ipt-active;
966
+ }
967
+
968
+
969
+ @keyframes spin {
970
+ 0% { transform: rotate(0deg); }
971
+ 100% { transform: rotate(360deg); }
972
+ }
973
+ </style>