You've already forked DataMate
feat(annotation): 添加Label Studio文本编辑器的焦点管理功能
- 实现focusIframe函数用于聚焦iframe元素 - 在iframeReady和lsReady状态变化时自动聚焦编辑器 - 添加窗口聚焦事件监听器以保持编辑器焦点 - 在编辑器容器上添加鼠标点击事件以获取焦点 - 确保标签工作室准备就绪后正确设置焦点 - 优化用户体验通过自动焦点切换机制
This commit is contained in:
@@ -172,6 +172,13 @@ export default function LabelStudioTextEditor() {
|
|||||||
const [segments, setSegments] = useState<SegmentInfo[]>([]);
|
const [segments, setSegments] = useState<SegmentInfo[]>([]);
|
||||||
const [currentSegmentIndex, setCurrentSegmentIndex] = useState(0);
|
const [currentSegmentIndex, setCurrentSegmentIndex] = useState(0);
|
||||||
|
|
||||||
|
const focusIframe = useCallback(() => {
|
||||||
|
const iframe = iframeRef.current;
|
||||||
|
if (!iframe) return;
|
||||||
|
iframe.focus();
|
||||||
|
iframe.contentWindow?.focus?.();
|
||||||
|
}, []);
|
||||||
|
|
||||||
const postToIframe = useCallback((type: string, payload?: unknown) => {
|
const postToIframe = useCallback((type: string, payload?: unknown) => {
|
||||||
const win = iframeRef.current?.contentWindow;
|
const win = iframeRef.current?.contentWindow;
|
||||||
if (!win) return;
|
if (!win) return;
|
||||||
@@ -600,6 +607,25 @@ export default function LabelStudioTextEditor() {
|
|||||||
initEditorForFile(selectedFileId);
|
initEditorForFile(selectedFileId);
|
||||||
}, [selectedFileId, iframeReady, initEditorForFile]);
|
}, [selectedFileId, iframeReady, initEditorForFile]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!iframeReady) return;
|
||||||
|
focusIframe();
|
||||||
|
}, [focusIframe, iframeReady]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!lsReady) return;
|
||||||
|
focusIframe();
|
||||||
|
}, [focusIframe, lsReady]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!lsReady) return;
|
||||||
|
const handleWindowFocus = () => {
|
||||||
|
focusIframe();
|
||||||
|
};
|
||||||
|
window.addEventListener("focus", handleWindowFocus);
|
||||||
|
return () => window.removeEventListener("focus", handleWindowFocus);
|
||||||
|
}, [focusIframe, lsReady]);
|
||||||
|
|
||||||
const segmentTreeData = useMemo(() => {
|
const segmentTreeData = useMemo(() => {
|
||||||
if (!segmented || segments.length === 0) return [];
|
if (!segmented || segments.length === 0) return [];
|
||||||
const lineMap = new Map<number, SegmentInfo[]>();
|
const lineMap = new Map<number, SegmentInfo[]>();
|
||||||
@@ -870,7 +896,7 @@ export default function LabelStudioTextEditor() {
|
|||||||
{/* 右侧编辑器 - Label Studio iframe */}
|
{/* 右侧编辑器 - Label Studio iframe */}
|
||||||
<div className="flex-1 flex flex-col min-h-0">
|
<div className="flex-1 flex flex-col min-h-0">
|
||||||
{/* 编辑器区域 */}
|
{/* 编辑器区域 */}
|
||||||
<div className="flex-1 relative">
|
<div className="flex-1 relative" onMouseDown={focusIframe}>
|
||||||
{(!iframeReady || loadingTaskDetail || (selectedFileId && !lsReady)) && (
|
{(!iframeReady || loadingTaskDetail || (selectedFileId && !lsReady)) && (
|
||||||
<div className="absolute inset-0 z-10 flex items-center justify-center bg-white/80">
|
<div className="absolute inset-0 z-10 flex items-center justify-center bg-white/80">
|
||||||
<Spin
|
<Spin
|
||||||
|
|||||||
Reference in New Issue
Block a user