askbot-dragon 1.8.35-beta → 1.8.37-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/package.json +1 -1
  2. package/public/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  3. package/public/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  4. package/public/pdfjs/cmaps/78-H.bcmap +0 -0
  5. package/public/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  6. package/public/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  7. package/public/pdfjs/cmaps/78-V.bcmap +0 -0
  8. package/public/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  9. package/public/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  10. package/public/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  11. package/public/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  12. package/public/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  13. package/public/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  14. package/public/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  15. package/public/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  16. package/public/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  17. package/public/pdfjs/cmaps/Add-H.bcmap +0 -0
  18. package/public/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  19. package/public/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  20. package/public/pdfjs/cmaps/Add-V.bcmap +0 -0
  21. package/public/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  22. package/public/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  23. package/public/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  24. package/public/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  25. package/public/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  26. package/public/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  27. package/public/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  28. package/public/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  29. package/public/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  30. package/public/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  31. package/public/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  32. package/public/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  33. package/public/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  34. package/public/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  35. package/public/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  36. package/public/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  37. package/public/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  38. package/public/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  39. package/public/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  40. package/public/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  41. package/public/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  42. package/public/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  43. package/public/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  44. package/public/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  45. package/public/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  46. package/public/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  47. package/public/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  48. package/public/pdfjs/cmaps/B5-H.bcmap +0 -0
  49. package/public/pdfjs/cmaps/B5-V.bcmap +0 -0
  50. package/public/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  51. package/public/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  52. package/public/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  53. package/public/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  54. package/public/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  55. package/public/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  56. package/public/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  57. package/public/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  58. package/public/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  59. package/public/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  60. package/public/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  61. package/public/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  62. package/public/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  63. package/public/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  64. package/public/pdfjs/cmaps/EUC-H.bcmap +0 -0
  65. package/public/pdfjs/cmaps/EUC-V.bcmap +0 -0
  66. package/public/pdfjs/cmaps/Ext-H.bcmap +0 -0
  67. package/public/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  68. package/public/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  69. package/public/pdfjs/cmaps/Ext-V.bcmap +0 -0
  70. package/public/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  71. package/public/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  72. package/public/pdfjs/cmaps/GB-H.bcmap +4 -0
  73. package/public/pdfjs/cmaps/GB-V.bcmap +0 -0
  74. package/public/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  75. package/public/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  76. package/public/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  77. package/public/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  78. package/public/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  79. package/public/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  80. package/public/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  81. package/public/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  82. package/public/pdfjs/cmaps/GBT-H.bcmap +0 -0
  83. package/public/pdfjs/cmaps/GBT-V.bcmap +0 -0
  84. package/public/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  85. package/public/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  86. package/public/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  87. package/public/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  88. package/public/pdfjs/cmaps/H.bcmap +0 -0
  89. package/public/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  90. package/public/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  91. package/public/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  92. package/public/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  93. package/public/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  94. package/public/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  95. package/public/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  96. package/public/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  97. package/public/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  98. package/public/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  99. package/public/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  100. package/public/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  101. package/public/pdfjs/cmaps/Hankaku.bcmap +0 -0
  102. package/public/pdfjs/cmaps/Hiragana.bcmap +0 -0
  103. package/public/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  104. package/public/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  105. package/public/pdfjs/cmaps/KSC-H.bcmap +0 -0
  106. package/public/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  107. package/public/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  108. package/public/pdfjs/cmaps/KSC-V.bcmap +0 -0
  109. package/public/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  110. package/public/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  111. package/public/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  112. package/public/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  113. package/public/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  114. package/public/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  115. package/public/pdfjs/cmaps/Katakana.bcmap +0 -0
  116. package/public/pdfjs/cmaps/LICENSE +36 -0
  117. package/public/pdfjs/cmaps/NWP-H.bcmap +0 -0
  118. package/public/pdfjs/cmaps/NWP-V.bcmap +0 -0
  119. package/public/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  120. package/public/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  121. package/public/pdfjs/cmaps/Roman.bcmap +0 -0
  122. package/public/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  123. package/public/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  124. package/public/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  125. package/public/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  126. package/public/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  127. package/public/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  128. package/public/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  129. package/public/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  130. package/public/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  131. package/public/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  132. package/public/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  133. package/public/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  134. package/public/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  135. package/public/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  136. package/public/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  137. package/public/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  138. package/public/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  139. package/public/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  140. package/public/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  141. package/public/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  142. package/public/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  143. package/public/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  144. package/public/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  145. package/public/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  146. package/public/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  147. package/public/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  148. package/public/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  149. package/public/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  150. package/public/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  151. package/public/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  152. package/public/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  153. package/public/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  154. package/public/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  155. package/public/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  156. package/public/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  157. package/public/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  158. package/public/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  159. package/public/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  160. package/public/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  161. package/public/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  162. package/public/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  163. package/public/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  164. package/public/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  165. package/public/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  166. package/public/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  167. package/public/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  168. package/public/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  169. package/public/pdfjs/cmaps/V.bcmap +0 -0
  170. package/public/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  171. package/public/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  172. package/public/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  173. package/public/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  174. package/public/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  175. package/public/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  176. package/public/pdfjs/standard_fonts/FoxitSans.pfb +0 -0
  177. package/public/pdfjs/standard_fonts/FoxitSansBold.pfb +0 -0
  178. package/public/pdfjs/standard_fonts/FoxitSansBoldItalic.pfb +0 -0
  179. package/public/pdfjs/standard_fonts/FoxitSansItalic.pfb +0 -0
  180. package/public/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  181. package/public/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  182. package/public/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  183. package/public/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  184. package/public/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  185. package/public/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  186. package/public/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
  187. package/public/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  188. package/public/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  189. package/public/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  190. package/public/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  191. package/src/components/preview/pdfView.vue +189 -224
