fix: isolate rectification UI mutations

This commit is contained in:
Jesse_Chen
2026-07-21 04:48:30 +08:00
parent 741a395a77
commit c68f4e5f4f
5 changed files with 444 additions and 53 deletions
@@ -99,7 +99,9 @@ export function ConversationalRectificationSurface({
const abandonTrigger = useRef<HTMLButtonElement>(null);
const abandonCancel = useRef<HTMLButtonElement>(null);
const abandonConfirm = useRef<HTMLButtonElement>(null);
const terminalStatus = useRef<HTMLDivElement>(null);
const restoreAbandonFocus = useRef(false);
const focusTerminalForCase = useRef<string | null>(null);
const turn = controller.turn;
const pendingQuestion = turn?.pendingConsultationQuestion ?? pendingConsultationQuestion ?? null;
const abandonIdentity = turn
@@ -126,6 +128,19 @@ export function ConversationalRectificationSurface({
}
}, [abandonArmed]);
useEffect(() => {
const requestedCase = focusTerminalForCase.current;
if (!requestedCase) return;
if (!turn || turn.caseId !== requestedCase) {
focusTerminalForCase.current = null;
return;
}
if (turn.status === "abandoned") {
focusTerminalForCase.current = null;
terminalStatus.current?.focus();
}
}, [turn]);
if (!turn) {
return (
<section className="conversational-rectification" aria-busy={controller.pending} aria-label="生时校正对话">
@@ -179,6 +194,14 @@ export function ConversationalRectificationSurface({
abandonCancel.current?.focus();
}
};
const confirmAbandon = () => {
focusTerminalForCase.current = turn.caseId;
void controller.abandon().catch(() => {
if (focusTerminalForCase.current === turn.caseId) {
focusTerminalForCase.current = null;
}
});
};
return (
<section
@@ -300,7 +323,13 @@ export function ConversationalRectificationSurface({
</section>
)}
<div className="conversational-status" aria-live="polite">
<div
aria-label={turn.status === "abandoned" ? "生时校正终态" : undefined}
aria-live="polite"
className="conversational-status"
ref={terminalStatus}
tabIndex={turn.status === "abandoned" ? -1 : undefined}
>
{turn.status === "paused" && <p></p>}
{turn.status === "abandoned" && <p></p>}
{turn.status === "completed" && turn.candidate.status === "confirmed"
@@ -389,7 +418,7 @@ export function ConversationalRectificationSurface({
disabled={controller.pending}
ref={abandonConfirm}
type="button"
onClick={() => safely(controller.abandon())}
onClick={confirmAbandon}
>
</button>