feat(label-studio): 添加编辑器就绪状态检查和任务ID验证

- 添加 expectedTaskIdRef 用于跟踪预期任务ID
- 添加 lsReady 状态管理编辑器就绪状态
- 在任务加载时重置编辑器就绪状态和预期任务ID
- 实现 LS_READY 消息处理和任务ID验证逻辑
- 添加错误处理时设置编辑器为未就绪状态
- 更新加载提示显示不同状态信息
- 改进条件渲染确保编辑器完全准备就绪后显示
This commit is contained in:
2026-01-12 22:44:13 +08:00
parent e1c41a93c3
commit 70b2ddd4a2

View File

@@ -42,6 +42,7 @@ export default function LabelStudioTextEditor() {
const origin = useMemo(() => window.location.origin, []);
const iframeRef = useRef<HTMLIFrameElement | null>(null);
const initSeqRef = useRef(0);
const expectedTaskIdRef = useRef<number | null>(null);
const [loadingProject, setLoadingProject] = useState(true);
const [loadingTasks, setLoadingTasks] = useState(false);
@@ -49,6 +50,7 @@ export default function LabelStudioTextEditor() {
const [saving, setSaving] = useState(false);
const [iframeReady, setIframeReady] = useState(false);
const [lsReady, setLsReady] = useState(false);
const [project, setProject] = useState<EditorProjectInfo | null>(null);
const [tasks, setTasks] = useState<EditorTaskListItem[]>([]);
const [selectedFileId, setSelectedFileId] = useState<string>("");
@@ -109,6 +111,8 @@ export default function LabelStudioTextEditor() {
const seq = ++initSeqRef.current;
setLoadingTaskDetail(true);
setLsReady(false);
expectedTaskIdRef.current = null;
try {
const resp = (await getEditorTaskUsingGet(projectId, fileId)) as any;
@@ -119,6 +123,7 @@ export default function LabelStudioTextEditor() {
}
if (seq !== initSeqRef.current) return;
expectedTaskIdRef.current = Number(task?.id) || null;
postToIframe("LS_INIT", {
labelConfig: project.labelConfig,
task,
@@ -179,6 +184,8 @@ export default function LabelStudioTextEditor() {
setTasks([]);
setSelectedFileId("");
initSeqRef.current = 0;
setLsReady(false);
expectedTaskIdRef.current = null;
if (projectId) loadProject();
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -207,6 +214,15 @@ export default function LabelStudioTextEditor() {
return;
}
if (msg.type === "LS_READY") {
const readyTaskId = msg.payload?.taskId;
if (expectedTaskIdRef.current && readyTaskId) {
if (Number(readyTaskId) !== expectedTaskIdRef.current) return;
}
setLsReady(true);
return;
}
if (msg.type === "LS_EXPORT_RESULT") {
saveFromExport(msg.payload);
return;
@@ -220,6 +236,7 @@ export default function LabelStudioTextEditor() {
if (msg.type === "LS_ERROR") {
message.error(msg.payload?.message || "编辑器发生错误");
setLsReady(false);
}
};
@@ -332,9 +349,17 @@ export default function LabelStudioTextEditor() {
<Card title="编辑器" className="flex-1 h-full flex flex-col" bodyStyle={{ padding: 0, flex: 1, overflow: "hidden" }}>
<div className="relative h-full">
{loadingTaskDetail && (
{(!iframeReady || loadingTaskDetail || (selectedFileId && !lsReady)) && (
<div className="absolute inset-0 z-10 flex items-center justify-center bg-white/70">
<Spin />
<Spin
tip={
!iframeReady
? "编辑器资源加载中..."
: loadingTaskDetail
? "任务数据加载中..."
: "编辑器初始化中..."
}
/>
</div>
)}
<iframe