@@ -88,7 +88,8 @@ export default {
88
88
  pdf: null,
89
89
  numPages: 0,
90
90
  scale: 1, // 初始缩小比例
91
- pages: [], // { pageNumber: number, loaded: boolean, canvas: ref, loading: boolean, retryCount: number }
91
+ renderInProgress: false,
92
+ pages: [], // { pageNumber: number, loaded: boolean, canvas: ref, loading: boolean }
92
93
  // 静态高亮(坐标采用顶部为原点)
93
94
  highlights: [],
94
95
  searchQuery: "",
@@ -165,7 +166,12 @@ export default {
165
166
  if (!this.pdfFile) return;
166
167
  this.pdfFile = setTimestamp(this.pdfFile)
167
168
  // this.pdf = await pdfjsLib.getDocument(this.pdfFile).promise;
168
- this.loadingTask = pdfjsLib.getDocument(this.pdfFile);
169
+ this.loadingTask = pdfjsLib.getDocument({
170
+ url: this.pdfFile,
171
+ cMapUrl: "/pdfjs/cmaps/",
172
+ cMapPacked: true,
173
+ standardFontDataUrl: "/pdfjs/standard_fonts/",
174
+ });
169
175
  await this.loadingTask.promise.then(async pdf => {
170
176
  // 获取PDF的第一页
171
177
  this.pdf = pdf;
@@ -178,22 +184,28 @@ export default {
178
184
  loaded: false,
179
185
  canvas: null,
180
186
  loading: false,
181
- retryCount: 0,
182
187
  }));
183
188
  // 清空搜索高亮
184
189
  this.searchHighlights = [];
185
190
  this.searchTermCount = 0;
186
191
  this.currentSearchIndex = 0;
187
- setTimeout(async () => {
188
- await this.setCanvasRef();
189
- },100)
192
+ // 确保 DOM 更新完成后再设置 canvas 引用
193
+ await this.$nextTick();
194
+ await this.setCanvasRef();
195
+ }).catch(error => {
196
+ console.error('PDF 加载失败:', error);
190
197
  })
191
198
 
192
199
  },
193
200
  async loadPdf() {
194
201
  if (!this.pdfFile) return;
195
202
  await this.initPdf();
196
- this.initObserver();
203
+ // 确保 canvas 引用设置完成后再初始化观察器
204
+ await this.$nextTick();
205
+ // 延迟初始化观察器,确保所有 canvas 都已准备好
206
+ setTimeout(() => {
207
+ this.initObserver();
208
+ }, 200);
197
209
  },
