Add platform generation dialogs and task refresh

This commit is contained in:
kdletters
2026-05-26 19:40:23 +08:00
parent abea7cec1d
commit 4001ee0a5c
4 changed files with 58 additions and 10 deletions

View File

@@ -3404,6 +3404,7 @@ export function PlatformEntryFlowShellImpl({
}) })
| null | null
>(null); >(null);
const [profileTaskRefreshKey, setProfileTaskRefreshKey] = useState(0);
const [initialCreationUrlState] = useState(() => readCreationUrlState()); const [initialCreationUrlState] = useState(() => readCreationUrlState());
const handledInitialCreationUrlStateRef = useRef(false); const handledInitialCreationUrlStateRef = useRef(false);
const [initialPuzzleRuntimeUrlState] = useState(() => const [initialPuzzleRuntimeUrlState] = useState(() =>
@@ -3549,7 +3550,7 @@ export function PlatformEntryFlowShellImpl({
'ready', 'ready',
viewedImmediately, viewedImmediately,
); );
if (!viewedImmediately) { setProfileTaskRefreshKey((current) => current + 1);
const completedAtMs = Date.now(); const completedAtMs = Date.now();
setPendingPlatformTaskCompletionDialog({ setPendingPlatformTaskCompletionDialog({
key: `${kind}:${collectDraftNoticeKeys(kind, ids).join('|')}:${completedAtMs}`, key: `${kind}:${collectDraftNoticeKeys(kind, ids).join('|')}:${completedAtMs}`,
@@ -3557,7 +3558,6 @@ export function PlatformEntryFlowShellImpl({
message: '生成任务已完成,可以继续查看草稿。', message: '生成任务已完成,可以继续查看草稿。',
completedAtMs, completedAtMs,
}); });
}
}, },
[setPendingPlatformTaskCompletionDialog, updateDraftGenerationNotices], [setPendingPlatformTaskCompletionDialog, updateDraftGenerationNotices],
); );
@@ -14755,6 +14755,7 @@ export function PlatformEntryFlowShellImpl({
isLoadingPlatform={platformBootstrap.isLoadingPlatform} isLoadingPlatform={platformBootstrap.isLoadingPlatform}
isLoadingDashboard={platformBootstrap.isLoadingDashboard} isLoadingDashboard={platformBootstrap.isLoadingDashboard}
hasUnreadDraftUpdate={hasUnreadDraftUpdates} hasUnreadDraftUpdate={hasUnreadDraftUpdates}
profileTaskRefreshKey={profileTaskRefreshKey}
isDesktopLayout={isDesktopLayout} isDesktopLayout={isDesktopLayout}
isResumingSaveWorldKey={platformBootstrap.isResumingSaveWorldKey} isResumingSaveWorldKey={platformBootstrap.isResumingSaveWorldKey}
platformError={ platformError={

View File

@@ -7137,6 +7137,48 @@ test('persisted generating puzzle draft keeps session polling on the same sessio
expect(getPuzzleAgentSession).toHaveBeenCalledTimes(2); expect(getPuzzleAgentSession).toHaveBeenCalledTimes(2);
}); });
test('puzzle compile timeout shows failure dialog when reread session is still generating', async () => {
const user = userEvent.setup();
const runningSession = buildMockPuzzleAgentSession({
sessionId: 'puzzle-session-timeout',
draft: null,
stage: 'collecting_anchors',
progressPercent: 88,
lastAssistantReply: '正在生成拼图草稿。',
});
vi.mocked(createPuzzleAgentSession).mockResolvedValueOnce({
session: runningSession,
});
vi.mocked(executePuzzleAgentAction).mockRejectedValueOnce(
Object.assign(new Error('请求超时1800000ms'), {
name: 'TimeoutError',
}),
);
vi.mocked(getPuzzleAgentSession).mockResolvedValue({
session: runningSession,
});
render(<TestWrapper withAuth />);
await openCreateTemplateHub(user);
await user.click(await findCreationTypeButton('拼图'));
await user.click(await screen.findByRole('button', { name: '生成草稿' }));
const dialog = await screen.findByRole('dialog', { name: '发生错误' });
expect(within(dialog).getByText('拼图草稿 puzzle-session-timeout')).toBeTruthy();
expect(
within(dialog).getByText(
'拼图共创操作超时,请确认运行时后端已启动后重试。',
),
).toBeTruthy();
expect(within(dialog).getByRole('button', { name: '复制报错' })).toBeTruthy();
expect(
await screen.findByRole('progressbar', {
name: '拼图草稿生成进度',
}),
).toBeTruthy();
});
test('published puzzle work card restores its source session for editing', async () => { test('published puzzle work card restores its source session for editing', async () => {
const user = userEvent.setup(); const user = userEvent.setup();

View File

@@ -216,6 +216,7 @@ export interface RpgEntryHomeViewProps {
onOpenPlayedWork?: (work: ProfilePlayedWorkSummary) => void; onOpenPlayedWork?: (work: ProfilePlayedWorkSummary) => void;
onOpenFeedback?: () => void; onOpenFeedback?: () => void;
onRechargeSuccess?: () => void | Promise<void>; onRechargeSuccess?: () => void | Promise<void>;
profileTaskRefreshKey?: number;
createTabContent?: ReactNode; createTabContent?: ReactNode;
draftTabContent?: ReactNode; draftTabContent?: ReactNode;
hasUnreadDraftUpdate?: boolean; hasUnreadDraftUpdate?: boolean;
@@ -3983,6 +3984,7 @@ export function RpgEntryHomeView({
onOpenPlayedWork, onOpenPlayedWork,
onOpenFeedback, onOpenFeedback,
onRechargeSuccess, onRechargeSuccess,
profileTaskRefreshKey = 0,
createTabContent, createTabContent,
draftTabContent, draftTabContent,
hasUnreadDraftUpdate = false, hasUnreadDraftUpdate = false,
@@ -4798,7 +4800,7 @@ export function RpgEntryHomeView({
} }
loadTaskCenter(); loadTaskCenter();
}, [activeTab, isAuthenticated, loadTaskCenter]); }, [activeTab, isAuthenticated, loadTaskCenter, profileTaskRefreshKey]);
const openTaskCenterPanel = () => { const openTaskCenterPanel = () => {
setIsTaskCenterOpen(true); setIsTaskCenterOpen(true);

View File

@@ -9,6 +9,9 @@ import type { CustomWorldProfile } from '../../types';
export function resolveRpgEntryErrorMessage(error: unknown, fallback: string) { export function resolveRpgEntryErrorMessage(error: unknown, fallback: string) {
if (isTimeoutError(error)) { if (isTimeoutError(error)) {
if (//u.test(fallback) && /|||稿/u.test(fallback)) {
return '拼图共创操作超时,请确认运行时后端已启动后重试。';
}
if (//u.test(fallback)) { if (//u.test(fallback)) {
return '开启智能创作工作区超时,请确认运行时后端已启动后重试。'; return '开启智能创作工作区超时,请确认运行时后端已启动后重试。';
} }