@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.
- package/dist/{index-YVNy3DHg.js → index-BngqS3RU.js} +87 -87
- package/dist/{index-BwWdGx71.mjs → index-DuCZ_Am_.mjs} +7431 -7529
- package/dist/index.cjs.js +2 -2
- package/dist/index.esm.js +2 -2
- package/dist/index.umd.js +229 -0
- package/dist/style.css +1 -1
- package/dist/{tiff.min-BjOpN7Tg.js → tiff.min-8gTbSZDP.js} +1 -1
- package/dist/{tiff.min-C7mxi5R2.mjs → tiff.min-KAQAp3fU.mjs} +1 -1
- package/package.json +8 -5
- package/preview/ImagePreview.vue +119 -357
- package/preview/PdfPreview.vue +5 -8
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as getAugmentedNamespace, a as getDefaultExportFromCjs } from "./index-
|
|
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
|
|
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
|
+
}
|
package/preview/ImagePreview.vue
CHANGED
|
@@ -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
|
-
//
|
|
1646
|
-
|
|
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
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
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
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
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
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
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
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
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
|
-
|
|
2269
|
-
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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 {
|