@koi-br/ocr-web-sdk 1.0.37 → 1.0.38

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koi-br/ocr-web-sdk",
3
- "version": "1.0.37",
3
+ "version": "1.0.38",
4
4
  "description": "一个支持多种Office文件格式预览的Vue3组件SDK,包括PDF、Word、Excel、图片、OFD、TIF等格式",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -116,7 +116,17 @@
116
116
  @mouseleave="stopPan"
117
117
  @scroll="handleScroll"
118
118
  >
119
- <div class="image-wrapper-container" :style="containerStyle">
119
+ <!-- 自适应宽度计算 Loading -->
120
+ <div v-if="isCalculatingAutoFit && autoFitWidth" class="auto-fit-loading">
121
+ <div class="loading-spinner"></div>
122
+ <div class="loading-text">加载中...</div>
123
+ </div>
124
+
125
+ <div
126
+ class="image-wrapper-container"
127
+ :style="containerStyle"
128
+ :class="{ 'image-hidden': !isImageReady && autoFitWidth }"
129
+ >
120
130
  <!-- 渲染所有图片页面 -->
121
131
  <div
122
132
  v-for="(imageUrl, pageIndex) in imageUrls"
@@ -390,6 +400,24 @@ const position = ref({ x: 0, y: 0 });
390
400
  const isPanning = ref(false);
391
401
  const lastPosition = ref({ x: 0, y: 0 });
392
402
  const initialAutoFitScale = ref<number | null>(null); // 记录初始自适应缩放比例
403
+ const isCalculatingAutoFit = ref(false); // 标记是否正在计算自适应宽度(显示 loading)
404
+ const isImageReady = ref(false); // 标记图片是否已准备好显示(自适应宽度计算完成)
405
+
406
+ // 监听图片URL变化,当有新图片时立即隐藏(等待自适应宽度计算)
407
+ watch(
408
+ () => imageUrls.value,
409
+ (newUrls, oldUrls) => {
410
+ // 如果有新的图片URL,且启用自适应宽度,立即隐藏图片
411
+ if (newUrls && newUrls.length > 0 && props.autoFitWidth) {
412
+ isImageReady.value = false;
413
+ isCalculatingAutoFit.value = true;
414
+ } else if (!props.autoFitWidth) {
415
+ // 如果没有启用自适应宽度,立即显示
416
+ isImageReady.value = true;
417
+ }
418
+ },
419
+ { immediate: true }
420
+ );
393
421
  const isUserZooming = ref(false); // 标记用户是否主动缩放
394
422
 
395
423
  // 滚动翻页相关
@@ -938,6 +966,10 @@ const onImageLoad = (event: Event, pageNum: number) => {
938
966
  if (pageNum === 1 && props.autoFitWidth) {
939
967
  // 重置用户缩放标记
940
968
  isUserZooming.value = false;
969
+
970
+ // 隐藏图片,显示 loading
971
+ isImageReady.value = false;
972
+ isCalculatingAutoFit.value = true;
941
973
 
942
974
  // 使用双重 nextTick 确保容器尺寸已确定
943
975
  nextTick(() => {
@@ -949,9 +981,18 @@ const onImageLoad = (event: Event, pageNum: number) => {
949
981
  scale.value = autoScale;
950
982
  initialAutoFitScale.value = autoScale; // 记录初始自适应缩放比例
951
983
  }
984
+ // 计算完成后,显示图片并隐藏 loading
985
+ isCalculatingAutoFit.value = false;
986
+ // 使用 requestAnimationFrame 确保在下一帧显示,避免闪烁
987
+ requestAnimationFrame(() => {
988
+ isImageReady.value = true;
989
+ });
952
990
  }, 100); // 增加延迟,确保所有图片都已加载
953
991
  });
954
992
  });
993
+ } else if (!props.autoFitWidth) {
994
+ // 如果没有启用自适应宽度,立即显示图片
995
+ isImageReady.value = true;
955
996
  }
956
997
 
957
998
  // 如果第一页已经加载完成,且当前页不是第一页,也应用自适应宽度