198
210
  initObserver(type) {
199
211
  if (this.observer) {
@@ -206,7 +218,7 @@ export default {
206
218
  const index = Number(entry.target.getAttribute('data-index'));
207
219
  const page = this.pages[index];
208
220
  if (page && !page.loaded && !page.loading) {
209
- this.renderPage(page.pageNumber);
221
+ this.renderPage(page.pageNumber);
210
222
  }
211
223
  this.updateCurrentPage();
212
224
  }
@@ -218,7 +230,9 @@ export default {
218
230
  threshold: 0.1,
219
231
  }
220
232
  );
221
- this.$nextTick( () => {
233
+ // 确保 canvas 引用都已设置好后再开始观察
234
+ this.$nextTick(() => {
235
+ // 增加延迟确保所有 canvas 引用都已设置
222
236
  setTimeout(() => {
223
237
  this.pages.forEach((page, index) => {
224
238
  const canvas = page.canvas;
@@ -227,7 +241,7 @@ export default {
227
241
  this.observer.observe(canvas);
228
242
  }
229
243
  });
230
- },300)
244
+ },500)
231
245
  if (type !== 'changeScale' && type !== 'onResize'){
232
246
  setTimeout(async () => {
233
247
  let currentPage = this.split_paragraphs.length > 0 ? this.split_paragraphs[0] : null;
@@ -250,195 +264,161 @@ export default {
250
264
  await this.updateCurrentPage();
251
265
  }
252
266
  },
253
- async renderPage(pageNumber, retry = false) {
267
+ async renderPage(pageNumber) {
254
268
  if (!this.pdf) return;
255
269
  const pageIndex = pageNumber - 1;
256
270
  const pageData = this.pages[pageIndex];
257
271
  if (!pageData) return;
258
-
259
- // 如果正在加载且不是重试,避免重复渲染
260
- if (pageData.loading && !retry) return;
261
- // 如果已加载且不是重试,直接返回
262
- if (pageData.loaded && !retry) return;
263
-
264
- // 重试机制:最多重试 3 次
265
- const maxRetries = 3;
266
- if (retry && pageData.retryCount >= maxRetries) {
267
- console.error(`Max retries reached for page ${pageNumber}`);
268
- this.$set(pageData, 'loading', false);
269
- return;
270
- }
271
-
272
+ // 如果已经在加载或已加载,避免重复渲染
273
+ if (pageData.loaded || pageData.loading) return;
274
+
272
275
  this.pageNumber = pageNumber;
273
-
276
+
274
277
  try {
278
+ // 标记为加载中,防止重复渲染
279
+ this.$set(pageData, 'loading', true);
280
+
275
281
  const page = await this.pdf.getPage(pageNumber);
276
- let pdfWidth = page.getViewport({ scale: 1}).width;
282
+ let pdfWidth = page.getViewport({ scale: 1 }).width;
277
283
  const viewport = page.getViewport({ scale: this.calculateScale(pdfWidth) });
278
284
  this.viewport = viewport;
279
-
285
+
280
286
  const canvas = pageData.canvas;
281
287
  if (!canvas) {
282
- console.warn(`Canvas not found for page ${pageNumber}, will retry...`);
283
- // 如果 canvas 不存在,增加重试计数并延迟重试
284
- if (!retry) {
285
- this.$set(pageData, 'retryCount', (pageData.retryCount || 0) + 1);
286
- setTimeout(() => {
287
- this.renderPage(pageNumber, true);
288
- }, 200);
289
- }
288
+ console.warn(`页面 ${pageNumber} 的 canvas 引用不存在`);
289
+ this.$set(pageData, 'loading', false);
290
290
  return;
291
291
  }
292
292
 
293
293
  const context = canvas.getContext("2d");
294
294
  if (!context) {
295
- console.warn(`Failed to get context for page ${pageNumber}, will retry...`);
296
- // 如果无法获取 context,增加重试计数并延迟重试
297
- if (!retry) {
298
- this.$set(pageData, 'retryCount', (pageData.retryCount || 0) + 1);
299
- setTimeout(() => {
300
- this.renderPage(pageNumber, true);
301
- }, 200);
302
- }
295
+ console.warn(`页面 ${pageNumber} 无法获取 canvas context`);
296
+ this.$set(pageData, 'loading', false);
303
297
  return;
304
298
  }
305
-
299
+
306
300
  this.context = context;
307
- const devicePixelRatio = window.devicePixelRatio || 1;
308
- canvas.width = (viewport.width) * devicePixelRatio;
309
- canvas.height = viewport.height * devicePixelRatio;
310
- canvas.style.width = `${viewport.width}px`;
311
- canvas.style.height = `${viewport.height}px`;
312
- context.scale(devicePixelRatio, devicePixelRatio);
313
-
314
- // 设置加载状态
315
- this.$set(pageData, 'loading', true);
316
-
317
- // 清理旧的文本层
301
+
302
+ // 计算输出缩放比例(与 vuePdf 保持一致)
303
+ const outputScale = this.calculateScale(pdfWidth);
304
+
305
+ // 计算实际显示的尺寸
306
+ let domWidth = Math.floor(viewport.width);
307
+ let domHeight = Math.floor(viewport.height);
308
+
309
+ // 设置 canvas 尺寸(与 vuePdf 保持一致,使用 outputScale)
310
+ // 注意:vuePdf 不使用 devicePixelRatio,为了保持一致,我们也只使用 outputScale
311
+ canvas.width = Math.floor(viewport.width * outputScale);
312
+ canvas.height = Math.floor(viewport.height * outputScale);
313
+ canvas.style.width = `${domWidth}px`;
314
+ canvas.style.height = `${domHeight}px`;
315
+
316
+ // 创建 transform 矩阵(与 vuePdf 保持一致)
317
+ const transform = outputScale !== 1
318
+ ? [outputScale, 0, 0, outputScale, 0, 0]
319
+ : null;
320
+
321
+ // 清除旧的文本层
318
322
  let hasDoc = document.getElementById('textLayer' + pageNumber);
319
- if (hasDoc && hasDoc.parentNode) {
323
+ if (hasDoc) {
320
324
  hasDoc.parentNode.removeChild(hasDoc);
321
325
  }
322
-
323
- // 渲染 PDF 页面
324
- const renderTask = page.render({ canvasContext: context, viewport });
325
-
326
- // 等待渲染完成后再处理文本层和高亮
327
- await renderTask.promise.then(async () => {
328
- // 获取文本内容
326
+
327
+ // 渲染 PDF 页面到 canvas(传入 transform 确保正确渲染)
328
+ const renderTask = page.render({
329
+ canvasContext: context,
330
+ viewport: viewport,
331
+ transform: transform
332
+ });
333
+ await renderTask.promise;
334
+
335
+ // 渲染文本层(必须在高亮渲染之前,确保文本层在最上层)
336
+ try {
329
337
  const textContent = await page.getTextContent();
330
-
331
- // 创建文本层
332
338
  const textDiv = document.createElement('div');
333
339
  textDiv.setAttribute('class', 'textLayer');
334
340
  textDiv.setAttribute('id', 'textLayer' + pageNumber);
341
+ // 关键:TextLayerBuilder 也需要传入 transform,确保文本位置正确
335
342
  let textLayer = new TextLayerBuilder({
336
343
  textLayerDiv: textDiv,
337
344
  pageIndex: pageIndex,
338
345
  viewport: viewport,
346
+ transform: transform, // 添加 transform 参数
339
347
  });
340
-
341
- // 设置文本层样式 - 移除高度限制和 overflow hidden,避免文字被裁剪
342
- textDiv.style.width = `${viewport.width}px`;
343
- // 不设置固定高度,让内容自然展开,或者设置为足够大的值
344
- // textDiv.style.height = `${viewport.height}px`; // 移除固定高度
345
- textDiv.style.minHeight = `${viewport.height}px`; // 使用最小高度
346
- textDiv.style.overflow = 'visible'; // 改为 visible,避免裁剪文字
348
+ // 使用 domWidth 和 domHeight(与 vuePdf 保持一致)
349
+ textDiv.style.width = `${domWidth}px`;
350
+ textDiv.style.height = `${domHeight}px`;
351
+ // 使用 hidden 但确保尺寸正确(与 vuePdf 保持一致)
352
+ textDiv.style.overflow = 'hidden';
347
353
  textDiv.style.whiteSpace = 'pre-wrap';
348
354
  textDiv.style.position = 'absolute';
349
355
  textDiv.style.top = '0';
350
356
  textDiv.style.left = '0';
351
357
  textDiv.style.fontSize = '20px';
352
358
  textDiv.style.color = 'black';
353
- textDiv.style.pointerEvents = 'none'; // 确保文本层不阻挡交互
354
-
355
- // 将文本 div 先添加到覆盖层中(TextLayerBuilder 需要 DOM 元素存在)
356
- let pagesDiv = document.getElementById('canvas-wrapper' + pageIndex);
357
- if (!pagesDiv) {
358
- console.warn(`Canvas wrapper not found for page ${pageNumber}`);
359
- return;
360
- }
361
- pagesDiv.appendChild(textDiv);
362
-
363
- // 设置文本内容并渲染
364
359
  textLayer.setTextContent(textContent);
365
360
  textLayer.render();
366
-
367
- // 等待文本层渲染完成(使用 nextTick 和 setTimeout 确保 DOM 完全更新)
361
+
362
+ // 渲染完成后,检查文本层实际内容高度,如果超出则调整
368
363
  await this.$nextTick();
369
- // 额外等待一小段时间,确保 TextLayerBuilder 完成渲染
370
- await new Promise(resolve => setTimeout(resolve, 50));
371
-
372
- // 确保容器有足够的高度来显示所有文本
373
- // 获取文本层的实际高度(包括所有子元素)
374
- const textLayerHeight = Math.max(
375
- textDiv.scrollHeight,
376
- textDiv.offsetHeight,
377
- viewport.height
378
- );
379
-
380
- // 如果文本层实际高度超过 viewport,调整容器和 canvas 的高度
381
- if (textLayerHeight > viewport.height) {
382
- // 调整 canvas wrapper 的最小高度
383
- if (pagesDiv) {
384
- pagesDiv.style.minHeight = `${textLayerHeight}px`;
385
- }
386
- // 调整 canvas 的显示高度(如果需要)
387
- const canvas = pageData.canvas;
388
- if (canvas && canvas.parentElement) {
389
- canvas.parentElement.style.minHeight = `${textLayerHeight}px`;
364
+ const textLayerSpans = textDiv.querySelectorAll('span');
365
+ if (textLayerSpans.length > 0) {
366
+ let maxBottom = 0;
367
+ textLayerSpans.forEach(span => {
368
+ const rect = span.getBoundingClientRect();
369
+ const parentRect = textDiv.getBoundingClientRect();
370
+ const relativeBottom = rect.bottom - parentRect.top;
371
+ if (relativeBottom > maxBottom) {
372
+ maxBottom = relativeBottom;
373
+ }
374
+ });
375
+ // 如果文本内容超出当前高度,增加文本层高度(增加一些边距)
376
+ if (maxBottom > domHeight) {
377
+ textDiv.style.height = `${Math.ceil(maxBottom + 10)}px`;
390
378
  }
391
379
  }
392
-
393
- // 在文本层渲染完成后,再渲染高亮区域
394
- // 注意:高亮是在 canvas 上绘制的,不会遮挡文本层(文本层在 canvas 上方)
395
- // 渲染已有高亮区域(静态highlights)
396
- this.renderHighlights(context, pageNumber, viewport);
397
- // 渲染搜索高亮区域
398
- this.renderSearchHighlights(context, pageNumber, viewport);
399
-
400
- // 重置重试计数
401
- this.$set(pageData, 'retryCount', 0);
402
- // 更新页面状态
403
- this.$set(pageData, 'loading', false);
404
- this.$set(pageData, 'loaded', true);
405
- }).catch((error) => {
406
- console.error(`Error rendering page ${pageNumber}:`, error);
407
- // 如果渲染失败,尝试重试
408
- if (!retry && (pageData.retryCount || 0) < maxRetries) {
409
- this.$set(pageData, 'retryCount', (pageData.retryCount || 0) + 1);
410
- this.$set(pageData, 'loading', false);
411
- // 延迟后重试
412
- setTimeout(() => {
413
- this.renderPage(pageNumber, true);
414
- }, 500);
415
- } else {
416
- // 确保在错误时也更新状态
417
- this.$set(pageData, 'loading', false);
418
- this.$set(pageData, 'loaded', false);
380
+
381
+ // 将文本 div 添加到覆盖层中
382
+ let pagesDiv = document.getElementById('canvas-wrapper' + pageIndex);
383
+ if (pagesDiv) {
384
+ pagesDiv.appendChild(textDiv);
419
385
  }
420
- });
421
- } catch (error) {
422
- console.error(`Error loading page ${pageNumber}:`, error);
423
- // 如果加载失败,尝试重试
424
- if (!retry && (pageData.retryCount || 0) < maxRetries) {
425
- this.$set(pageData, 'retryCount', (pageData.retryCount || 0) + 1);
426
- this.$set(pageData, 'loading', false);
427
- // 延迟后重试
428
- setTimeout(() => {
429
- this.renderPage(pageNumber, true);
430
- }, 500);
431
- } else {
432
- this.$set(pageData, 'loading', false);
433
- this.$set(pageData, 'loaded', false);
386
+ } catch (textError) {
387
+ console.warn(`页面 ${pageNumber} 文本层渲染失败:`, textError);
388
+ // 文本层渲染失败不影响页面继续渲染
434
389
  }
390
+
391
+ // 渲染已有高亮区域(静态highlights)
392
+ // 注意:高亮是在 canvas 上绘制的,不会覆盖文本层(文本层在 canvas 上方)
393
+ // 需要传入 outputScale,因为 canvas 使用了 transform 渲染
394
+ try {
395
+ this.renderHighlights(context, pageNumber, viewport, outputScale);
396
+ } catch (highlightError) {
397
+ console.warn(`页面 ${pageNumber} 高亮渲染失败:`, highlightError);
398
+ }
399
+
400
+ // 渲染搜索高亮区域
401
+ try {
402
+ this.renderSearchHighlights(context, pageNumber, viewport, outputScale);
403
+ } catch (searchHighlightError) {
404
+ console.warn(`页面 ${pageNumber} 搜索高亮渲染失败:`, searchHighlightError);
405
+ }
406
+
407
+ // 标记为已加载
408
+ this.$set(pageData, 'loading', false);
409
+ this.$set(pageData, 'loaded', true);
410
+ } catch (error) {
411
+ console.error(`页面 ${pageNumber} 渲染失败:`, error);
412
+ // 渲染失败时重置状态,允许重试
413
+ this.$set(pageData, 'loading', false);
414
+ this.$set(pageData, 'loaded', false);
435
415
  }
436
416
  },
437
417
  calculateScale(pdfWidth) {
438
418
  const containerWidth = document.getElementById('pdfViewPage').clientWidth - 50;
439
419
  return (containerWidth / pdfWidth) * this.scale;
440
420
  },
441
- async renderHighlights(context, number,viewport) {
421
+ async renderHighlights(context, number, viewport, outputScale = 1) {
442
422
  const pageHighlights = this.highlights.filter(item => (item.page === number ))
443
423
  let highlights = this.mergedGroups(pageHighlights);
444
424
  this.mergedGroupsList = this.mergedGroupsList.concat(highlights)
@@ -452,63 +432,60 @@ export default {
452
432
  groups.push(position.slice(i, i + 4));
453
433
  }
454
434
  for (let i = 0;i<groups.length;i++){
455
- this.drawHighlight(context, viewport, groups[i], fillStyle, false);
435
+ this.drawHighlight(context, viewport, groups[i], fillStyle, false, outputScale);
456
436
  }
457
437
  });
458
438
  }
459
439
  },
460
- renderSearchHighlights(context, pageNumber, viewport) {
440
+ renderSearchHighlights(context, pageNumber, viewport, outputScale = 1) {
461
441
  const pageHighlights = this.searchHighlights.filter(h => h.pageNumber === pageNumber);
462
442
  pageHighlights.forEach(({ position }) => {
463
- this.drawHighlight(context, viewport, position, "rgba(255, 255, 0, 0.4)", true);
443
+ this.drawHighlight(context, viewport, position, "rgba(255, 255, 0, 0.4)", true, outputScale);
464
444
  });
465
445
  },
466
- drawHighlight(context, viewport, position, fillStyle, fromSearch = false) {
467
- if (!context || !position || position.length < 4) return;
468
-
446
+ drawHighlight(context, viewport, position, fillStyle, fromSearch = false, outputScale = 1) {
469
447
  const [x1, y1, x2, y2] = position;
448
+ // 使用 viewport.scale 计算 PDF 坐标到 viewport 坐标的转换
470
449
  const scale = viewport.scale;
450
+ // PDF 页面的实际高度(未缩放)
471
451
  const pageHeight = viewport.height / viewport.scale;
472
452
 
473
- let canvasX1 = x1 * scale;
474
- let canvasX2 = x2 * scale;
475
- let canvasY1, canvasY2;
453
+ // 计算在 viewport 坐标系中的位置(PDF 坐标 → viewport 坐标)
454
+ let viewportX1 = x1 * scale;
455
+ let viewportX2 = x2 * scale;
456
+ let viewportY1, viewportY2;
476
457
 
477
458
  if (fromSearch) {
478
- // 搜索高亮:PDF坐标系(左下原点)
479
- canvasY1 = (pageHeight - y1) * scale;
480
- canvasY2 = (pageHeight - y2) * scale;
459
+ // 搜索高亮:PDF坐标系(左下原点),需要转换为顶部原点
460
+ viewportY1 = (pageHeight - y1) * scale;
461
+ viewportY2 = (pageHeight - y2) * scale;
481
462
  } else {
482
- // 静态 highlights 假设顶部坐标原点不需翻转
483
- canvasY1 = y1 * scale;
484
- canvasY2 = y2 * scale;
463
+ // 静态 highlights:顶部坐标原点,直接使用
464
+ viewportY1 = y1 * scale;
465
+ viewportY2 = y2 * scale;
485
466
  }
486
467
 
487
- // 确保坐标在有效范围内
488
- const minX = Math.min(canvasX1, canvasX2);
489
- const minY = Math.min(canvasY1, canvasY2);
490
- const width = Math.abs(canvasX2 - canvasX1);
491
- const height = Math.abs(canvasY2 - canvasY1);
468
+ // 由于 canvas 使用了 transform 渲染,PDF.js 会在内部应用 transform
469
+ // 但 context 的坐标系统是 canvas 的实际尺寸(viewport.width * outputScale)
470
+ // 而 viewport 坐标是基于 viewport.width 的,所以需要转换为 canvas 坐标
471
+ // 注意:outputScale 和 viewport.scale 是相同的值,所以这里只需要乘以 outputScale
472
+ // 但实际上 viewport.scale 已经应用了,所以这里应该直接使用 viewport 坐标
473
+ // 但 canvas 的实际尺寸是 viewport.width * outputScale,所以需要缩放
474
+ let canvasX1 = viewportX1 * outputScale;
475
+ let canvasX2 = viewportX2 * outputScale;
476
+ let canvasY1 = viewportY1 * outputScale;
477
+ let canvasY2 = viewportY2 * outputScale;
492
478
 
493
- // 检查坐标是否在 canvas 范围内
494
- if (minX < 0 || minY < 0 || minX + width > viewport.width || minY + height > viewport.height) {
495
- // 如果超出范围,进行裁剪
496
- const clippedX = Math.max(0, minX);
497
- const clippedY = Math.max(0, minY);
498
- const clippedWidth = Math.min(width, viewport.width - clippedX);
499
- const clippedHeight = Math.min(height, viewport.height - clippedY);
500
-
501
- if (clippedWidth > 0 && clippedHeight > 0) {
502
- context.beginPath();
503
- context.fillStyle = fillStyle;
504
- context.fillRect(clippedX, clippedY, clippedWidth, clippedHeight);
505
- }
506
- } else {
507
- // 正常绘制
508
- context.beginPath();
509
- context.fillStyle = fillStyle;
510
- context.fillRect(minX, minY, width, height);
511
- }
479
+ // 清除当前路径
480
+ context.beginPath();
481
+
482
+ context.fillStyle = fillStyle;
483
+ context.fillRect(
484
+ Math.min(canvasX1, canvasX2),
485
+ Math.min(canvasY1, canvasY2),
486
+ Math.abs(canvasX2 - canvasX1),
487
+ Math.abs(canvasY2 - canvasY1)
488
+ );
512
489
  },
513
490
  handleFileUpload(event) {
514
491
  const file = event.target.files[0];
@@ -519,27 +496,26 @@ export default {
519
496
  }
520
497
  },
521
498
  async setCanvasRef() {
522
- // 使用 $nextTick 确保 DOM 已更新
499
+ // 等待 DOM 完全更新
523
500
  await this.$nextTick();
524
-
525
- // 如果 refs 还没有准备好,等待一段时间后重试
526
- if (!this.$refs.canvases || this.$refs.canvases.length === 0) {
527
- return new Promise((resolve) => {
528
- setTimeout(async () => {
529
- await this.setCanvasRef();
530
- resolve();
531
- }, 100);
532
- });
501
+
502
+ if (!this.$refs.canvases || !Array.isArray(this.$refs.canvases)) {
503
+ console.warn('Canvas 引用未准备好,延迟重试');
504
+ // 如果 canvas 引用还没准备好,延迟重试
505
+ setTimeout(() => {
506
+ this.setCanvasRef();
507
+ }, 100);
508
+ return;
533
509
  }
534
-
535
- // 设置 canvas 引用
536
- this.pages.forEach((page, index) => {
510
+
511
+ // 确保所有 canvas 引用都已设置
512
+ for (let index = 0; index < this.pages.length; index++) {
537
513
  if (this.$refs.canvases && this.$refs.canvases[index]) {
538
514
  this.$set(this.pages[index], 'canvas', this.$refs.canvases[index]);
539
515
  } else {
540
- console.warn(`Canvas ref not found for page ${index + 1}`);
516
+ console.warn(`页面 ${index + 1} 的 canvas 引用不存在`);
541
517
  }
542
- });
518
+ }
543
519
  },
544
520
  clearPages() {
545
521
  this.pages = [];
@@ -621,8 +597,7 @@ export default {
621
597
  zoomIn() {
622
598
  this.updateCurrentPage();
623
599
  // 检查是否有页面正在加载
624
- const hasLoadingPage = this.pages.some(p => p.loading);
625
- if (hasLoadingPage) return;
600
+ if (this.pages.some(p => p.loading)) return;
626
601
  const container = this.$refs.pdfContainer;
627
602
  const currentScroll = container.scrollTop;
628
603
  this.scale += 0.1;
@@ -631,8 +606,7 @@ export default {
631
606
  zoomOut() {
632
607
  this.updateCurrentPage();
633
608
  // 检查是否有页面正在加载
634
- const hasLoadingPage = this.pages.some(p => p.loading);
635
- if (hasLoadingPage) return;
609
+ if (this.pages.some(p => p.loading)) return;
636
610
  const container = this.$refs.pdfContainer;
637
611
  const currentScroll = container.scrollTop;
638
612
  this.scale = Math.max(this.scale - 0.1, 0.1);
@@ -642,11 +616,10 @@ export default {
642
616
  const pages = Vue.observable(this.pages)
643
617
  pages.forEach((p) => {
644
618
  p.loaded = false;
645
- this.$set(p, 'loading', false);
646
- this.$set(p, 'retryCount', 0);
619
+ this.$set(p,'loading',false)
647
620
  if (p.canvas) {
648
621
  const ctx = p.canvas.getContext('2d');
649
- ctx.clearRect(0, 0, p.canvas.width, p.canvas.height);
622
+ ctx.clearRect(0,0,p.canvas.width,p.canvas.height);
650
623
  }
651
624
  });
652
625
 
@@ -679,8 +652,7 @@ export default {
679
652
  async doSearch() {
680
653
  if (!this.pdf || !this.searchQuery) return;
681
654
  // 检查是否有页面正在加载
682
- const hasLoadingPage = this.pages.some(p => p.loading);
683
- if (hasLoadingPage) return;
655
+ if (this.pages.some(p => p.loading)) return;
684
656
 
685
657
  this.searchHighlights = [];
686
658
  const numPages = this.numPages;
@@ -743,8 +715,7 @@ export default {
743
715
  const currentScroll = container.scrollTop;
744
716
  this.pages.forEach((p) => {
745
717
  p.loaded = false;
746
- this.$set(p, 'loading', false);
747
- this.$set(p, 'retryCount', 0);
718
+ this.$set(p,'loading',false)
748
719
  if (p.canvas) {
749
720
  const ctx = p.canvas.getContext("2d");
750
721
  ctx.clearRect(0, 0, p.canvas.width, p.canvas.height);
@@ -775,18 +746,16 @@ export default {
775
746
  clearTimeout(this.resizeTimeout);
776
747
  this.resizeTimeout = setTimeout(() => {
777
748
  // 检查是否有页面正在加载
778
- const hasLoadingPage = this.pages.some(p => p.loading);
779
- if (hasLoadingPage) return;
749
+ if (this.pages.some(p => p.loading)) return;
780
750
  const container = this.$refs.pdfContainer;
781
751
  const currentScroll = container.scrollTop;
782
752
  const pages = Vue.observable(this.pages)
783
753
  pages.forEach((p) => {
784
754
  p.loaded = false;
785
- this.$set(p, 'loading', false);
786
- this.$set(p, 'retryCount', 0);
755
+ this.$set(p,'loading',false)
787
756
  if (p.canvas) {
788
757
  const ctx = p.canvas.getContext('2d');
789
- ctx.clearRect(0, 0, p.canvas.width, p.canvas.height);
758
+ ctx.clearRect(0,0,p.canvas.width,p.canvas.height);
790
759
  }
791
760
  });
792
761
  this.$nextTick(() => {
@@ -804,7 +773,7 @@ export default {
804
773
  console.log('ossPath',this.ossPath)
805
774
  // this.clearPages();
806
775
  // this.loadPdf();
807
- if (this.textWatermarkStr){
776
+ if (this.textWatermarkStr){ge
808
777
  newInitWaterMark('pdfViewPage', this.textWatermarkStr)
809
778
  }
810
779
  },
@@ -874,15 +843,11 @@ export default {
874
843
  display: flex;
875
844
  justify-content: center;
876
845
  width: 100%;
877
- min-height: fit-content; /* 确保容器能容纳所有内容 */
878
- overflow: visible; /* 允许内容超出,避免裁剪 */
879
846
  }
880
847
 
881
848
  .canvas-wrapper {
882
849
  position: relative;
883
850
  width: 100%;
884
- min-height: 100%; /* 确保容器有足够高度 */
885
- overflow: visible; /* 允许内容超出,避免裁剪 */
886
851
  }
887
852
 
888
853
  /* 在loading时覆盖canvas显示加载动画 */