feat(ai-writing): 后台挂起改为即时返回,乐观标记历史「挂起中」
点击「转后台」后立刻 reset 回初始页,挂起请求 fire-and-forget; 历史下拉靠 markBackground/clearBackground 乐观标记马上显示「挂起中」, 不等后端确认,与「多智能体会商」交互一致。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
b59cbd51d9
commit
0a456e9146
2 files changed
+56
-15
No files matched your search
@@ -91,7 +91,7 @@ export function AIWritingPanel({
|
||||
const { state, startWriting, submitIntervention, pauseWriting, resumeWriting, reset } = useAIWriting();
|
||||
const { historySession, isHistoryMode, openHistory, closeHistory } = useAIWritingHistory();
|
||||
const writingForm = useWritingFormOptional();
|
||||
const { sessions, loading: sessionsLoading, refresh, rename, remove } = useAIWritingSessions();
|
||||
const { sessions, loading: sessionsLoading, refresh, rename, remove, markBackground, clearBackground } = useAIWritingSessions();
|
||||
const { articleTypes, refresh: refreshArticleTypes } = useArticleTypes();
|
||||
|
||||
useEffect(() => { refreshArticleTypes(); }, [refreshArticleTypes]);
|
||||
@@ -207,24 +207,31 @@ export function AIWritingPanel({
|
||||
}, [closeHistory, reset]);
|
||||
|
||||
// ── 后台挂起:把当前写作转后台,后端自动驱动到定稿(离页/刷新/切号不打断) ──
|
||||
const handleBackgroundSuspend = useCallback(async () => {
|
||||
// 与「多智能体会商」一致:点击后**立刻**回到初始页面,挂起请求 fire-and-forget;
|
||||
// 历史下拉靠乐观标记马上显示「挂起中」,不等后端确认。
|
||||
const handleBackgroundSuspend = useCallback(() => {
|
||||
const sid = state.sessionId;
|
||||
if (!sid) {
|
||||
toast.error('当前没有可挂起的写作会话');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await suspendAIWritingToBackground(sid);
|
||||
} catch (e) {
|
||||
toast.error(e instanceof Error ? e.message : '后台挂起失败');
|
||||
return;
|
||||
}
|
||||
toast.success('已转入后台自动完成,稍后可在「历史记录」查看进度与结果');
|
||||
// reset() 会 stop 客户端 SSE 订阅并回到 idle —— 后端驱动器接管续跑,不冲突。
|
||||
// 1) 立刻:乐观标记 + 重置 UI 回到 idle(reset() 会 stop 客户端 SSE 订阅,
|
||||
// 后端驱动器接管续跑,不冲突)。
|
||||
markBackground(sid);
|
||||
reset();
|
||||
// 刷新历史列表,让「挂起中」徽标立刻出现。
|
||||
refresh();
|
||||
}, [state.sessionId, reset, refresh]);
|
||||
toast.success('已转入后台自动完成,稍后可在「历史记录」查看进度与结果');
|
||||
// 2) 后台:fire-and-forget 通知后端拉起驱动;完成后刷新真实状态并清除乐观标记。
|
||||
void (async () => {
|
||||
try {
|
||||
await suspendAIWritingToBackground(sid);
|
||||
} catch (e) {
|
||||
toast.error(e instanceof Error ? e.message : '后台挂起失败');
|
||||
} finally {
|
||||
await refresh();
|
||||
clearBackground(sid);
|
||||
}
|
||||
})();
|
||||
}, [state.sessionId, reset, refresh, markBackground, clearBackground]);
|
||||
|
||||
// 离页 / 刷新 / 关标签页时,若写作仍在进行中则自动转后台(与圆桌「自动挂起」一致)。
|
||||
// 用 ref 持有最新的「是否在跑 + 会话 id」,让卸载/卸载前回调读到即时值。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import {
|
||||
listAIWritingSessions,
|
||||
@@ -10,6 +10,27 @@ import type { AIWritingSessionSummary } from '../api/ai-writing-sessions';
|
||||
export function useAIWritingSessions() {
|
||||
const [sessions, setSessions] = useState<AIWritingSessionSummary[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
// 「后台挂起」乐观标记:点击挂起后立刻让历史下拉显示「挂起中」,不必等后端确认。
|
||||
// 后端状态(status='background')刷新到位后由调用方 clearBackground 清除。
|
||||
const [pendingBackground, setPendingBackground] = useState<Set<string>>(() => new Set());
|
||||
|
||||
const markBackground = useCallback((id: string) => {
|
||||
setPendingBackground((prev) => {
|
||||
if (prev.has(id)) return prev;
|
||||
const next = new Set(prev);
|
||||
next.add(id);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const clearBackground = useCallback((id: string) => {
|
||||
setPendingBackground((prev) => {
|
||||
if (!prev.has(id)) return prev;
|
||||
const next = new Set(prev);
|
||||
next.delete(id);
|
||||
return next;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
setLoading(true);
|
||||
@@ -41,5 +62,18 @@ export function useAIWritingSessions() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { sessions, loading, refresh, rename, remove };
|
||||
// 把乐观「挂起中」标记叠加到真实列表上:已在列表里的会话立刻显示 background。
|
||||
const displaySessions = useMemo(
|
||||
() =>
|
||||
pendingBackground.size === 0
|
||||
? sessions
|
||||
: sessions.map((s) =>
|
||||
pendingBackground.has(s.id) && s.status !== 'done'
|
||||
? { ...s, status: 'background' }
|
||||
: s,
|
||||
),
|
||||
[sessions, pendingBackground],
|
||||
);
|
||||
|
||||
return { sessions: displaySessions, loading, refresh, rename, remove, markBackground, clearBackground };
|
||||
}
|
||||
Reference in new issue
Block a user