@@ -2270,6 +2311,10 @@ const handleContainerResize = () => {
2270
2311
  resizeTimer = null;
2271
2312
  }
2272
2313
 
2314
+ // 隐藏图片,显示 loading
2315
+ isImageReady.value = false;
2316
+ isCalculatingAutoFit.value = true;
2317
+
2273
2318
  // 立即计算并应用新的缩放比例,避免过渡期间露出底色
2274
2319
  // 使用 requestAnimationFrame 确保在浏览器重绘前更新
2275
2320
  requestAnimationFrame(() => {
@@ -2287,6 +2332,11 @@ const handleContainerResize = () => {
2287
2332
  scale.value = finalScale;
2288
2333
  initialAutoFitScale.value = finalScale;
2289
2334
  }
2335
+ // 计算完成后,显示图片并隐藏 loading
2336
+ isCalculatingAutoFit.value = false;
2337
+ requestAnimationFrame(() => {
2338
+ isImageReady.value = true;
2339
+ });
2290
2340
  }, 350); // 350ms 延迟,略大于过渡动画时间(300ms),确保过渡完成后稳定
2291
2341
  });
2292
2342
  };
@@ -2300,6 +2350,9 @@ onMounted(() => {
2300
2350
  if (firstPageImage && firstPageImage.complete && props.autoFitWidth) {
2301
2351
  const firstPageSize = imageSizes.get(1);
2302
2352
  if (firstPageSize && firstPageSize.width > 0) {
2353
+ // 隐藏图片,显示 loading
2354
+ isImageReady.value = false;
2355
+ isCalculatingAutoFit.value = true;
2303
2356
  nextTick(() => {
2304
2357
  nextTick(() => {
2305
2358
  setTimeout(() => {
@@ -2308,10 +2361,18 @@ onMounted(() => {
2308
2361
  scale.value = autoScale;
2309
2362
  initialAutoFitScale.value = autoScale;
2310
2363
  }
2364
+ // 计算完成后,显示图片并隐藏 loading
2365
+ isCalculatingAutoFit.value = false;
2366
+ requestAnimationFrame(() => {
2367
+ isImageReady.value = true;
2368
+ });
2311
2369
  }, 100);
2312
2370
  });
2313
2371
  });
2314
2372
  }
2373
+ } else if (!props.autoFitWidth) {
2374
+ // 如果没有启用自适应宽度,立即显示图片
2375
+ isImageReady.value = true;
2315
2376
  }
2316
2377
 
2317
2378
  // 监听容器尺寸变化(用于响应外部收起/展开操作)
@@ -2381,6 +2442,47 @@ defineExpose({
2381
2442
  overflow: auto;
2382
2443
  }
2383
2444
 
2445
+ // 自适应宽度计算 Loading
2446
+ .auto-fit-loading {
2447
+ position: absolute;
2448
+ top: 50%;
2449
+ left: 50%;
2450
+ transform: translate(-50%, -50%);
2451
+ z-index: 1000;
2452
+ display: flex;
2453
+ flex-direction: column;
2454
+ align-items: center;
2455
+ gap: 12px;
2456
+ padding: 20px 30px;
2457
+ }
2458
+
2459
+ .loading-spinner {
2460
+ width: 32px;
2461
+ height: 32px;
2462
+ border: 3px solid #e5e7eb;
2463
+ border-top-color: #1890ff;
2464
+ border-radius: 50%;
2465
+ animation: spin 0.8s linear infinite;
2466
+ }
2467
+
2468
+ @keyframes spin {
2469
+ to {
2470
+ transform: rotate(360deg);
2471
+ }
2472
+ }
2473
+
2474
+ .loading-text {
2475
+ font-size: 14px;
2476
+ color: #666;
2477
+ white-space: nowrap;
2478
+ }
2479
+
2480
+ // 图片隐藏状态(自适应宽度计算完成前)
2481
+ // 使用 display: none 确保图片完全不可见,不会在加载过程中显示
2482
+ .image-wrapper-container.image-hidden {
2483
+ display: none !important;
2484
+ }
2485
+
2384
2486
  // 页码信息样式
2385
2487
  .page-info {
2386
2488
  display: inline-flex;