@koi-br/ocr-web-sdk 1.0.67 → 1.1.0

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-BwWdGx71.mjs";
1
+ import { g as getAugmentedNamespace, a as getDefaultExportFromCjs } from "./index-DuCZ_Am_.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,14 +1,16 @@
1
1
  {
2
2
  "name": "@koi-br/ocr-web-sdk",
3
- "version": "1.0.67",
3
+ "version": "1.1.0",
4
4
  "description": "一个支持多种Office文件格式预览的Vue3组件SDK,包括PDF、Word、Excel、图片、OFD、TIF等格式",
5
- "main": "dist/index.js",
5
+ "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
7
+ "browser": "dist/index.umd.js",
7
8
  "types": "dist/index.d.ts",
8
9
  "exports": {
9
10
  ".": {
10
11
  "import": "./dist/index.esm.js",
11
- "require": "./dist/index.js",
12
+ "require": "./dist/index.cjs.js",
13
+ "browser": "./dist/index.umd.js",
12
14
  "types": "./dist/index.d.ts"
13
15
  },
14
16
  "./style.css": "./dist/style.css"
@@ -55,9 +57,10 @@
55
57
  "less": "^4.4.2",
56
58
  "typescript": "^5.3.0",
57
59
  "vite": "^5.0.0",
58
- "vite-plugin-dts": "^3.6.0"
60
+ "vite-plugin-dts": "^3.6.0",
61
+ "vue-router": "^4.6.4"
59
62
  },
60
63
  "peerDependencies": {
61
64
  "vue": "^3.0.0"
62
65
  }
63
- }
66
+ }
@@ -1577,41 +1577,6 @@ const renderTextLayer = (pageNum?: number) => {
1577
1577
  blockDiv.style.backgroundColor = "transparent";
1578
1578
  blockDiv.style.pointerEvents = "auto";
1579
1579
  blockDiv.style.userSelect = "none";
1580
-
1581
- // 检查是否有已有批注,如果有则显示批注标记
1582
- const existingAnnotation = getAnnotationForBlock(bbox, targetPage);
1583
- if (existingAnnotation) {
1584
- // 添加批注标记样式类
1585
- blockDiv.classList.add("has-annotation");
1586
- blockDiv.title = `已有批注: ${existingAnnotation.content}`;
1587
- // 直接设置样式,确保生效(内联样式优先级高于CSS类)
1588
- blockDiv.style.backgroundColor = "rgba(255, 243, 205, 0.5)";
1589
- blockDiv.style.border = "1px solid rgba(255, 193, 7, 0.7)";
1590
- blockDiv.style.borderRadius = "3px";
1591
- blockDiv.style.padding = "1px 3px";
1592
- blockDiv.style.boxShadow = "0 1px 2px rgba(255, 193, 7, 0.25)";
1593
-
1594
- // 创建批注图标标记
1595
- const annotationMarker = document.createElement("span");
1596
- annotationMarker.className = "annotation-marker";
1597
- annotationMarker.textContent = "📝";
1598
- annotationMarker.style.position = "absolute";
1599
- annotationMarker.style.top = "-6px";
1600
- annotationMarker.style.right = "-6px";
1601
- annotationMarker.style.fontSize = "11px";
1602
- annotationMarker.style.backgroundColor = "rgba(255, 193, 7, 0.95)";
1603
- annotationMarker.style.borderRadius = "50%";
1604
- annotationMarker.style.width = "16px";
1605
- annotationMarker.style.height = "16px";
1606
- annotationMarker.style.display = "flex";
1607
- annotationMarker.style.alignItems = "center";
1608
- annotationMarker.style.justifyContent = "center";
1609
- annotationMarker.style.zIndex = "30";
1610
- annotationMarker.style.boxShadow = "0 1px 3px rgba(0, 0, 0, 0.25)";
1611
- annotationMarker.style.lineHeight = "1";
1612
- blockDiv.appendChild(annotationMarker);
1613
- }
1614
-
1615
1580
  // Hover 和点击事件
1616
1581
  blockDiv.addEventListener("mouseenter", (e) => {
1617
1582
  // ✅ 输入态:锚点已锁定,禁止 hover 驱动位置/激活块变化
@@ -1624,6 +1589,43 @@ const renderTextLayer = (pageNum?: number) => {
1624
1589
  return;
1625
1590
  }
1626
1591
 
1592
+ // 🔑 关键修复:如果鼠标是从批注按钮移动过来的,不处理hover事件
1593
+ // 这样可以避免鼠标移动到批注按钮时触发其他文本块的hover
1594
+ const relatedTarget = (e as MouseEvent).relatedTarget as HTMLElement;
1595
+ if (relatedTarget) {
1596
+ // 检查鼠标是否从批注按钮区域移动过来
1597
+ const annotationButton = relatedTarget.closest?.(".annotation-button-popup");
1598
+ const annotationButtonAction = relatedTarget.closest?.(".annotation-button-action");
1599
+ if (annotationButton || annotationButtonAction) {
1600
+ // 鼠标正在从批注按钮移动到文本块,不处理hover事件
1601
+ return;
1602
+ }
1603
+ }
1604
+
1605
+ // 🔑 关键修复:如果批注按钮正在显示,且当前激活的文本块不是这个块,检查鼠标位置
1606
+ // 如果鼠标在批注按钮附近,不更新激活的文本块(避免按钮位置被更新)
1607
+ if (showAnnotationPopup.value && activeBlockDiv.value && activeBlockDiv.value !== blockDiv) {
1608
+ const buttonElement = annotationButtonRef.value;
1609
+ if (buttonElement) {
1610
+ const buttonRect = buttonElement.getBoundingClientRect();
1611
+ const mouseX = (e as MouseEvent).clientX;
1612
+ const mouseY = (e as MouseEvent).clientY;
1613
+
1614
+ // 检查鼠标是否在批注按钮的"安全区域"内(按钮周围20px的区域)
1615
+ const safeAreaPadding = 20;
1616
+ const isInSafeArea =
1617
+ mouseX >= buttonRect.left - safeAreaPadding &&
1618
+ mouseX <= buttonRect.right + safeAreaPadding &&
1619
+ mouseY >= buttonRect.top - safeAreaPadding &&
1620
+ mouseY <= buttonRect.bottom + safeAreaPadding;
1621
+
1622
+ if (isInSafeArea) {
1623
+ // 鼠标在批注按钮的安全区域内,不更新激活的文本块
1624
+ return;
1625
+ }
1626
+ }
1627
+ }
1628
+
1627
1629
  // 取消之前的隐藏定时器
1628
1630
  if (hideTimer) {
1629
1631
  clearTimeout(hideTimer);
@@ -1642,15 +1644,14 @@ const renderTextLayer = (pageNum?: number) => {
1642
1644
  // 设置当前文本块为激活状态
1643
1645
  activeBlockDiv.value = blockDiv;
1644
1646
 
1645
- // 检查是否有批注,应用对应的 hover 样式
1646
- const existingAnnotation = getAnnotationForBlock(bbox, targetPage);
1647
- applyHoverStyle(blockDiv, !!existingAnnotation);
1647
+ // 应用 hover 样式
1648
+ applyHoverStyle(blockDiv);
1648
1649
 
1649
1650
  // 显示批注按钮浮层
1650
1651
  showAnnotationButtonForBlock(e, blockDiv);
1651
1652
  });
1652
1653
 
1653
- blockDiv.addEventListener("mouseleave", () => {
1654
+ blockDiv.addEventListener("mouseleave", (e) => {
1654
1655
  // ✅ 输入态:不再启动 auto-hide 逻辑
1655
1656
  if (currentAnnotationBlock.value) {
1656
1657
  return;
@@ -1661,6 +1662,18 @@ const renderTextLayer = (pageNum?: number) => {
1661
1662
  return;
1662
1663
  }
1663
1664
 
1665
+ // 🔑 关键修复:如果鼠标是移动到批注按钮,不启动隐藏定时器
1666
+ const relatedTarget = (e as MouseEvent).relatedTarget as HTMLElement;
1667
+ if (relatedTarget) {
1668
+ // 检查鼠标是否移动到批注按钮区域
1669
+ const annotationButton = relatedTarget.closest?.(".annotation-button-popup");
1670
+ const annotationButtonAction = relatedTarget.closest?.(".annotation-button-action");
1671
+ if (annotationButton || annotationButtonAction) {
1672
+ // 鼠标正在移动到批注按钮,不启动隐藏定时器
1673
+ return;
1674
+ }
1675
+ }
1676
+
1664
1677
  // 延迟隐藏,给用户时间移动到批注按钮
1665
1678
  if (props.enableHoverAutoHide) {
1666
1679
  hideTimer = setTimeout(() => {
@@ -1912,57 +1925,15 @@ const clearAllHighlights = (
1912
1925
  return;
1913
1926
  }
1914
1927
 
1915
- // 检查是否有批注
1916
- const bboxStr = el.dataset.bbox;
1917
- if (!bboxStr) return;
1918
-
1919
- try {
1920
- const bbox = JSON.parse(bboxStr) as [number, number, number, number];
1921
- const pageStr = el.dataset.page;
1922
- const pageNum = pageStr ? parseInt(pageStr, 10) : undefined;
1923
- const existingAnnotation = getAnnotationForBlock(bbox, pageNum);
1924
-
1925
- if (existingAnnotation) {
1926
- // 如果有批注,恢复批注样式(不使用 hover 样式)
1927
- el.style.setProperty(
1928
- "background-color",
1929
- "rgba(255, 243, 205, 0.5)",
1930
- "important"
1931
- );
1932
- el.style.setProperty(
1933
- "border",
1934
- "1px solid rgba(255, 193, 7, 0.7)",
1935
- "important"
1936
- );
1937
- el.style.setProperty("border-radius", "3px", "important");
1938
- el.style.setProperty("padding", "1px 3px", "important");
1939
- el.style.setProperty(
1940
- "box-shadow",
1941
- "0 1px 2px rgba(255, 193, 7, 0.25)",
1942
- "important"
1943
- );
1944
- } else {
1945
- // 如果没有批注,清除所有高亮样式
1946
- el.style.backgroundColor = "transparent";
1947
- el.style.border = "none";
1948
- el.style.borderRadius = "2px";
1949
- el.style.padding = "0";
1950
- el.style.boxShadow = "none";
1951
- el.style.removeProperty("background-color");
1952
- el.style.removeProperty("border");
1953
- el.style.removeProperty("box-shadow");
1954
- }
1955
- } catch (error) {
1956
- // 如果解析失败,清除所有高亮样式
1957
- el.style.backgroundColor = "transparent";
1958
- el.style.border = "none";
1959
- el.style.borderRadius = "2px";
1960
- el.style.padding = "0";
1961
- el.style.boxShadow = "none";
1962
- el.style.removeProperty("background-color");
1963
- el.style.removeProperty("border");
1964
- el.style.removeProperty("box-shadow");
1965
- }
1928
+ // 清除所有高亮样式
1929
+ el.style.backgroundColor = "transparent";
1930
+ el.style.border = "none";
1931
+ el.style.borderRadius = "2px";
1932
+ el.style.padding = "0";
1933
+ el.style.boxShadow = "none";
1934
+ el.style.removeProperty("background-color");
1935
+ el.style.removeProperty("border");
1936
+ el.style.removeProperty("box-shadow");
1966
1937
  });
1967
1938
  };
1968
1939
 
@@ -1970,143 +1941,38 @@ const clearAllHighlights = (
1970
1941
  * 恢复文本块样式(根据是否有批注)
1971
1942
  */
1972
1943
  const restoreBlockStyle = (blockDiv: HTMLElement) => {
1973
- const bboxStr = blockDiv.dataset.bbox;
1974
- if (!bboxStr) {
1975
- console.log("restoreBlockStyle: 没有 bbox");
1976
- return;
1977
- }
1978
-
1979
- try {
1980
- const bbox = JSON.parse(bboxStr) as [number, number, number, number];
1981
- const pageStr = blockDiv.dataset.page;
1982
- const pageNum = pageStr ? parseInt(pageStr, 10) : undefined;
1983
- const existingAnnotation = getAnnotationForBlock(bbox, pageNum);
1984
-
1985
- console.log("restoreBlockStyle:", {
1986
- bbox,
1987
- pageNum,
1988
- existingAnnotation,
1989
- blockDiv: blockDiv,
1990
- width: blockDiv.style.width,
1991
- height: blockDiv.style.height,
1992
- computedStyle: {
1993
- backgroundColor: window.getComputedStyle(blockDiv).backgroundColor,
1994
- width: window.getComputedStyle(blockDiv).width,
1995
- height: window.getComputedStyle(blockDiv).height,
1996
- display: window.getComputedStyle(blockDiv).display,
1997
- visibility: window.getComputedStyle(blockDiv).visibility,
1998
- },
1999
- inlineStyle: {
2000
- backgroundColor: blockDiv.style.backgroundColor,
2001
- border: blockDiv.style.border,
2002
- },
2003
- });
2004
-
2005
- if (existingAnnotation) {
2006
- // 如果有批注,保持批注样式(使用 !important 确保优先级)
2007
- blockDiv.style.setProperty(
2008
- "background-color",
2009
- "rgba(255, 243, 205, 0.5)",
2010
- "important"
2011
- );
2012
- blockDiv.style.setProperty(
2013
- "border",
2014
- "1px solid rgba(255, 193, 7, 0.7)",
2015
- "important"
2016
- );
2017
- blockDiv.style.setProperty("border-radius", "3px", "important");
2018
- blockDiv.style.setProperty("padding", "1px 3px", "important");
2019
- blockDiv.style.setProperty(
2020
- "box-shadow",
2021
- "0 1px 2px rgba(255, 193, 7, 0.25)",
2022
- "important"
2023
- );
2024
-
2025
- // 确保元素可见
2026
- blockDiv.style.setProperty("display", "block", "important");
2027
- blockDiv.style.setProperty("visibility", "visible", "important");
2028
- blockDiv.style.setProperty("opacity", "1", "important");
2029
-
2030
- console.log("restoreBlockStyle: 已设置批注样式", {
2031
- backgroundColor: blockDiv.style.backgroundColor,
2032
- border: blockDiv.style.border,
2033
- computedAfter: window.getComputedStyle(blockDiv).backgroundColor,
2034
- });
2035
- } else {
2036
- // 如果没有批注,恢复透明背景(清除所有高亮相关样式)
2037
- blockDiv.style.backgroundColor = "transparent";
2038
- blockDiv.style.border = "none";
2039
- blockDiv.style.borderRadius = "2px"; // 恢复默认值
2040
- blockDiv.style.padding = "0";
2041
- blockDiv.style.boxShadow = "none";
2042
- // 清除可能残留的样式属性
2043
- blockDiv.style.removeProperty("background-color");
2044
- blockDiv.style.removeProperty("border");
2045
- blockDiv.style.removeProperty("box-shadow");
2046
- }
2047
- } catch (error) {
2048
- console.error("restoreBlockStyle 错误:", error);
2049
- // 如果解析失败,恢复透明背景(清除所有高亮相关样式)
2050
- blockDiv.style.backgroundColor = "transparent";
2051
- blockDiv.style.border = "none";
2052
- blockDiv.style.borderRadius = "2px"; // 恢复默认值
2053
- blockDiv.style.padding = "0";
2054
- blockDiv.style.boxShadow = "none";
2055
- // 清除可能残留的样式属性
2056
- blockDiv.style.removeProperty("background-color");
2057
- blockDiv.style.removeProperty("border");
2058
- blockDiv.style.removeProperty("box-shadow");
2059
- }
1944
+ // 恢复透明背景(清除所有高亮相关样式)
1945
+ blockDiv.style.backgroundColor = "transparent";
1946
+ blockDiv.style.border = "none";
1947
+ blockDiv.style.borderRadius = "2px"; // 恢复默认值
1948
+ blockDiv.style.padding = "0";
1949
+ blockDiv.style.boxShadow = "none";
1950
+ // 清除可能残留的样式属性
1951
+ blockDiv.style.removeProperty("background-color");
1952
+ blockDiv.style.removeProperty("border");
1953
+ blockDiv.style.removeProperty("box-shadow");
2060
1954
  };
2061
1955
 
2062
1956
  /**
2063
1957
  * 应用 hover 样式
2064
1958
  */
2065
- const applyHoverStyle = (blockDiv: HTMLElement, hasAnnotation: boolean) => {
2066
- if (hasAnnotation) {
2067
- // 有批注时使用 annotationHoverStyle
2068
- const style = props.annotationHoverStyle;
2069
- if (style.backgroundColor) {
2070
- blockDiv.style.setProperty(
2071
- "background-color",
2072
- style.backgroundColor,
2073
- "important"
2074
- );
2075
- }
2076
- if (style.border) {
2077
- blockDiv.style.setProperty("border", style.border, "important");
2078
- }
2079
- if (style.borderRadius) {
2080
- blockDiv.style.setProperty(
2081
- "border-radius",
2082
- style.borderRadius,
2083
- "important"
2084
- );
2085
- }
2086
- if (style.padding) {
2087
- blockDiv.style.setProperty("padding", style.padding, "important");
2088
- }
2089
- if (style.boxShadow) {
2090
- blockDiv.style.setProperty("box-shadow", style.boxShadow, "important");
2091
- }
2092
- } else {
2093
- // 无批注时使用 hoverStyle
2094
- const style = props.hoverStyle;
2095
- if (style.backgroundColor) {
2096
- blockDiv.style.backgroundColor = style.backgroundColor;
2097
- }
2098
- if (style.border) {
2099
- blockDiv.style.border = style.border;
2100
- }
2101
- if (style.borderRadius) {
2102
- blockDiv.style.borderRadius = style.borderRadius;
2103
- }
2104
- if (style.padding) {
2105
- blockDiv.style.padding = style.padding;
2106
- }
2107
- if (style.boxShadow) {
2108
- blockDiv.style.boxShadow = style.boxShadow;
2109
- }
1959
+ const applyHoverStyle = (blockDiv: HTMLElement) => {
1960
+ // 统一使用 hoverStyle,不再区分是否有批注
1961
+ const style = props.hoverStyle;
1962
+ if (style.backgroundColor) {
1963
+ blockDiv.style.backgroundColor = style.backgroundColor;
1964
+ }
1965
+ if (style.border) {
1966
+ blockDiv.style.border = style.border;
1967
+ }
1968
+ if (style.borderRadius) {
1969
+ blockDiv.style.borderRadius = style.borderRadius;
1970
+ }
1971
+ if (style.padding) {
1972
+ blockDiv.style.padding = style.padding;
1973
+ }
1974
+ if (style.boxShadow) {
1975
+ blockDiv.style.boxShadow = style.boxShadow;
2110
1976
  }
2111
1977
  };
2112
1978
 
@@ -2127,47 +1993,18 @@ const hideAnnotationButton = () => {
2127
1993
  hideTimer = setTimeout(() => {
2128
1994
  showAnnotationPopup.value = false;
2129
1995
 
2130
- // 恢复文本块的样式(如果有批注则保持批注样式)
1996
+ // 恢复文本块的样式
2131
1997
  if (activeBlockDiv.value) {
2132
- const bboxStr = activeBlockDiv.value.dataset.bbox;
2133
- if (bboxStr) {
2134
- try {
2135
- const bbox = JSON.parse(bboxStr) as [number, number, number, number];
2136
- const existingAnnotation = getAnnotationForBlock(bbox);
2137
- if (existingAnnotation) {
2138
- // 如果有批注,恢复批注样式
2139
- activeBlockDiv.value.style.backgroundColor =
2140
- "rgba(255, 243, 205, 0.5)";
2141
- activeBlockDiv.value.style.border =
2142
- "1px solid rgba(255, 193, 7, 0.7)";
2143
- activeBlockDiv.value.style.padding = "1px 3px";
2144
- activeBlockDiv.value.style.boxShadow =
2145
- "0 1px 2px rgba(255, 193, 7, 0.25)";
2146
- } else {
2147
- // 如果没有批注,恢复透明背景(清除所有高亮相关样式)
2148
- activeBlockDiv.value.style.backgroundColor = "transparent";
2149
- activeBlockDiv.value.style.border = "none";
2150
- activeBlockDiv.value.style.borderRadius = "2px"; // 恢复默认值
2151
- activeBlockDiv.value.style.padding = "0";
2152
- activeBlockDiv.value.style.boxShadow = "none";
2153
- // 清除可能残留的样式属性
2154
- activeBlockDiv.value.style.removeProperty("background-color");
2155
- activeBlockDiv.value.style.removeProperty("border");
2156
- activeBlockDiv.value.style.removeProperty("box-shadow");
2157
- }
2158
- } catch (error) {
2159
- // 如果解析失败,恢复透明背景(清除所有高亮相关样式)
2160
- activeBlockDiv.value.style.backgroundColor = "transparent";
2161
- activeBlockDiv.value.style.border = "none";
2162
- activeBlockDiv.value.style.borderRadius = "2px"; // 恢复默认值
2163
- activeBlockDiv.value.style.padding = "0";
2164
- activeBlockDiv.value.style.boxShadow = "none";
2165
- // 清除可能残留的样式属性
2166
- activeBlockDiv.value.style.removeProperty("background-color");
2167
- activeBlockDiv.value.style.removeProperty("border");
2168
- activeBlockDiv.value.style.removeProperty("box-shadow");
2169
- }
2170
- }
1998
+ // 恢复透明背景(清除所有高亮相关样式)
1999
+ activeBlockDiv.value.style.backgroundColor = "transparent";
2000
+ activeBlockDiv.value.style.border = "none";
2001
+ activeBlockDiv.value.style.borderRadius = "2px"; // 恢复默认值
2002
+ activeBlockDiv.value.style.padding = "0";
2003
+ activeBlockDiv.value.style.boxShadow = "none";
2004
+ // 清除可能残留的样式属性
2005
+ activeBlockDiv.value.style.removeProperty("background-color");
2006
+ activeBlockDiv.value.style.removeProperty("border");
2007
+ activeBlockDiv.value.style.removeProperty("box-shadow");
2171
2008
  // 清除高亮标志
2172
2009
  isHighlighted.value = false;
2173
2010
  activeBlockDiv.value = null;
@@ -2264,15 +2101,9 @@ const openAnnotationInput = (e?: Event) => {
2264
2101
  return;
2265
2102
  }
2266
2103
 
2267
- // 检查是否已有批注
2268
- const existingAnnotation = getAnnotationForBlock(bbox);
2269
- if (existingAnnotation) {
2270
- annotationInput.value = existingAnnotation.content;
2271
- currentEditingAnnotation.value = existingAnnotation; // 保存当前编辑的批注信息
2272
- } else {
2273
- annotationInput.value = "";
2274
- currentEditingAnnotation.value = null; // 新批注,清空编辑信息
2275
- }
2104
+ // 每次打开批注输入框都是新的,清空输入内容
2105
+ annotationInput.value = "";
2106
+ currentEditingAnnotation.value = null;
2276
2107
 
2277
2108
  currentAnnotationBlock.value = {
2278
2109
  bbox,
@@ -2298,8 +2129,8 @@ const openAnnotationInput = (e?: Event) => {
2298
2129
  // 清除其它块的高亮,避免竞态残留
2299
2130
  clearAllHighlights(lockedAnnotationDiv.value);
2300
2131
 
2301
- // 保持该块的 hover/批注样式
2302
- applyHoverStyle(lockedAnnotationDiv.value, !!existingAnnotation);
2132
+ // 保持该块的 hover 样式
2133
+ applyHoverStyle(lockedAnnotationDiv.value);
2303
2134
 
2304
2135
  // 使用 outline 作为“锁定态”标识(不依赖 scoped CSS)
2305
2136
  applyLockedAnnotationOutline(lockedAnnotationDiv.value);
@@ -2532,7 +2363,7 @@ const saveAnnotation = () => {
2532
2363
  // 关闭输入框
2533
2364
  closeAnnotationInput();
2534
2365
 
2535
- // 重新渲染文本图层以显示批注标记
2366
+ // 重新渲染文本图层以更新批注数据
2536
2367
  nextTick(() => {
2537
2368
  renderTextLayer();
2538
2369
  });
@@ -2755,34 +2586,15 @@ const highlightPosition = (
2755
2586
  // 这样可以避免多个高亮框同时存在的问题
2756
2587
  const hadHighlight = activeBlockDiv.value !== null && isHighlighted.value;
2757
2588
 
2758
- // ✅ 如果当前有批注输入态锁定块,先记录它的批注状态,清理后再补回样式
2589
+ // ✅ 如果当前有批注输入态锁定块,清理后再补回样式
2759
2590
  const lockedDiv = lockedAnnotationDiv.value;
2760
- let lockedHasAnnotation = false;
2761
- if (lockedDiv) {
2762
- const bboxStr = lockedDiv.dataset.bbox;
2763
- const pageStr = lockedDiv.dataset.page;
2764
- const lockedPageNum = pageStr ? parseInt(pageStr, 10) : undefined;
2765
- if (bboxStr) {
2766
- try {
2767
- const bbox = JSON.parse(bboxStr) as [
2768
- number,
2769
- number,
2770
- number,
2771
- number
2772
- ];
2773
- lockedHasAnnotation = !!getAnnotationForBlock(bbox, lockedPageNum);
2774
- } catch (_e) {
2775
- lockedHasAnnotation = false;
2776
- }
2777
- }
2778
- }
2779
2591
 
2780
2592
  // 清除所有高亮(包括所有页面的文本块),不排除任何元素
2781
2593
  clearAllHighlights();
2782
2594
 
2783
2595
  // ✅ 清理后补回锁定块样式(避免 jump/highlight 清掉输入态的背景高亮)
2784
2596
  if (lockedDiv) {
2785
- applyHoverStyle(lockedDiv, lockedHasAnnotation);
2597
+ applyHoverStyle(lockedDiv);
2786
2598
  applyLockedAnnotationOutline(lockedDiv);
2787
2599
  }
2788
2600
 
@@ -3050,34 +2862,15 @@ const jumpToPosition = (
3050
2862
  isHighlighted: isHighlighted.value,
3051
2863
  reason: previousPositioningId ? '之前的定位被新定位覆盖' : '清除残留的高亮'
3052
2864
  });
3053
- // ✅ 如果当前有批注输入态锁定块,先记录它的批注状态,清理后再补回样式
2865
+ // ✅ 如果当前有批注输入态锁定块,清理后再补回样式
3054
2866
  const lockedDiv = lockedAnnotationDiv.value;
3055
- let lockedHasAnnotation = false;
3056
- if (lockedDiv) {
3057
- const bboxStr = lockedDiv.dataset.bbox;
3058
- const pageStr = lockedDiv.dataset.page;
3059
- const lockedPageNum = pageStr ? parseInt(pageStr, 10) : undefined;
3060
- if (bboxStr) {
3061
- try {
3062
- const lockedBbox = JSON.parse(bboxStr) as [
3063
- number,
3064
- number,
3065
- number,
3066
- number
3067
- ];
3068
- lockedHasAnnotation = !!getAnnotationForBlock(lockedBbox, lockedPageNum);
3069
- } catch (_e) {
3070
- lockedHasAnnotation = false;
3071
- }
3072
- }
3073
- }
3074
2867
 
3075
2868
  // 清除所有页面的高亮元素,不排除任何元素
3076
2869
  clearAllHighlights();
3077
2870
 
3078
2871
  // ✅ 清理后补回锁定块样式(避免跳转清掉输入态的背景高亮)
3079
2872
  if (lockedDiv) {
3080
- applyHoverStyle(lockedDiv, lockedHasAnnotation);
2873
+ applyHoverStyle(lockedDiv);
3081
2874
  applyLockedAnnotationOutline(lockedDiv);
3082
2875
  }
3083
2876
  }
@@ -3239,7 +3032,7 @@ watch(
3239
3032
  );
3240
3033
 
3241
3034
  /**
3242
- * 监听 annotations 变化,增量更新所有页面的文本图层以显示批注标记
3035
+ * 监听 annotations 变化,增量更新所有页面的文本图层以更新批注数据
3243
3036
  */
3244
3037
  watch(
3245
3038
  () => props.annotations,
@@ -3713,12 +3506,14 @@ defineExpose({
3713
3506
  // 确保可见
3714
3507
  visibility: visible !important;
3715
3508
  display: block !important;
3509
+ // 🔑 确保文本块的z-index低于批注按钮,避免遮挡批注按钮
3510
+ z-index: 20 !important;
3716
3511
  }
3717
3512
 
3718
3513
  // 批注按钮浮层
3719
3514
  .annotation-button-popup {
3720
3515
  position: absolute;
3721
- z-index: 1000;
3516
+ z-index: 10000; // 🔑 提高z-index,确保批注按钮在所有文本块之上
3722
3517
  display: flex;
3723
3518
  flex-direction: row;
3724
3519
  width: fit-content;
@@ -3728,6 +3523,8 @@ defineExpose({
3728
3523
  border-radius: 6px;
3729
3524
  box-shadow: 0 4px 12px rgb(0 0 0 / 15%);
3730
3525
  animation: fade-in 0.2s ease;
3526
+ // 🔑 确保批注按钮可以接收鼠标事件,不被其他元素遮挡
3527
+ isolation: isolate;
3731
3528
 
3732
3529
  .annotation-button-action {
3733
3530
  display: flex;
@@ -3740,6 +3537,10 @@ defineExpose({
3740
3537
  white-space: nowrap;
3741
3538
  cursor: pointer;
3742
3539
  border-radius: 4px;
3540
+ // 🔑 确保按钮可以接收鼠标事件
3541
+ pointer-events: auto;
3542
+ position: relative;
3543
+ z-index: 10001; // 确保按钮在浮层之上
3743
3544
  }
3744
3545
 
3745
3546
  .annotation-button-action:hover {
@@ -3872,45 +3673,6 @@ defineExpose({
3872
3673
  }
3873
3674
 
3874
3675
  // 有批注的文本块样式
3875
- .text-block.has-annotation {
3876
- position: relative;
3877
- // 添加背景色区分
3878
- background-color: rgba(255, 243, 205, 0.5) !important; // 浅黄色背景
3879
- // 添加边框
3880
- border: 1px solid rgba(255, 193, 7, 0.7) !important; // 黄色边框
3881
- border-radius: 3px;
3882
- // 添加内边距,让文字不贴边
3883
- padding: 1px 3px;
3884
- // 添加阴影效果
3885
- box-shadow: 0 1px 2px rgba(255, 193, 7, 0.25) !important;
3886
-
3887
- // 鼠标悬停时加深效果
3888
- &:hover {
3889
- background-color: rgba(255, 243, 205, 0.7) !important;
3890
- border-color: rgba(255, 193, 7, 0.9) !important;
3891
- box-shadow: 0 2px 4px rgba(255, 193, 7, 0.35) !important;
3892
- }
3893
-
3894
- // 使用伪元素添加批注标记图标
3895
- &::before {
3896
- content: "📝";
3897
- position: absolute;
3898
- top: -6px;
3899
- right: -6px;
3900
- font-size: 11px;
3901
- background-color: rgba(255, 193, 7, 0.95);
3902
- border-radius: 50%;
3903
- width: 16px;
3904
- height: 16px;
3905
- display: flex;
3906
- align-items: center;
3907
- justify-content: center;
3908
- z-index: 30;
3909
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
3910
- line-height: 1;
3911
- }
3912
- }
3913
-
3914
3676
  // 淡入动画
3915
3677
  @keyframes fade-in {
3916
3678
  from {