diff --git a/docs/technical/MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md b/docs/technical/MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md new file mode 100644 index 00000000..c26481d8 --- /dev/null +++ b/docs/technical/MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md @@ -0,0 +1,394 @@ +# 抓大鹅 Match3D F2 结果页与发布技术方案 + +日期:`2026-04-30` + +## 1. 文档目的 + +本文件承接 [MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md](./MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md),只冻结 F2 开发范围: + +1. Match3D 待发布结果页。 +2. 作品基础信息编辑。 +3. 发布前试玩入口。 +4. 发布入口。 +5. 已发布作品二次编辑恢复口径。 + +本阶段不实现运行态即时反馈 UI,不实现 SpacetimeDB 表与 procedure,不实现 `api-server` facade。F2 可以先基于 shared contracts 与 mock client 开发,等待 B4+B5 接入真实 HTTP。 + +--- + +## 2. 前置依赖 + +F2 依赖以下已冻结文档: + +1. PRD:[AI_NATIVE_MATCH3D_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-04-30.md](../prd/AI_NATIVE_MATCH3D_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-04-30.md) +2. A0:[MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md](./MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md) +3. B1+B2:[MATCH3D_DOMAIN_AND_CONTRACTS_STAGE1_2026-04-30.md](./MATCH3D_DOMAIN_AND_CONTRACTS_STAGE1_2026-04-30.md) + +F2 可在 B4+B5 之前并行开发,但必须遵守 B2 的 TypeScript contract,不得在前端私自扩字段。 + +--- + +## 3. 本阶段做 + +1. 新增 Match3D 结果页组件目录。 +2. 新增 Match3D works service 目录。 +3. 展示草稿配置摘要: + - 题材主题 + - 需要消除次数 + - 难度 + - 参考图片预览 +4. 支持编辑发布基础信息: + - 游戏名称 + - 标签 + - 封面图 +5. 支持发布前试玩入口。 +6. 支持试玩中止后回到结果页继续编辑。 +7. 支持发布入口。 +8. 支持已发布作品二次编辑的前端恢复路径。 + +--- + +## 4. 本阶段不做 + +1. 不生成题材物品素材。 +2. 不生成额外封面图;封面图只接收已有图片、上传图片或后端已有占位结果。 +3. 不要求试玩通关后才能发布。 +4. 不实现运行态点击、飞入、三消等即时反馈。 +5. 不实现首页、分类页和广场投影。 +6. 不实现排行榜。 +7. 不在 UI 中默认展示玩法规则说明长文。 +8. 不把发布校验只写在前端;前端只做即时提示,后端 publish gate 是最终门槛。 + +--- + +## 5. 文件落点 + +## 5.1 前端组件 + +新增: + +```text +src/components/match3d-result/ +``` + +建议文件: + +```text +src/components/match3d-result/Match3DResultView.tsx +src/components/match3d-result/Match3DResultView.test.tsx +src/components/match3d-result/index.ts +``` + +如组件变大,可后续拆分: + +```text +Match3DResultHeader.tsx +Match3DResultBasicsForm.tsx +Match3DResultConfigPreview.tsx +Match3DResultPublishPanel.tsx +``` + +首版不要过早拆太多文件,优先保持可读和低冲突。 + +## 5.2 前端 service + +新增: + +```text +src/services/match3d-works/ +``` + +建议文件: + +```text +src/services/match3d-works/match3dWorksClient.ts +src/services/match3d-works/index.ts +``` + +F2 只负责 works 维度: + +1. 读取作品详情。 +2. 更新作品基础信息。 +3. 发布作品。 +4. 删除作品可后置,若 F4 需要再补。 + +运行态启动接口归 `src/services/match3d-runtime/`,F2 只调用上层传入的 `onStartTestRun`。 + +--- + +## 6. shared contracts 使用 + +F2 只消费 B2 已冻结的 TypeScript contract: + +```text +packages/shared/src/contracts/match3dWorks.ts +packages/shared/src/contracts/match3dAgent.ts +packages/shared/src/contracts/match3dRuntime.ts +``` + +必要类型: + +1. `Match3DWorkProfile` +2. `Match3DWorkSummary` +3. `Match3DWorkUpdateRequest` +4. `Match3DPublishRequest` +5. `Match3DPublishResult` +6. `Match3DCompileDraftResult` +7. `Match3DCreatorConfig` + +F2 不新增独立的前端私有数据结构来表达作品真相;只允许使用局部表单状态承载未保存输入。 + +--- + +## 7. 结果页 props contract + +建议 `Match3DResultView` props: + +```ts +type Match3DResultViewProps = { + profile: Match3DWorkProfile; + draft?: Match3DCompileDraftResult | null; + isBusy?: boolean; + error?: string | null; + onBack: () => void; + onStartTestRun: (profile: Match3DWorkProfile) => void; + onPublish: (payload: Match3DPublishRequest) => void; + onSaved?: (profile: Match3DWorkProfile) => void; +}; +``` + +说明: + +1. `profile` 是结果页当前作品真相源。 +2. `draft` 只用于展示草稿生成附加信息;不能覆盖 `profile` 的发布字段。 +3. `onStartTestRun` 进入 F3/B5 运行态链路。 +4. `onPublish` 可以先由 mock client 实现,B5 完成后替换为真实 HTTP。 +5. `onSaved` 用于把自动保存后的 profile 回写给上层流程控制器。 + +--- + +## 8. 页面内容顺序 + +结果页保持单列表,不做多 Tab。 + +固定顺序: + +1. 顶部返回与保存状态。 +2. 封面图。 +3. 游戏名称。 +4. 标签。 +5. 题材主题。 +6. 需要消除次数。 +7. 难度。 +8. 参考图片预览。 +9. 试玩按钮。 +10. 发布按钮。 + +UI 只呈现必要信息,不在页面中展示玩法规则说明长文。 + +--- + +## 9. 字段编辑规则 + +## 9.1 游戏名称 + +1. 必填。 +2. 首版建议前端限制 `1~30` 个中文字符等价长度。 +3. 默认值来自 Agent 确认题材或系统生成草稿。 + +## 9.2 标签 + +1. 必填。 +2. 首版建议 `3~6` 个标签,与拼图发布门槛保持一致。 +3. 输入支持中文逗号、英文逗号、顿号、换行拆分。 +4. 前端需要去重和去空格。 + +## 9.3 封面图 + +1. 必填。 +2. F2 可先复用参考图片、占位封面或用户上传图。 +3. 图片真实存储由现有资产链或后续 B5 facade 处理。 +4. 前端不得把本地临时 blob URL 当作已发布封面真相。 + +## 9.4 题材主题、需要消除次数、难度 + +首版结果页允许展示并可编辑这些配置。 + +修改后必须同步保存到作品 profile: + +1. `themeText` +2. `clearCount` +3. `difficulty` + +注意: + +1. `clearCount` 必须为正整数。 +2. `difficulty` 必须在 `1~10`。 +3. 修改配置后,下一次试玩必须基于最新保存配置启动。 + +--- + +## 10. 自动保存 + +F2 建议实现自动保存,口径参考拼图结果页: + +1. 输入变更后 `600ms` debounce。 +2. 只保存结果页可编辑字段。 +3. 保存中展示轻量状态。 +4. 保存失败展示轻量错误,不弹长说明。 +5. 发布前必须等待最后一次保存完成,或发布 payload 直接携带当前表单字段。 + +建议状态: + +```ts +type Match3DAutoSaveState = 'idle' | 'saving' | 'saved' | 'error'; +``` + +--- + +## 11. 发布门槛 + +前端即时 blocker: + +1. 游戏名称为空。 +2. 标签数量不在 `3~6`。 +3. 封面图为空。 +4. `clearCount` 不是正整数。 +5. `difficulty` 不在 `1~10`。 + +后端 publish gate 是最终门槛,前端不得绕过。 + +发布不要求试玩通关。 + +--- + +## 12. 试玩入口 + +结果页提供“试玩”入口。 + +行为: + +1. 点击试玩前先保存当前表单。 +2. 保存成功后调用 `onStartTestRun(profile)`。 +3. 上层进入 Match3D 运行态。 +4. 运行态停止或返回后,回到同一个结果页继续编辑。 + +F2 不实现运行态本身;只冻结结果页如何发起试玩。 + +--- + +## 13. 发布接口 + +F2 service 建议接口: + +```ts +const MATCH3D_WORKS_API_BASE = '/api/creation/match3d/works'; + +export async function getMatch3DWorkDetail(profileId: string): Promise; + +export async function updateMatch3DWork( + profileId: string, + payload: Match3DWorkUpdateRequest, +): Promise; + +export async function publishMatch3DWork( + profileId: string, + payload: Match3DPublishRequest, +): Promise; +``` + +后续 B5 必须提供同名 HTTP facade 或在 service 层做最小适配。 + +--- + +## 14. Mock client 口径 + +F2 可以在真实 B5 接口完成前使用 mock client。 + +要求: + +1. mock 数据必须来自 shared contracts。 +2. mock profile 字段必须覆盖发布必填项。 +3. mock publish 只能返回“可发布成功”的本地结果,不得伪造平台广场投影。 +4. B5 接入后,mock 只能保留为测试 fixture。 + +--- + +## 15. 已发布作品二次编辑 + +进入自己已发布 Match3D 作品时,结果页应支持二次编辑。 + +规则: + +1. 优先通过 `sourceSessionId` 恢复原创作 session。 +2. 如果没有 session,则通过 `profileId` 读取作品详情进入结果页。 +3. 二次发布不得创建新作品,必须覆盖同一 `profileId`。 +4. 不清零 `playCount`。 +5. 不改变作品归属。 + +--- + +## 16. 与其它分支的接口边界 + +## 16.1 依赖 F1 + +F1 负责创建会话和 Agent UI。F2 接收 F1 编译出的 `profile / draft`,不重复实现 Agent 对话。 + +## 16.2 依赖 F3 + +F3 负责运行态 UI。F2 只提供 `onStartTestRun` 入口。 + +## 16.3 依赖 B5 + +B5 负责真实 HTTP facade。F2 的 service path 和 DTO 必须按本文冻结,避免后续替换 mock 时改组件结构。 + +## 16.4 依赖 F4 + +F4 负责首页、分类页和广场分发。F2 发布成功后只需要把返回 profile 交给上层;不直接刷新广场列表。 + +--- + +## 17. 测试要求 + +建议新增: + +```text +src/components/match3d-result/Match3DResultView.test.tsx +``` + +覆盖: + +1. 展示游戏名称、标签、封面图、题材、需要消除次数和难度。 +2. 游戏名称为空时发布按钮阻断。 +3. 标签数量不足时发布按钮阻断。 +4. `clearCount` 非正整数时发布按钮阻断。 +5. `difficulty` 超出 `1~10` 时发布按钮阻断。 +6. 点击试玩前触发保存。 +7. 发布不要求试玩通关。 + +service 测试可在 B5 接入后补齐。 + +--- + +## 18. 验收命令 + +F2 文档分支: + +```powershell +npm run check:encoding -- docs/technical/MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md docs/technical/README.md +``` + +F2 前端实现分支: + +```powershell +npm run check:encoding +npm run typecheck +``` + +如新增组件测试,补跑对应 `vitest`。 + +--- + +## 19. 一句话结论 + +F2 只负责把 Match3D 草稿变成可编辑、可试玩、可发布的作品工作台;它必须复用平台结果页和发布体验,发布不要求试玩通关,并为 B5 真实后端接口与 F3 运行态试玩入口保留清晰边界。 diff --git a/docs/technical/README.md b/docs/technical/README.md index c090e18b..5153be57 100644 --- a/docs/technical/README.md +++ b/docs/technical/README.md @@ -8,6 +8,7 @@ - [MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md](./MATCH3D_CREATION_AND_RUNTIME_MINIMAL_IMPLEMENTATION_2026-04-30.md):冻结抓大鹅 Match3D 首版 demo 的独立玩法域、表与 procedure、HTTP facade、前端即时反馈/后端权威确认协议,以及可并行开发包。 - [MATCH3D_DOMAIN_AND_CONTRACTS_STAGE1_2026-04-30.md](./MATCH3D_DOMAIN_AND_CONTRACTS_STAGE1_2026-04-30.md):冻结抓大鹅 Match3D B1+B2 的纯领域规则 crate、Rust/TypeScript shared contracts,以及 Stage1 不触碰 SpacetimeDB 表和 api-server 的边界。 - [MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md](./MATCH3D_F1_CREATION_ENTRY_AND_AGENT_UI_2026-04-30.md):记录抓大鹅 F1 创作入口、Agent 工作区、参考图入口、本地 mock client 与后续 B5 HTTP facade 替换点。 +- [MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md](./MATCH3D_F2_RESULT_AND_PUBLISH_2026-04-30.md):冻结抓大鹅 F2 结果页、基础信息编辑、发布前试玩入口、发布门槛、自动保存和已发布作品二次编辑恢复口径。 - [PLATFORM_MOBILE_BOTTOM_DOCK_VIEWPORT_FIX_2026-04-30.md](./PLATFORM_MOBILE_BOTTOM_DOCK_VIEWPORT_FIX_2026-04-30.md):记录平台首页底部 dock 在手机浏览器地址栏展开时脱离可见区域的根因,以及 `100dvh`、固定底部锚点和安全区占位的修复口径。 - [SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md](./SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md):记录 SpacetimeDB private 表迁移 JSON 导出/导入 procedure、迁移操作员授权、HTTP 413 分片导入、Jenkins 自动迁移回灌和导入脚本参数。 - [JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md](./JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md):记录 `Genarrative-Database-Export` / `Genarrative-Database-Import` 两条 SCM-backed 数据库迁移流水线参数、默认 dry-run、token 边界和 `CHUNK_SIZE` 413 规避参数。