@koi-br/ocr-web-sdk 1.0.28 → 1.0.29

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.
@@ -1,4 +1,4 @@
1
- import { g as getAugmentedNamespace, a as getDefaultExportFromCjs } from "./index-BUW0_Hv2.mjs";
1
+ import { g as getAugmentedNamespace, a as getDefaultExportFromCjs } from "./index-QOLKOKLO.mjs";
2
2
  function _mergeNamespaces(U, W) {
3
3
  for (var Z = 0; Z < W.length; Z++) {
4
4
  const s0 = W[Z];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koi-br/ocr-web-sdk",
3
- "version": "1.0.28",
3
+ "version": "1.0.29",
4
4
  "description": "一个支持多种Office文件格式预览的Vue3组件SDK,包括PDF、Word、Excel、图片、OFD、TIF等格式",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -426,12 +426,18 @@ const imageSize = computed({
426
426
  });
427
427
 
428
428
  // 计算图片放大后的实际尺寸(考虑旋转)
429
+ // 在自适应宽度模式下,使用第一页的尺寸;否则使用当前页的尺寸
429
430
  const scaledImageSize = computed(() => {
430
- if (imageSize.value.width === 0 || imageSize.value.height === 0) {
431
+ // 如果启用自适应宽度,使用第一页的尺寸作为基准
432
+ const baseSize = props.autoFitWidth
433
+ ? (imageSizes.get(1) || { width: 0, height: 0 })
434
+ : imageSize.value;
435
+
436
+ if (baseSize.width === 0 || baseSize.height === 0) {
431
437
  return { width: 0, height: 0 };
432
438
  }
433
439
 
434
- const { width, height } = imageSize.value;
440
+ const { width, height } = baseSize;
435
441
  const scaledWidth = width * scale.value;
436
442
  const scaledHeight = height * scale.value;
437
443
 
@@ -825,11 +831,13 @@ const original = () => {
825
831
 
826
832
  // 计算自适应宽度的缩放比例
827
833
  const calculateAutoFitScale = () => {
828
- if (
829
- !props.autoFitWidth ||
830
- !containerRef.value ||
831
- imageSize.value.width === 0
832
- ) {
834
+ if (!props.autoFitWidth || !containerRef.value) {
835
+ return 1;
836
+ }
837
+
838
+ // 使用第一页的图片尺寸作为基准(所有页面使用相同的缩放比例)
839
+ const firstPageSize = imageSizes.get(1);
840
+ if (!firstPageSize || firstPageSize.width === 0) {
833
841
  return 1;
834
842
  }
835
843
 
@@ -846,7 +854,7 @@ const calculateAutoFitScale = () => {
846
854
  const normalizedRotation = ((rotation.value % 360) + 360) % 360;
847
855
  const isRotated = normalizedRotation === 90 || normalizedRotation === 270;
848
856
 
849
- const imageWidth = isRotated ? imageSize.value.height : imageSize.value.width;
857
+ const imageWidth = isRotated ? firstPageSize.height : firstPageSize.width;
850
858
 
851
859
  if (imageWidth <= 0) {
852
860
  return 1;
@@ -884,10 +892,18 @@ const onImageLoad = (event: Event, pageNum: number) => {
884
892
  scale.value = autoScale;
885
893
  initialAutoFitScale.value = autoScale; // 记录初始自适应缩放比例
886
894
  }
887
- }, 50);
895
+ }, 100); // 增加延迟,确保所有图片都已加载
888
896
  });
889
897
  });
890
898
  }
899
+
900
+ // 如果第一页已经加载完成,且当前页不是第一页,也应用自适应宽度
901
+ if (pageNum > 1 && props.autoFitWidth && initialAutoFitScale.value !== null) {
902
+ // 确保后续页面也使用相同的缩放比例
903
+ if (Math.abs(scale.value - initialAutoFitScale.value) > 0.01) {
904
+ scale.value = initialAutoFitScale.value;
905
+ }
906
+ }
891
907
 
892
908
  emit("load", {
893
909
  width: img.naturalWidth,
@@ -959,7 +975,7 @@ const calculateFontSize = (
959
975
  };
960
976
 
961
977
  /**
962
- * 渲染文本图层(使用 blocksData 数据)
978
+ * 渲染文本图层(使用 blocksData 数据,支持增量渲染)
963
979
  */
964
980
  const renderTextLayer = (pageNum?: number) => {
965
981
  const targetPage = pageNum || currentPage.value;
@@ -970,24 +986,38 @@ const renderTextLayer = (pageNum?: number) => {
970
986
  return;
971
987
  }
972
988
 
989
+ // 如果图片还没加载完成,等待加载完成后再渲染
990
+ if (!image.complete || image.naturalWidth === 0) {
991
+ return;
992
+ }
993
+
973
994
  const pageBlocksData = getPageBlocksData(targetPage);
974
995
  console.log("renderTextLayer", targetPage, pageBlocksData);
975
996
 
976
- // 如果没有提供分块数据,跳过渲染
997
+ // 设置文本图层的尺寸与图片尺寸一致
998
+ textLayer.style.width = `${image.naturalWidth}px`;
999
+ textLayer.style.height = `${image.naturalHeight}px`;
1000
+
1001
+ // 如果没有提供分块数据,清空文本图层
977
1002
  if (!pageBlocksData || pageBlocksData.length === 0) {
978
1003
  textLayer.innerHTML = "";
979
1004
  return;
980
1005
  }
981
1006
 
982
1007
  try {
983
- // 设置文本图层的尺寸与图片尺寸一致
984
- textLayer.style.width = `${image.naturalWidth}px`;
985
- textLayer.style.height = `${image.naturalHeight}px`;
1008
+ // 增量渲染:获取现有的文本块
1009
+ const existingBlocks = new Map<string, HTMLElement>();
1010
+ textLayer.querySelectorAll(".text-block").forEach((el) => {
1011
+ const bboxStr = (el as HTMLElement).dataset.bbox;
1012
+ if (bboxStr) {
1013
+ existingBlocks.set(bboxStr, el as HTMLElement);
1014
+ }
1015
+ });
986
1016
 
987
- // 清空文本图层
988
- textLayer.innerHTML = "";
1017
+ // 创建新的文本块 Map,用于跟踪需要保留的块
1018
+ const newBlocksMap = new Map<string, boolean>();
989
1019
 
990
- // 使用指定页码的 blocksData 创建可交互的块
1020
+ // 使用指定页码的 blocksData 创建或更新可交互的块
991
1021
  pageBlocksData.forEach((block, index) => {
992
1022
  const { content, bbox } = block;
993
1023
 
@@ -1078,7 +1108,76 @@ const renderTextLayer = (pageNum?: number) => {
1078
1108
  blockDiv.style.backgroundColor = "transparent";
1079
1109
  }
1080
1110
 
1081
- textLayer.appendChild(blockDiv);
1111
+ // 检查是否已存在相同的文本块(通过 bbox 匹配)
1112
+ const bboxKey = JSON.stringify(bbox);
1113
+ const existingBlock = existingBlocks.get(bboxKey);
1114
+
1115
+ if (existingBlock) {
1116
+ // 如果已存在,更新内容(增量更新,避免闪烁)
1117
+ existingBlock.textContent = content;
1118
+ existingBlock.dataset.text = content;
1119
+ // 更新批注状态
1120
+ const existingAnnotation = getAnnotationForBlock(bbox);
1121
+ if (existingAnnotation) {
1122
+ if (!existingBlock.classList.contains("has-annotation")) {
1123
+ existingBlock.classList.add("has-annotation");
1124
+ existingBlock.title = `已有批注: ${existingAnnotation.content}`;
1125
+ existingBlock.style.backgroundColor = "rgba(255, 243, 205, 0.5)";
1126
+ existingBlock.style.border = "1px solid rgba(255, 193, 7, 0.7)";
1127
+ existingBlock.style.borderRadius = "3px";
1128
+ existingBlock.style.padding = "1px 3px";
1129
+ existingBlock.style.boxShadow = "0 1px 2px rgba(255, 193, 7, 0.25)";
1130
+
1131
+ // 添加批注标记(如果还没有)
1132
+ if (!existingBlock.querySelector(".annotation-marker")) {
1133
+ const annotationMarker = document.createElement("span");
1134
+ annotationMarker.className = "annotation-marker";
1135
+ annotationMarker.textContent = "📝";
1136
+ annotationMarker.style.position = "absolute";
1137
+ annotationMarker.style.top = "-6px";
1138
+ annotationMarker.style.right = "-6px";
1139
+ annotationMarker.style.fontSize = "11px";
1140
+ annotationMarker.style.backgroundColor = "rgba(255, 193, 7, 0.95)";
1141
+ annotationMarker.style.borderRadius = "50%";
1142
+ annotationMarker.style.width = "16px";
1143
+ annotationMarker.style.height = "16px";
1144
+ annotationMarker.style.display = "flex";
1145
+ annotationMarker.style.alignItems = "center";
1146
+ annotationMarker.style.justifyContent = "center";
1147
+ annotationMarker.style.zIndex = "30";
1148
+ annotationMarker.style.boxShadow = "0 1px 3px rgba(0, 0, 0, 0.25)";
1149
+ annotationMarker.style.lineHeight = "1";
1150
+ existingBlock.appendChild(annotationMarker);
1151
+ }
1152
+ }
1153
+ } else {
1154
+ // 移除批注标记
1155
+ if (existingBlock.classList.contains("has-annotation")) {
1156
+ existingBlock.classList.remove("has-annotation");
1157
+ existingBlock.title = "";
1158
+ existingBlock.style.backgroundColor = "transparent";
1159
+ existingBlock.style.border = "none";
1160
+ existingBlock.style.padding = "0";
1161
+ existingBlock.style.boxShadow = "none";
1162
+ const marker = existingBlock.querySelector(".annotation-marker");
1163
+ if (marker) {
1164
+ marker.remove();
1165
+ }
1166
+ }
1167
+ }
1168
+ newBlocksMap.set(bboxKey, true);
1169
+ } else {
1170
+ // 如果不存在,创建新的文本块
1171
+ textLayer.appendChild(blockDiv);
1172
+ newBlocksMap.set(bboxKey, true);
1173
+ }
1174
+ });
1175
+
1176
+ // 删除不再存在的文本块(增量删除)
1177
+ existingBlocks.forEach((block, bboxKey) => {
1178
+ if (!newBlocksMap.has(bboxKey)) {
1179
+ block.remove();
1180
+ }
1082
1181
  });
1083
1182
  } catch (error) {
1084
1183
  console.error("❌ 文本图层渲染失败:", error);
@@ -1777,65 +1876,58 @@ const jumpToPosition = (
1777
1876
  };
1778
1877
 
1779
1878
  /**
1780
- * 监听 blocksData 变化,重新渲染文本图层
1879
+ * 监听 blocksData 变化,增量渲染所有页面的文本图层(避免闪烁)
1781
1880
  */
1782
1881
  watch(
1783
1882
  () => props.blocksData,
1784
1883
  () => {
1785
1884
  nextTick(() => {
1786
- renderTextLayer();
1885
+ // 渲染所有页面的文本图层
1886
+ for (let pageNum = 1; pageNum <= totalPages.value; pageNum++) {
1887
+ renderTextLayer(pageNum);
1888
+ }
1787
1889
  });
1788
1890
  },
1789
- { deep: true, immediate: false }
1891
+ { deep: true, immediate: true }
1790
1892
  );
1791
1893
 
1792
1894
  /**
1793
- * 监听 annotations 变化,重新渲染文本图层以显示批注标记
1895
+ * 监听 annotations 变化,增量更新所有页面的文本图层以显示批注标记
1794
1896
  */
1795
1897
  watch(
1796
1898
  () => props.annotations,
1797
1899
  () => {
1798
1900
  nextTick(() => {
1799
- renderTextLayer();
1901
+ // 更新所有页面的文本图层
1902
+ for (let pageNum = 1; pageNum <= totalPages.value; pageNum++) {
1903
+ renderTextLayer(pageNum);
1904
+ }
1800
1905
  });
1801
1906
  },
1802
1907
  { deep: true }
1803
1908
  );
1804
1909
 
1805
1910
  /**
1806
- * 监听当前页码变化,重新渲染文本图层
1911
+ * 监听当前页码变化,确保当前页的文本图层已渲染
1807
1912
  */
1808
1913
  watch(
1809
1914
  () => currentPage.value,
1810
1915
  () => {
1811
1916
  nextTick(() => {
1812
- renderTextLayer();
1917
+ renderTextLayer(currentPage.value);
1813
1918
  });
1814
1919
  }
1815
1920
  );
1816
1921
 
1817
1922
  /**
1818
- * 监听当前页码的blocksData变化,重新渲染文本图层
1819
- */
1820
- watch(
1821
- () => currentPageBlocksData.value,
1822
- () => {
1823
- nextTick(() => {
1824
- renderTextLayer();
1825
- });
1826
- },
1827
- { deep: true }
1828
- );
1829
-
1830
- /**
1831
- * 监听图片尺寸变化,重新渲染文本图层
1923
+ * 监听图片尺寸变化,重新渲染当前页的文本图层
1832
1924
  */
1833
1925
  watch(
1834
1926
  () => imageSize.value,
1835
1927
  () => {
1836
1928
  if (imageSize.value.width > 0 && imageSize.value.height > 0) {
1837
1929
  nextTick(() => {
1838
- renderTextLayer();
1930
+ renderTextLayer(currentPage.value);
1839
1931
  });
1840
1932
  }
1841
1933
  },
@@ -1858,18 +1950,23 @@ watch(
1858
1950
  * 组件挂载时的初始化
1859
1951
  */
1860
1952
  onMounted(() => {
1861
- // 如果图片已经加载完成,立即渲染文本图层和自适应宽度
1862
- if (imageRef.value && imageRef.value.complete) {
1863
- nextTick(() => {
1864
- // 如果启用自适应宽度,计算并设置初始缩放比例
1865
- if (props.autoFitWidth && imageSize.value.width > 0) {
1866
- const autoScale = calculateAutoFitScale();
1867
- if (autoScale !== 1) {
1868
- scale.value = autoScale;
1869
- }
1870
- }
1871
- renderTextLayer();
1872
- });
1953
+ // 如果第一页图片已经加载完成,立即计算自适应宽度
1954
+ const firstPageImage = imageRefs.get(1);
1955
+ if (firstPageImage && firstPageImage.complete && props.autoFitWidth) {
1956
+ const firstPageSize = imageSizes.get(1);
1957
+ if (firstPageSize && firstPageSize.width > 0) {
1958
+ nextTick(() => {
1959
+ nextTick(() => {
1960
+ setTimeout(() => {
1961
+ const autoScale = calculateAutoFitScale();
1962
+ if (autoScale !== 1 && autoScale > 0) {
1963
+ scale.value = autoScale;
1964
+ initialAutoFitScale.value = autoScale;
1965
+ }
1966
+ }, 100);
1967
+ });
1968
+ });
1969
+ }
1873
1970
  }
1874
1971
  });
1875
1972