引导移动端创作主页使用桌面端

移动端直达 /creation 时展示桌面端打开引导

补充移动端创作主页回归测试

同步创作主页与玩法链路文档口径
This commit is contained in:
2026-06-22 19:09:55 +08:00
parent 7b2903496e
commit b03b6b0c13
5 changed files with 78 additions and 9 deletions
@@ -67,7 +67,7 @@
## 2026-06-18 `/creation` 独立为陶泥儿创作工具主页
- 背景:图片画布项目已经成为独立项目资产,旧“创作”站内 Tab 和一级“草稿”入口不能清晰表达桌面端创作工具主页与项目管理入口。
- 决策:桌面端新增独立 `/creation` 创作工具主页,桌面端直接打开站点首页 `/` 时也默认展示新版创作主页;顶级“创作”入口跳转 `/creation`,原“草稿”入口替换为“项目”并跳转 `/project`。移动端首页 `/` 继续保持原推荐首页,移动端隐藏“创作”和“项目”入口,但不拦截直接 URL。页面文案统一使用“陶泥儿”,外部品牌只作为设计参考,不进入用户可见 UI、测试名、产品文案或验收口径。`陶泥儿精选` 是用户素材瀑布流,不展示玩法入口列表;创作入口事实源继续来自 `/api/creation-entry/config`,项目入口通过 `createEditorProject``/editor/canvas?projectid=xxx` 链路进入画布。
- 决策:桌面端新增独立 `/creation` 创作工具主页,桌面端直接打开站点首页 `/` 时也默认展示新版创作主页;顶级“创作”入口跳转 `/creation`,原“草稿”入口替换为“项目”并跳转 `/project`。移动端首页 `/` 继续保持原推荐首页,移动端隐藏“创作”和“项目”入口;移动端直达 `/creation` 时不加载创作主页,显示桌面端打开引导,`/creation/<play>` 玩法工作台直达仍按原链路进入。页面文案统一使用“陶泥儿”,外部品牌只作为设计参考,不进入用户可见 UI、测试名、产品文案或验收口径。`陶泥儿精选` 是用户素材瀑布流,不展示玩法入口列表;创作入口事实源继续来自 `/api/creation-entry/config`,项目入口通过 `createEditorProject``/editor/canvas?projectid=xxx` 链路进入画布。
- 影响范围:平台入口导航、`SelectionStage` 路由、`/creation` 首页、`/project` 项目入口、`/editor/canvas` 项目打开链路、“我的”页快捷入口和创作入口相关测试。
- 验证方式:桌面 `/` 初始阶段和 `/creation` 解析为创作主页,移动端 `/` 仍是推荐首页,`/creation/<play>` 仍进入对应玩法工作台;桌面导航显示“创作 / 项目”且不显示“草稿”;移动端底部不显示“创作 / 项目”;页面不出现外站品牌或 `Discord` 字样;新建项目进入 `/editor/canvas?projectid=xxx`
- 关联文档:`docs/【玩法创作】创作主页与项目入口改版计划-2026-06-18.md``docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
@@ -13,7 +13,7 @@
- 新增桌面端独立 `/creation` 创作工具主页。
- 桌面端直接打开站点首页 `/` 时默认展示新版创作主页内容;移动端继续保持原推荐首页。
- 顶级导航中“创作”进入 `/creation`,“草稿”改为“项目”并进入 `/project`
- 移动端隐藏“创作”和“项目”入口,只保留浏览和个人相关入口。
- 移动端隐藏“创作”和“项目”入口,只保留浏览和个人相关入口;移动端直达 `/creation` 时提示用户使用桌面端打开
- 登录后在创作主页展示最近项目,并通过新建项目进入 `/editor/canvas?projectid=xxx`
- `陶泥儿精选` 展示真实账号素材瀑布流,不使用 mock 素材。
- 现有 `/creation/<play>` 玩法工作台、草稿、作品架、生成恢复和发布链路保持不变。
@@ -128,7 +128,7 @@ Tab
- 桌面端从 `/creation` 切换到 `/project` 后,“项目”页签进入选中态,“创作”页签必须恢复为普通默认态,不保留创作主页的主按钮强调表现。
- `/project` 项目页头部必须提供 `返回主站` 按钮,点击后切回平台首页 `/`,行为与桌面侧栏切回推荐页保持一致。
- 移动端导航列表不展示“创作”和“项目”。
- 移动端不拦截用户直接访问 `/creation` `/project`
- 移动端直接访问 `/creation` 时显示桌面端打开引导,不加载创作工具主页;`/creation/<play>` 继续直达对应玩法工作台。`/project` 暂不新增移动端拦截
## 实施拆分
@@ -137,7 +137,7 @@ Tab
- 增加 `/creation` 路由映射和测试。
- 增加桌面 `/` 初始阶段映射测试,确认不会影响移动端首页。
- 调整桌面导航文案与点击行为。
- 移动端导航移除“创作”和“项目”入口。
- 移动端导航移除“创作”和“项目”入口,并为直达 `/creation` 增加桌面端打开引导
- 保持现有 `/creation/<play>` 工作台、生成页、结果页和运行态路由不回归。
### 创作主页
@@ -194,6 +194,7 @@ git diff --check
- 桌面导航显示“项目”,不显示“草稿”。
- `/project` 头部点击“返回主站”回到 `/`,并退出项目页主内容。
- 移动视口底部不显示“创作”和“项目”。
- 移动端直达 `/creation` 显示“请在桌面端打开创作主页”,点击“返回首页”回到 `/`
- “我的”页没有项目快捷入口。
- 陶泥儿精选素材瀑布流不出现 mock 素材、假作者或假泥点成本。
- 陶泥儿精选素材卡按真实素材宽高呈现瀑布流,不退化为固定等高网格。
@@ -205,4 +206,5 @@ git diff --check
- 不删除现有玩法草稿、作品架、生成恢复、发布或运行态能力。
- 不恢复前端硬编码创作入口配置。
- 不用 mock 素材填充用户素材展示。
-在移动端禁止直接 URL 访问 `/creation``/project`
-影响 `/creation/<play>` 玩法工作台、生成页、结果页和运行态直达恢复
- 不在本轮拦截移动端直接 URL 访问 `/project`
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
import { Loader2 } from 'lucide-react';
import { Home, Loader2, Monitor } from 'lucide-react';
import { AnimatePresence, motion } from 'motion/react';
import {
@@ -1636,6 +1636,45 @@ function CreationResultRecoveryPanel({
);
}
function MobileCreationDesktopGuide({
onReturnHome,
}: {
onReturnHome: () => void;
}) {
return (
<main
className="flex min-h-full flex-1 items-center justify-center px-4 py-8"
aria-label="桌面端创作提示"
>
<PlatformSubpanel
as="section"
radius="xl"
padding="none"
className="platform-remap-surface w-full max-w-sm px-5 py-6 text-center"
>
<span className="mx-auto flex h-14 w-14 items-center justify-center rounded-[1.05rem] bg-[rgba(199,101,50,0.12)] text-[var(--platform-accent-strong)]">
<Monitor aria-hidden="true" className="h-7 w-7" />
</span>
<h1 className="mt-4 text-xl font-black leading-tight text-[var(--platform-text-strong)]">
</h1>
<p className="mt-3 text-sm font-semibold leading-6 text-[var(--platform-text-base)]">
</p>
<PlatformActionButton
onClick={onReturnHome}
size="md"
shape="pill"
className="mt-5 min-h-11 w-full"
>
<Home aria-hidden="true" className="h-4 w-4" />
</PlatformActionButton>
</PlatformSubpanel>
</main>
);
}
export function PlatformEntryFlowShellImpl({
selectionStage,
setSelectionStage,
@@ -15238,7 +15277,7 @@ export function PlatformEntryFlowShellImpl({
'works-only',
'正在加载草稿列表...',
);
const creationLandingContent = (
const creationLandingContent = isDesktopLayout ? (
<Suspense fallback={<LazyPanelFallback label="正在加载创作主页..." />}>
<CreationLandingView
onOpenProject={openEditorProject}
@@ -15250,6 +15289,14 @@ export function PlatformEntryFlowShellImpl({
]}
/>
</Suspense>
) : (
<MobileCreationDesktopGuide
onReturnHome={() => {
pushAppHistoryPath('/');
platformBootstrap.setPlatformTab('home');
setSelectionStage('platform', { path: '/' });
}}
/>
);
const projectGalleryContent = (
<Suspense fallback={<LazyPanelFallback label="正在加载项目..." />}>
@@ -9267,13 +9267,22 @@ test('project page header can return to main site', async () => {
expect(window.location.pathname).toBe('/');
});
test('direct mobile creation home keeps landing content without mobile nav entry', async () => {
test('direct mobile creation home guides users to desktop without mobile nav entry', async () => {
const user = userEvent.setup();
window.history.replaceState(null, '', '/creation');
const { container } = render(<TestWrapper withAuth />);
expect(
await screen.findByRole('main', { name: '陶泥儿创作主页' }),
await screen.findByRole('main', { name: '桌面端创作提示' }),
).toBeTruthy();
expect(screen.getByText('请在桌面端打开创作主页')).toBeTruthy();
expect(
screen.getByText('图片画布、项目管理和素材库需要更大的操作空间。'),
).toBeTruthy();
expect(
screen.queryByRole('main', { name: '陶泥儿创作主页' }),
).toBeNull();
const bottomNav = container.querySelector('.platform-bottom-nav');
expect(bottomNav).toBeTruthy();
expect(
@@ -9282,6 +9291,15 @@ test('direct mobile creation home keeps landing content without mobile nav entry
expect(
within(bottomNav as HTMLElement).queryByRole('button', { name: '项目' }),
).toBeNull();
await user.click(screen.getByRole('button', { name: //u }));
await waitFor(() => {
expect(window.location.pathname).toBe('/');
expect(
screen.queryByRole('main', { name: '桌面端创作提示' }),
).toBeNull();
});
});
test('embedded puzzle form timeout exits busy state and shows a readable error', async () => {