fix: keep rectification questions context-aware

This commit is contained in:
Jesse_Chen
2026-07-30 07:58:06 +08:00
parent eb303c7089
commit e9d20382d9
12 changed files with 322 additions and 71 deletions
+37 -19
View File
@@ -24,6 +24,16 @@ function friendly(error: unknown): string {
return error instanceof Error ? error.message : "暂时无法处理,请稍后再试。";
}
export function applyRectificationV4JobUpdate(
data: RectificationV4ApiResponse | null,
job: RectificationV4Job,
): RectificationV4ApiResponse | null {
if (data?.job?.id !== job.id) return data;
if (["completed", "failed", "stale"].includes(data.job.status)) return data;
if (job.updatedAt < data.job.updatedAt) return data;
return { ...data, job };
}
export function useRectificationV4(input: {
readonly pendingConsultationQuestion?: string | null;
readonly onPendingChange?: (pending: boolean) => void;
@@ -31,13 +41,17 @@ export function useRectificationV4(input: {
const onPendingChange = input.onPendingChange;
const pendingConsultationQuestion = input.pendingConsultationQuestion?.trim() || null;
const [data, setData] = useState<RectificationV4ApiResponse | null>(null);
const [job, setJob] = useState<RectificationV4Job | null>(null);
const [handoff, setHandoff] = useState<RectificationV4Handoff | null>(null);
const [loading, setLoading] = useState(true);
const [pending, setPending] = useState(false);
const [error, setError] = useState("");
const mounted = useRef(true);
const job = data?.job ?? null;
const jobId = job?.id ?? null;
const jobStatus = job?.status ?? null;
const caseId = data?.case.id ?? null;
const setBusy = useCallback((value: boolean) => {
setPending(value);
onPendingChange?.(value);
@@ -47,7 +61,6 @@ export function useRectificationV4(input: {
const result = caseId ? await loadRectificationV4(caseId) : await loadActiveRectificationV4();
if (mounted.current) {
setData(result);
setJob(result?.job ?? null);
}
return result;
}, []);
@@ -74,7 +87,6 @@ export function useRectificationV4(input: {
}
if (mounted.current) {
setData(result);
setJob(result.job);
setHandoff(nextHandoff);
}
} catch (caught) {
@@ -87,23 +99,30 @@ export function useRectificationV4(input: {
}, [pendingConsultationQuestion]);
useEffect(() => {
const jobId = job?.id;
if (!jobId || !["pending", "processing"].includes(job.status)) return;
const timer = window.setInterval(() => {
void loadRectificationV4Job(jobId).then(async (next) => {
if (!mounted.current) return;
setJob(next);
if (["completed", "failed", "stale"].includes(next.status) && data) {
window.clearInterval(timer);
const latest = await refresh(data.case.id);
if (!jobId || !jobStatus || !["pending", "processing"].includes(jobStatus)) return;
let cancelled = false;
let timer: number | null = null;
const poll = async () => {
try {
const next = await loadRectificationV4Job(jobId);
if (cancelled || !mounted.current) return;
setData((current) => applyRectificationV4JobUpdate(current, next));
if (["completed", "failed", "stale"].includes(next.status) && caseId) {
const latest = await refresh(caseId);
if (next.status === "failed" && latest) setError("这次比较没有完成,回答已经保留,请再试一次。");
return;
}
}).catch((caught) => {
if (mounted.current) setError(friendly(caught));
});
}, 1_000);
return () => window.clearInterval(timer);
}, [data, job, refresh]);
} catch (caught) {
if (!cancelled && mounted.current) setError(friendly(caught));
}
if (!cancelled) timer = window.setTimeout(() => void poll(), 1_000);
};
timer = window.setTimeout(() => void poll(), 1_000);
return () => {
cancelled = true;
if (timer !== null) window.clearTimeout(timer);
};
}, [caseId, jobId, jobStatus, refresh]);
const mutate = useCallback(async (operation: () => Promise<RectificationV4ApiResponse>) => {
setBusy(true);
@@ -112,7 +131,6 @@ export function useRectificationV4(input: {
const result = await operation();
if (mounted.current) {
setData(result);
setJob(result.job);
}
return result;
} catch (caught) {