fix: refine jump hop draft detail flow

This commit is contained in:
2026-06-06 21:02:11 +08:00
parent cd8088d1fd
commit 683a9115b3
11 changed files with 194 additions and 9 deletions

View File

@@ -83,6 +83,24 @@ test('跳一跳结果页默认角色预览使用陶泥儿透明 logo', () => {
);
});
test('跳一跳结果页根容器允许移动端向下滚动到操作按钮', () => {
const { container } = render(
<JumpHopResultView
profile={buildProfile()}
onBack={() => {}}
onEdit={() => {}}
onStartTestRun={() => {}}
onPublish={() => {}}
onRegenerateTiles={() => {}}
/>,
);
const root = container.firstElementChild as HTMLElement;
expect(root.className).toContain('overflow-y-auto');
expect(root.className).toContain('overscroll-contain');
expect(root.className).toContain('safe-area-inset-bottom');
});
test('跳一跳草稿结果页不请求公开排行榜', () => {
render(
<JumpHopResultView

View File

@@ -300,7 +300,7 @@ export function JumpHopResultView({
};
return (
<div className="platform-remap-surface mx-auto flex h-full min-h-0 w-full max-w-5xl flex-col px-3 pb-3 pt-3 sm:px-4 sm:pt-4">
<div className="platform-remap-surface mx-auto flex h-full min-h-0 w-full max-w-5xl flex-col overflow-y-auto overscroll-contain px-3 pb-[max(1.5rem,env(safe-area-inset-bottom))] pt-3 sm:px-4 sm:pt-4">
<div className="mb-3 flex items-center justify-between gap-3">
<button
type="button"

View File

@@ -12878,12 +12878,18 @@ export function PlatformEntryFlowShellImpl({
}
try {
const detail = await jumpHopClient.getWorkDetail(item.profileId);
const detail = await jumpHopClient.getWorkDetail(item.profileId, {
audience: 'creation',
});
setJumpHopSession(null);
setJumpHopRun(null);
setJumpHopWork(detail.item);
setJumpHopRuntimeReturnStage('jump-hop-result');
enterCreateTab();
pushAppHistoryPath('/creation/jump-hop/result');
writeCreationUrlState(
buildJumpHopCreationUrlState({ work: detail.item }),
);
setSelectionStage('jump-hop-result');
} catch (error) {
setJumpHopError(
@@ -14073,7 +14079,11 @@ export function PlatformEntryFlowShellImpl({
let work: JumpHopWorkProfileResponse | null = null;
try {
if (profileId) {
work = (await jumpHopClient.getWorkDetail(profileId)).item;
work = (
await jumpHopClient.getWorkDetail(profileId, {
audience: 'creation',
})
).item;
}
} catch {
work = null;

View File

@@ -8055,10 +8055,84 @@ test('direct jump hop result route restores work detail by profile id', async ()
expect(screen.queryByText('跳一跳草稿未恢复')).toBeNull();
expect(jumpHopClient.getWorkDetail).toHaveBeenCalledWith(
'jump-hop-profile-restore-1',
{ audience: 'creation' },
);
expect(jumpHopClient.getSession).not.toHaveBeenCalled();
});
test('completed unpublished jump hop draft opens result page without starting runtime', async () => {
const user = userEvent.setup();
const work = buildMockJumpHopWork({
summary: {
runtimeKind: 'jump-hop',
workId: 'jump-hop-work-draft-ready-1',
profileId: 'jump-hop-profile-draft-ready-1',
ownerUserId: 'user-1',
sourceSessionId: 'jump-hop-session-draft-ready-1',
themeText: '未发布跳一跳草稿',
workTitle: '未发布跳一跳草稿',
workDescription: '已经生成完成,但还没有发布。',
themeTags: ['草稿'],
difficulty: 'standard',
stylePreset: 'paper-toy',
coverImageSrc: null,
publicationStatus: 'draft',
playCount: 0,
updatedAt: '2026-05-30T10:00:00.000Z',
publishedAt: null,
publishReady: true,
generationStatus: 'ready',
},
});
vi.mocked(jumpHopClient.listWorks).mockResolvedValue({
items: [work.summary],
});
vi.mocked(jumpHopClient.getWorkDetail).mockResolvedValueOnce({
item: work,
} satisfies JumpHopWorkDetailResponse);
vi.mocked(fetchCreationEntryConfig).mockResolvedValueOnce({
...testCreationEntryConfig,
creationTypes: [
...testCreationEntryConfig.creationTypes,
{
id: 'jump-hop',
title: '跳一跳',
subtitle: '主题驱动平台跳跃',
badge: '可创建',
imageSrc: '/creation-type-references/jump-hop.webp',
visible: true,
open: true,
sortOrder: 55,
categoryId: 'recommended',
categoryLabel: '热门推荐',
categorySortOrder: 20,
updatedAtMicros: 1,
},
],
});
render(<TestWrapper withAuth />);
await openDraftHub(user);
const draftPanel = getPlatformTabPanel('saves');
await user.click(
await within(draftPanel).findByRole('button', {
name: /继续创作《未发布跳一跳草稿》/u,
}),
);
expect(await screen.findByText('未发布跳一跳草稿')).toBeTruthy();
expect(jumpHopClient.getWorkDetail).toHaveBeenCalledWith(
'jump-hop-profile-draft-ready-1',
{ audience: 'creation' },
);
expect(jumpHopClient.startRun).not.toHaveBeenCalled();
expect(window.location.pathname).toBe('/creation/jump-hop/result');
expect(window.location.search).toContain(
'profileId=jump-hop-profile-draft-ready-1',
);
});
test('embedded puzzle form maps raw bearer token errors to user-facing auth copy', async () => {
const user = userEvent.setup();