Merge remote-tracking branch 'origin/master' into codex/wooden-fish-template

# Conflicts:
#	.hermes/shared-memory/decision-log.md
#	.hermes/shared-memory/pitfalls.md
#	docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md
#	src/components/platform-entry/PlatformEntryFlowShellImpl.tsx
This commit is contained in:
2026-05-26 02:00:11 +08:00
140 changed files with 12176 additions and 3526 deletions

View File

@@ -15,6 +15,10 @@
- [运营查询](./operations/README.md):任务、领奖、钱包对账等后台核查查询。
- [PRD](./prd/README.md):产品需求与阶段计划;参考 MOKU / 幕间类 AI 文游的陶泥儿 `text-game` 模板口径见 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md](./prd/AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_2026-05-05.md),视觉小说模板 TXT 玩法平台化接入口径见 [AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md](./prd/AI_NATIVE_VISUAL_NOVEL_TEMPLATE_PRD_2026-05-05.md),创意互动内容 Agent Phase 1 的 LangChain-Rust PoC、拼图闭环和并行任务拆分见 [CREATIVE_INTERACTIVE_AGENT_PHASE1_LANGCHAIN_RUST_PUZZLE_LOOP_PRD_2026-05-05.md](./prd/CREATIVE_INTERACTIVE_AGENT_PHASE1_LANGCHAIN_RUST_PUZZLE_LOOP_PRD_2026-05-05.md),幸存者类模板闭环见 [AI_NATIVE_SURVIVOR_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-05.md](./prd/AI_NATIVE_SURVIVOR_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-05.md),后台管理独立前端工程见 [ADMIN_WEB_CONSOLE_PRD_2026-04-30.md](./prd/ADMIN_WEB_CONSOLE_PRD_2026-04-30.md),新增 RPG 开场动画方案见 [AI_NATIVE_RPG_OPENING_ANIMATION_PRD_2026-04-25.md](./prd/AI_NATIVE_RPG_OPENING_ANIMATION_PRD_2026-04-25.md),新增抓大鹅 Match3D 玩法方案见 [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),方洞挑战创作、发布与试玩闭环见 [AI_NATIVE_SQUARE_HOLE_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-04.md](./prd/AI_NATIVE_SQUARE_HOLE_CREATOR_AND_GAMEPLAY_SYSTEM_PRD_2026-05-04.md),跳一跳俯视角玩法模板 PRD 见 [【玩法创作】跳一跳俯视角玩法模板PRD-2026-05-19.md](./prd/%E3%80%90%E7%8E%A9%E6%B3%95%E5%88%9B%E4%BD%9C%E3%80%91%E8%B7%B3%E4%B8%80%E8%B7%B3%E4%BF%AF%E8%A7%86%E8%A7%92%E7%8E%A9%E6%B3%95%E6%A8%A1%E6%9D%BFPRD-2026-05-19.md)。
拼图生成页步骤真进度、步骤内假进度和精简展示口径见 [【玩法创作】拼图生成页进度口径-2026-05-23.md](./%E3%80%90%E7%8E%A9%E6%B3%95%E5%88%9B%E4%BD%9C%E3%80%91%E6%8B%BC%E5%9B%BE%E7%94%9F%E6%88%90%E9%A1%B5%E8%BF%9B%E5%BA%A6%E5%8F%A3%E5%BE%84-2026-05-23.md)。
从文字需求生成高一致性美术素材流程抽象出的发明专利交底稿见 [【专利交底】一种极低成本快速生成高质量2D小游戏高一致性美术素材的解决方案-2026-05-25.md](./%E3%80%90%E4%B8%93%E5%88%A9%E4%BA%A4%E5%BA%95%E3%80%91%E4%B8%80%E7%A7%8D%E6%9E%81%E4%BD%8E%E6%88%90%E6%9C%AC%E5%BF%AB%E9%80%9F%E7%94%9F%E6%88%90%E9%AB%98%E8%B4%A8%E9%87%8F2D%E5%B0%8F%E6%B8%B8%E6%88%8F%E9%AB%98%E4%B8%80%E8%87%B4%E6%80%A7%E7%BE%8E%E6%9C%AF%E7%B4%A0%E6%9D%90%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88-2026-05-25.md)。
生产部署切换到 systemd + Nginx + SpacetimeDB 自托管的总方案见 [PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md](./technical/PRODUCTION_DEPLOYMENT_PLAN_2026-05-02.md),该文档也是当前生产 Jenkinsfile 的唯一入口。SpacetimeDB 表结构变更、自动迁移边界和保留旧数据的分阶段迁移流程见 [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md)private 表迁移 JSON 导入导出、HTTP 413 分片导入和旧数据库迁移流水线经验见 [SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md](./technical/SPACETIMEDB_JSON_STRING_MIGRATION_PROCEDURE_2026-04-27.md) 与 [JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md](./technical/JENKINS_SPACETIMEDB_DATABASE_MIGRATION_PIPELINES_2026-04-29.md);后台管理独立前端工程技术方案见 [ADMIN_WEB_CONSOLE_TECHNICAL_SOLUTION_2026-04-30.md](./technical/ADMIN_WEB_CONSOLE_TECHNICAL_SOLUTION_2026-04-30.md)。
SpacetimeDB 表结构变更、自动迁移边界和保留旧数据的分阶段迁移流程见 [SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md](./technical/SPACETIMEDB_SCHEMA_CHANGE_CONSTRAINTS.md)。

View File

@@ -0,0 +1,33 @@
# 创作 Tab 入口表单回切记录
> 说明本文件原本记录“空白入口页”实施计划。2026-05-24 已按产品反馈回切为点击玩法模板卡后直达既有入口创作表单,保留此文件作为历史回顾,避免后续误按旧计划继续实现空白页。
**Goal:** 创作 Tab 只展示赛事 banner、玩法模板分类和两列玩法卡点击卡片后直接进入对应玩法已有的入口创作表单而不是继续展示空白占位页。
**Architecture:** 保留现有创作大厅和入口配置事实源。创作大厅负责参考图 banner、分类 tabs 和入口卡片;平台壳层负责把卡片点击路由到对应玩法的既有入口表单 stage。入口表单继续承接各玩法自己的表单、草稿恢复和后续编排不再多套一层空白入口页。
**Current Route Mapping:**
- `/creation/rpg` -> `agent-workspace`
- `/creation/big-fish` -> `big-fish-agent-workspace`
- `/creation/match3d` -> `match3d-agent-workspace`
- `/creation/square-hole` -> `square-hole-agent-workspace`
- `/creation/jump-hop` -> `jump-hop-workspace`
- `/creation/wooden-fish` -> `wooden-fish-workspace`
- `/creation/puzzle` -> `puzzle-agent-workspace`
- `/creation/bark-battle` -> `bark-battle-workspace`
- `/creation/visual-novel` -> `visual-novel-agent-workspace`
- `/creation/baby-object-match` -> `baby-object-match-workspace`
**Verification:**
- `npm test -- src/routing/appPageRoutes.test.ts`
- `npm test -- src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "create tab opens match3d entry form from the template card|create tab opens puzzle entry form from the template card|create tab opens bark battle entry form from the template card"`
- `npm run typecheck`
- `npm run check:encoding`
**Notes:**
- 不再新增或保留 `*-workspace-entry` 空白 stage。
- `/creation/<play>` 是用户可直达的入口表单 URL。
- 旧的空白入口页方案已废弃;如需重新引入,必须先更新平台入口文档和本记录。

View File

@@ -0,0 +1,59 @@
# Profile Tab Mobile Layout Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Tighten the mobile `我的` Tab layout so typography, spacing, and fixed-height controls align with the rest of the platform UI and do not overlap the bottom dock.
**Architecture:** Keep the existing `RpgEntryHomeView` structure and update only page-specific class names plus CSS rules. Treat `src/index.css` as the platform token surface; document the mobile profile Tab acceptance criteria in the existing product / play-flow docs instead of creating a parallel doc.
**Tech Stack:** React, TypeScript, Tailwind utility classes, project CSS in `src/index.css`, Vitest, Vite local browser smoke.
---
### Task 1: Add Mobile Profile Layout Assertions
**Files:**
- Modify: `src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`
- [ ] Add expectations in `mobile profile page matches the reference layout sections` that the profile page, header, stats grid, daily task card, shortcut grid, and bottom dock expose the stable class hooks used by the mobile CSS.
- [ ] Run `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "mobile profile page matches the reference layout sections"` and verify the test covers the hooks before CSS edits.
### Task 2: Tighten Profile Tab Markup Hooks
**Files:**
- Modify: `src/components/rpg-entry/RpgEntryHomeView.tsx`
- [ ] Add focused class hooks for profile identity text, stat values, shortcut labels, membership copy, and daily task copy without changing user-facing Chinese text.
- [ ] Keep the current page order: profile header, membership card, three stats, daily task, five shortcut buttons, settings, secondary shortcuts, legal strip.
### Task 3: Implement Mobile CSS
**Files:**
- Modify: `src/index.css`
- [ ] Under the existing `@media (max-width: 639px)` block, reduce `我的` Tab fixed sizes to ordinary UI scale: profile title 16-17px, body copy 11-13px, stats values 13-14px, shortcut labels 11-12px.
- [ ] Make narrow screens robust: stats grid uses three min-width-safe columns, shortcut grid becomes `repeat(5, minmax(0, 1fr))` above 360px and a stable `repeat(3, minmax(0, 1fr))` below 360px, identity text wraps safely, legal links wrap when needed.
- [ ] Keep the bottom dock fixed but add enough profile page bottom padding so the final legal / secondary section can scroll above it.
### Task 4: Update Docs
**Files:**
- Modify: `docs/【项目基线】当前产品与工程约束-2026-05-15.md`
- Modify: `docs/【玩法创作】平台入口与玩法链路-2026-05-15.md`
- [ ] Add the acceptance rule that mobile `我的` Tab typography stays within normal UI sizes and all functional blocks must scroll clear of the bottom dock on narrow screens.
### Task 5: Verify
**Files:**
- No new files.
- [ ] Run `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "mobile profile page matches the reference layout sections"`.
- [ ] Run `npm run check:encoding`.
- [ ] Run a local mobile viewport smoke check for the profile tab if the dev server starts cleanly.

View File

@@ -0,0 +1,184 @@
# 一种极低成本快速生成高质量2D小游戏高一致性美术素材的解决方案
更新时间:`2026-05-25`
> 本文为内部发明专利交底稿,目标是把“文字需求 -> 画面图 -> 透明 spritesheet -> 自动边界检测 -> 元素绑定”这一条高一致性美术素材生成链路抽象为可申请的通用技术方案。
## 摘要
本发明涉及一种极低成本快速生成高质量 2D 小游戏高一致性美术素材的解决方案。该方案接收文字形态的需求描述,调用图片生成模型生成一张用于表达整体视觉关系的游戏画面图;再以所述游戏画面图作为参考,继续调用图片生成模型生成一张透明背景的 spritesheet 图片,所述 spritesheet 图片承载需要随不同设备分辨率自适应调整位置的素材;随后基于自动边界检测算法对所述 spritesheet 图片中的素材进行逐一解析,按照从上到下、从左到右的顺序,将解析出的素材与文字形态需求描述中的画面元素一一对应,并将代码中的元素标识与对应素材绑定。该方案通过单次文字输入驱动画面图生成、基于画面图派生透明 spritesheet、自动边界检测替代人工切图、顺序映射替代手工命名和手工对图从而在较少人工干预和较低重复生成成本下快速得到风格统一、可直接绑定代码的高一致性美术素材。
## 技术领域
本发明属于人工智能图像生成、2D 小游戏美术素材生产、图像分割解析和元素绑定技术领域具体涉及一种根据文字需求描述自动生成游戏画面图、spritesheet 美术素材和元素映射关系的方法及系统。
## 背景技术
现有 2D 小游戏的美术素材生产通常包含以下步骤:先由设计人员撰写文字需求,再由美术人员分别绘制画面图、按钮图、状态图和装饰图,之后由前端或游戏程序员进行切图、命名、排布和代码绑定。该流程存在如下问题:
1. 素材往往分散生成,整体风格不统一。
2. 多分辨率适配时,需要人工调整大量元素位置,维护成本高。
3. 切图和命名依赖人工,容易出现遗漏、错位和绑定错误。
4. 文字需求与最终代码元素之间缺少稳定映射,后续修改代价大。
5. 若每个素材分别生成,会增加生成次数和等待成本。
因此,需要一种能够把文字需求直接转化为成套美术素材,并且能够自动解析、自动映射、自动绑定到代码中的方法。
## 发明内容
### 要解决的技术问题
本发明主要解决以下技术问题:
1. 如何根据文字形态的需求描述快速生成一张完整游戏画面图。
2. 如何基于该画面图进一步生成透明背景的 spritesheet 图片。
3. 如何基于自动边界检测算法逐一解析 spritesheet 中的素材。
4. 如何按照从上到下、从左到右的顺序将素材与文字描述中的画面元素一一对应。
5. 如何将映射结果稳定绑定到代码,减少人工切图和手工配置成本。
### 技术方案
本发明提供一种高一致性美术素材生成方法,包括如下步骤:
```text
文字形态需求描述
-> 游戏画面图生成
-> 透明背景 spritesheet 生成
-> 自动边界检测解析素材
-> 顺序映射文字元素
-> 代码绑定
```
其中,所述文字形态需求描述至少包含画面元素名称、语义说明、布局意图和顺序信息。所述游戏画面图用于表达整体视觉风格和元素关系;所述 spritesheet 图片用于承载需要随不同设备分辨率自适应调整位置的素材;所述自动边界检测算法用于把 spritesheet 中的独立素材一一切分出来;所述顺序映射用于将解析结果与文字描述中的元素一一对应;所述代码绑定用于将元素标识、资源地址、边界框或布局参数写入代码配置或元素表。
### 有益效果
与现有技术相比,本发明至少具有以下效果:
1. 降低人工切图成本。
2. 降低人工命名和代码绑定成本。
3. 提升整体美术素材一致性。
4. 提升多分辨率适配效率。
5. 减少重复生成和重复调整次数。
6. 让文字需求到代码元素的映射更稳定、更可维护。
## 附图说明
图 1 为本发明从文字需求描述到元素绑定的总体流程图。
图 2 为游戏画面图生成与 spritesheet 生成的派生关系示意图。
图 3 为自动边界检测算法解析透明背景 spritesheet 的流程图。
图 4 为素材顺序与文字形态需求描述中的画面元素一一对应的映射关系示意图。
## 具体实施方式
### 一、系统组成
本发明的系统可以包括如下模块:
1. 输入采集模块:用于接收文字形态需求描述。
2. 图像生成模块:用于根据文字形态需求描述生成游戏画面图。
3. 图集生成模块:用于根据游戏画面图生成透明背景 spritesheet 图片。
4. 边界检测模块:用于对 spritesheet 图片执行自动边界检测算法。
5. 顺序映射模块:用于将解析出的素材按照从上到下、从左到右的顺序与文字描述中的画面元素对应。
6. 代码绑定模块:用于将元素标识与对应素材绑定。
### 二、方法步骤
#### S100接收文字形态需求描述
系统接收用户输入的文字形态需求描述。该需求描述可写成一段自然语言,也可写成按元素顺序排列的结构化文本。需求描述中应至少能够识别出画面元素名称、语义含义和布局顺序。
#### S200生成游戏画面图
图像生成模块调用图片生成模型,根据所述文字形态需求描述生成一张完整游戏画面图。所述游戏画面图用于表达整体视觉关系、主次层级和风格基调,为后续 spritesheet 生成提供统一参考。
#### S300生成透明背景 spritesheet 图片
图集生成模块以所述游戏画面图为参考,再次调用图片生成模型,生成一张透明背景的 spritesheet 图片。所述 spritesheet 图片中包含需要随不同设备分辨率自适应调整位置的素材,例如按钮、状态条、提示气泡、装饰元素或其他需要由代码控制位置的元素。
#### S400自动边界检测解析素材
边界检测模块对所述 spritesheet 图片执行自动边界检测算法,对透明背景中的每个独立素材进行逐一解析,输出素材边界框、素材索引和必要的资源属性。所述自动边界检测算法优选采用 alpha 通道连通域检测、边界矩形检测或二者组合;在一个优选实施方式中,可复用拼图场景中已验证的自动边界检测思路,以提高解析稳定性。
#### S500按照顺序映射文字元素
顺序映射模块将解析出的素材按照从上到下、从左到右的顺序进行排列,并与文字形态需求描述中的画面元素内容一一对应。若需求描述中已显式给出元素顺序,则优先按该顺序映射;若仅给出自然语言描述,则可先抽取元素列表,再按布局顺序排序。由此形成元素索引与语义名称之间的稳定映射关系。
#### S600代码绑定
代码绑定模块将所述映射关系写入代码配置、元素表或资源清单中。代码侧只需读取元素标识,即可找到对应素材的资源地址、边界框和布局参数,从而完成美术素材与程序逻辑之间的直接绑定。
#### S700输出美术素材包
系统最终输出至少包括游戏画面图、透明背景 spritesheet 图片、素材映射表和代码绑定结果。由于 spritesheet 图片与游戏画面图来自同一视觉链路,且素材顺序与文字描述顺序一一对应,因此可得到风格统一、可直接绑定、可适配多分辨率的高一致性美术素材包。
### 三、核心机制
1. 文字驱动:一次文字描述即可驱动画面图和 spritesheet 生成。
2. 单图派生spritesheet 以游戏画面图为参考生成,减少风格漂移。
3. 自动解析:边界检测算法替代人工切图。
4. 顺序对应:素材顺序与文字元素顺序一致,减少命名和对图错误。
5. 代码绑定:映射结果可直接进入代码配置或资源表。
### 四、实施例
#### 实施例一:界面型 2D 小游戏素材生成
用户输入“科技实验室界面,顶部标题栏,中部主角色,底部三个操作按钮,右侧状态提示”。系统先生成一张完整游戏画面图,再生成一张透明背景 spritesheet 图片。边界检测模块解析出标题栏、主角色、操作按钮和状态提示等素材,顺序映射模块按从上到下、从左到右的顺序将其与文字描述对应,代码绑定模块将这些元素写入代码配置,最终形成可直接用于界面装配的素材包。
#### 实施例二:需要自适应位置的素材生成
用户输入“横版战斗界面,血条、技能按钮、提示气泡、道具栏”。系统将这些需要随设备分辨率自适应调整位置的元素集中生成到同一张 spritesheet 图片中。运行时,代码根据元素绑定结果对血条、按钮和提示元素进行位置调整,而不改变它们对应的语义关系。
#### 实施例三:代码与元素一一绑定
系统为解析出的每个素材分配唯一元素标识,例如 `top_title_bar``center_character``bottom_actions``right_status_hint`。代码侧通过元素标识直接读取对应素材的边界框和资源路径,从而消除人工对图和人工命名的步骤。
## 权利要求书草案
1. 一种极低成本快速生成高质量 2D 小游戏高一致性美术素材的方法,其特征在于,包括:接收文字形态需求描述;根据所述文字形态需求描述调用图片生成模型生成游戏画面图;以所述游戏画面图为参考图再次调用图片生成模型生成透明背景的 spritesheet 图片;对所述 spritesheet 图片执行自动边界检测算法,逐一解析素材边界;按照从上到下、从左到右的顺序将解析出的素材与所述文字形态需求描述中的画面元素一一对应;将代码中的元素标识与对应素材绑定。
2. 根据权利要求 1 所述的方法,其特征在于,所述文字形态需求描述至少包括画面元素名称、语义说明和布局顺序。
3. 根据权利要求 1 所述的方法,其特征在于,所述游戏画面图用于表达整体视觉风格和元素关系,所述 spritesheet 图片用于承载需要随不同设备分辨率自适应调整位置的素材。
4. 根据权利要求 1 所述的方法,其特征在于,所述 spritesheet 图片具有透明背景,且素材之间通过透明区域分隔。
5. 根据权利要求 1 所述的方法,其特征在于,所述自动边界检测算法包括基于 alpha 通道的连通域检测、边界矩形检测或二者组合。
6. 根据权利要求 5 所述的方法,其特征在于,所述自动边界检测算法复用拼图场景中已验证的素材边界解析思路。
7. 根据权利要求 1 所述的方法,其特征在于,所述从上到下、从左到右的顺序用于建立元素索引与语义名称之间的映射表。
8. 根据权利要求 1 所述的方法,其特征在于,所述代码绑定包括为每一素材写入唯一元素标识,并在代码中通过所述元素标识读取对应素材的资源地址、边界框或布局参数。
9. 根据权利要求 1 所述的方法,其特征在于,所述 spritesheet 图片中的素材包括按钮、状态条、提示元素、装饰元素或其他需要自适应布局的画面元素。
10. 根据权利要求 1 所述的方法,其特征在于,所述游戏画面图与所述 spritesheet 图片由同一视觉链路生成,以保持美术素材的一致性。
11. 根据权利要求 1 所述的方法,其特征在于,所述元素绑定结果用于在不同设备分辨率下动态调整素材位置,而不改变元素语义对应关系。
12. 一种极低成本快速生成高质量 2D 小游戏高一致性美术素材的系统,其特征在于,包括输入采集模块、图像生成模块、图集生成模块、边界检测模块、顺序映射模块和代码绑定模块;所述各模块被配置为执行权利要求 1 至 11 任一项所述的方法。
13. 一种电子设备,包括处理器和存储器,所述存储器中存储有计算机程序,其特征在于,所述计算机程序被所述处理器执行时实现权利要求 1 至 11 任一项所述的方法。
14. 一种计算机可读存储介质,其上存储有计算机程序,其特征在于,所述计算机程序被处理器执行时实现权利要求 1 至 11 任一项所述的方法。
## 可重点保护的创新点
1. 文字需求直接驱动一张游戏画面图。
2. 基于该画面图再生成透明背景 spritesheet。
3. 自动边界检测替代人工切图。
4. 按从上到下、从左到右的顺序把素材与文字元素一一对应。
5. 通过元素标识直接绑定代码与素材,减少人工命名和对图成本。
## 正式申请前建议
1. 检索是否已有“文字生成画面图 + spritesheet 自动解析 + 元素绑定”的相近专利,再确定独立权利要求的保护重心。
2. 将“极低成本”“高质量”等效果性表述尽量放在说明书效果部分,权利要求中改写为“减少人工切图”“减少重复生成”“提高一致性”等技术特征。
3. 避免在权利要求中绑定特定供应商或模型名称;模型名称可保留在实施例中。
4. 如需扩大保护范围可将“2D 小游戏”进一步上位为“交互式图像驱动应用”的美术素材生成方法。
5. 如需增强授权稳定性,可将“文字驱动生成 + 透明 spritesheet + 自动边界检测 + 顺序映射 + 代码绑定”组合为主权利要求的必要技术特征。

View File

@@ -20,7 +20,7 @@ server-rs + Axum + SpacetimeDB
- HTTP 服务:`api-server`
- 领域模块:`module-ai``module-assets``module-auth``module-bark-battle``module-big-fish``module-combat``module-creative-agent``module-custom-world``module-inventory``module-match3d``module-npc``module-progression``module-puzzle``module-quest``module-runtime``module-runtime-item``module-runtime-story``module-square-hole``module-story``module-visual-novel`
- 平台副作用:`platform-agent``platform-auth``platform-llm``platform-oss``platform-speech`
- 平台副作用:`platform-agent``platform-auth``platform-image``platform-llm``platform-oss``platform-speech`
- 共享层:`shared-contracts``shared-kernel``shared-logging`
- SpacetimeDB`spacetime-client``spacetime-module`
- 测试支撑:`tests-support`
@@ -98,6 +98,8 @@ npm run check:server-rs-ddd
该拆分只改变 `api-server` 文件组织,不改变 `/api/runtime/puzzle/*` route、DTO、error envelope、SpacetimeDB schema、公开 gallery cache 语义或计费语义;后续继续细分时也必须先保持行为不变,再单独讨论领域规则下沉。
`/api/runtime/puzzle/runs*` 当前接受 `RuntimePrincipal`,可同时识别登录用户 Bearer 和 runtime guest token。推荐页嵌入运行态的正式开局、交换、拖拽、下一关、暂停、道具与排行榜请求应由前端在登录态下继续携带账号 access token匿名游客仅在确认为未登录时走 runtime guest token。不要再把拼图 runtime 当成只认普通 Bearer 的纯账号接口。
抓大鹅 Match3D `api-server` 内部拆分:
- `server-rs/crates/api-server/src/modules/match3d.rs` 继续负责路由装配和 body limit对外 handler 名称保持不变。
@@ -117,9 +119,10 @@ npm run check:server-rs-ddd
2. Adapter 输入应显式包含 provider、prompt、reference images、OSS prefix/path/file name、asset kind、entity kind/id、slot、owner/profile/source job、metadata 和可选透明背景后处理。
3. Adapter 输出应保留 legacy public path、object key、asset object id、MIME、extension、task id 和实际 prompt。
4. Adapter 不负责扣费、退款或钱包读取;计费仍由调用方显式包裹。
5. Puzzle、Match3D、音频、GLB、视频等复杂媒体可以复用 OSS + asset object + binding 的底层持久化能力,但玩法专属处理规则留在各自编排层,不塞进公共接口
6. 拼图图生图参考图主链不得再把大图 Data URL 塞进创作 JSON body前端先直传 OSS 并提交 `referenceImageAssetObjectId(s)``api-server` 校验 `asset_object` 的 bucket、kind、图片 MIME、大小和 owner 后签发只读 URL 给 VectorEngine 读取Data URL / `/generated-*` 仅作为旧请求兼容
7. 系列素材图集使用 `server-rs/crates/api-server/src/generated_asset_sheets.rs`:调用方必须传入 `grid_size` 作为 `n*n``n`,可选传入物品名称 prompt 模板和特殊设定 prompt模块负责 sheet prompt 组装、按 `n*n` 切片、透明化、PNG 输出、OSS private upload 请求构造和 sheet / item / special prompt 元数据持久化。玩法只负责规划 slot、调用具体生图 provider、计费、失败回写以及把通用切片结果映射回自己的 DTO / 草稿 / runtime 字段
5. 图片 provider 协议不再放在玩法模块里实现。VectorEngine `gpt-image-2` 创建 / 编辑协议、URL / base64 图片解析、远端图片下载、请求超时 / 上游状态 / 响应解析 / 缺图 / 下载失败的结构化日志统一在 `server-rs/crates/platform-image``api-server` 只负责配置校验、玩法 prompt 编排、OSS / asset object / binding 持久化、计费和外部 API 失败审计落库
6. Puzzle、Match3D、音频、GLB、视频等复杂媒体可以复用 OSS + asset object + binding 的底层持久化能力,但玩法专属处理规则留在各自编排层,不塞进公共接口
7. 拼图入口页与结果页新增关卡的本地参考图不走浏览器直传 OSS前端读取为 Data URL 后随创作 action 提交,并在读取前限制 6MB、显示“图片≤6MB”。`api-server` 必须对 Data URL 实际字节数再次校验;历史图片才提交 `referenceImageAssetObjectId(s)`,后端校验 `asset_object` 的 bucket、kind、图片 MIME、大小和 owner 后签发只读 URL 给 VectorEngine 读取
8. 系列素材图集使用 `server-rs/crates/api-server/src/generated_asset_sheets.rs`:调用方必须传入 `grid_size` 作为 `n*n``n`,可选传入物品名称 prompt 模板和特殊设定 prompt模块负责 sheet prompt 组装、按 `n*n` 切片、透明化、PNG 输出、OSS private upload 请求构造和 sheet / item / special prompt 元数据持久化。玩法只负责规划 slot、调用具体生图 provider、计费、失败回写以及把通用切片结果映射回自己的 DTO / 草稿 / runtime 字段。
## SpacetimeDB schema 变更规则
@@ -156,7 +159,7 @@ npm run check:server-rs-ddd
## 外部服务与资产
- LLM`GENARRATIVE_LLM_*`,创意 Agent 另用 `APIMART_BASE_URL` / `APIMART_API_KEY`
- 图片生成VectorEngine / APIMart / DashScope密钥只在后端环境变量中
- 图片生成VectorEngine `gpt-image-2` 图片 provider 归属 `platform-image`,密钥只在后端环境变量中;`api-server` 内的 `openai_image_generation.rs` 只是兼容调用面和外部失败审计桥接,不再承载 provider 协议实现。APIMart 只保留给创意 Agent `gpt-5` Responses 文本 / 多模态链路DashScope 只按仍在使用的历史能力单独处理,不作为 GPT-image-2 兜底
- Match3D 物品 sheet关卡整图完成后走 VectorEngine `/v1/images/edits` multipart `image`,模型为 `gpt-image-2``2K 1:1` 输出 `10*10` spritesheet物品 sheet prompt 固定要求纯绿色绿幕背景,后端上传 OSS 前必须把绿幕扣成透明 PNG并把透明整图写入 `itemSpritesheetImageSrc/itemSpritesheetImageObjectKey`。后端优先按透明 alpha 连通域从该 sheet 识别真实素材矩形并持久化 20 个物品、每个 5 个形态;识别数量不足时才回退 `10*10` 固定网格。通用系列素材图集的行列索引按每行 2 个物品计算,必须落在 `1..=10`,难度只决定运行态加载 3 / 9 / 15 / 20 种。
- Match3D UI spritesheet 和背景派生图:关卡整图作为参考图并发生成 `1K 1:1` UI spritesheet 与 `1K 9:16` 背景图,模型均为 `gpt-image-2`。UI spritesheet prompt 固定要求纯绿色绿幕背景,后端上传 OSS 前必须把绿幕扣成透明 PNG背景图必须合成为全画幅不透明 PNG。
- Match3D 1:1 容器 UIVectorEngine `/v1/images/edits` multipart 参考图。该容器参考图是后端生图协议输入,必须通过 `include_bytes!``api-server` 编译进二进制,避免 API 单独发布或运行目录缺少 `public/` 时生成失败。
@@ -164,7 +167,7 @@ npm run check:server-rs-ddd
- Hyper3D / Rodin只保留后端安全代理和旧数据兼容新 Match3D 草稿和批量新增不再生成 GLB。
- 音频:视觉小说专用音频路由保留;拼图、抓大鹅和敲木鱼提示词生成音效入口暂时关闭,通用 `/api/creation/audio/*` 对这些目标返回 `410 Gone`。敲木鱼创作只接收上传 / 录音音频资产;未提供时由 `api-server` 写回内置默认木鱼音 `/wooden-fish/default-hit-sound.mp3`
- OSS私有 generated legacy path 进入浏览器前必须通过 `/api/assets/read-url` 换签;不要裸请求 `/generated-*`
- 外部 API 失败审计:外部供应商调用未成功时,`api-server` 必须发送 OTLP 失败事件并写入 `tracking_event`当前通用 VectorEngine `gpt-image-2-all` 图片生成 / 编辑适配器在 `request_send``response_body``upstream_status``response_parse``missing_image``image_download` 阶段失败时记录 `external_api_call_failure``scope_kind = module``scope_id = provider``module_key = external-api`metadata 固定包含 provider、endpoint、operation、failureStage、statusCode、statusClass、timeout、retryable、errorMessage、latencyMs、promptChars、referenceImageCountimageModel。入库优先复用 tracking outboxoutbox 不可写或保护阈值拒绝时回退同步写 SpacetimeDB不得新增前端兜底或在 SpacetimeDB reducer 内做外部 I/O。
- 外部 API 失败审计:外部供应商调用未成功时,`api-server` 必须发送 OTLP 失败事件并写入 `tracking_event`。VectorEngine 图片 provider 在 `platform-image` 内输出结构化日志和 `PlatformImageFailureAudit`,覆盖 `request_send``response_body``upstream_status``response_parse``missing_image``image_download` 阶段`api-server` 只把该 audit 映射成 `external_api_call_failure``scope_kind = module``scope_id = provider``module_key = external-api`metadata 固定包含 provider、endpoint、operation、failureStage、statusCode、statusClass、timeout、retryable、errorMessage、latencyMs、promptChars、referenceImageCountimageModel 和 rawExcerpt。入库优先复用 tracking outboxoutbox 不可写或保护阈值拒绝时回退同步写 SpacetimeDB不得新增前端兜底或在 SpacetimeDB reducer 内做外部 I/O。
## SpacetimeDB 表目录
@@ -312,11 +315,15 @@ npm run check:server-rs-ddd
- Rust 结构体:`CreationEntryConfig`
- 源码:`server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs`
- 字段:`config_id``start_title``start_description``start_idle_badge``start_busy_badge``modal_title``modal_description``updated_at``event_title``event_description``event_cover_image_src``event_prize_pool_mud_points``event_starts_at_text``event_ends_at_text`
- 迁移兼容:旧迁移包缺少活动横幅字段时,由 `migration.rs` 写入 `None` / `58000` 默认值;运行态读取层再按 `module-runtime` 默认横幅归一,不覆盖后台已保存配置。
### `creation_entry_type_config`
- Rust 结构体:`CreationEntryTypeConfig`
- 源码:`server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs`
- 字段:`id``title``subtitle``badge``image_src``visible``open``sort_order``updated_at``category_id``category_label``category_sort_order`
- 迁移兼容:旧迁移包缺少入口分类字段时,由 `migration.rs` 写入 `None` / `0` 默认值;入口分组展示由 `module-runtime` 和前端展示派生消费。
### `custom_world_agent_message`
@@ -639,6 +646,7 @@ npm run check:server-rs-ddd
拼图、自定义世界、抓大鹅、方洞挑战、视觉小说和大鱼吃小鱼的公开列表 HTTP 路由都从订阅 cache 读取公开 read model / view。各玩法的个人作品列表、详情、发布、点赞、游玩记录、Remix 和其它需要鉴权或写入副作用的路径继续走 procedure / reducer不要为了公开列表性能把这些 owner-specific 或 mutation 语义混进 public view。
`GET /api/creation-entry/config` 和入口熔断优先从订阅 cache 读取创作入口配置cache 缺失时使用最近一次成功读取的内存快照,再兜底调用 `get_creation_entry_config` procedure 完成空库种子或旧库兼容。
入口配置快照包含 start card、类型弹窗、活动横幅和入口类型列表入口类型列表新增 `category_id``category_label``category_sort_order` 后,后台 upsert、`shared-contracts``module-runtime``spacetime-client` binding 必须同步,旧迁移 JSON 通过 `migration.rs` 默认值兼容。
RPG 创作入口的配置 ID 是 `rpg`,当前 `visible=true``open=true`;历史 `custom-world` 路由仍是 RPG 的工程域与运行态源类型。入口熔断把 `/api/runtime/custom-world*``/api/story/*``/api/runtime/chat/*` 统一映射到 `rpg`,不要新增平行 `airp` 路由或用 `airp` 接管当前文字冒险链路。

View File

@@ -45,6 +45,8 @@ npm run dev:api-server
后端日志默认写入 `logs/api-server/`。后端 API smoke 使用 `npm run dev:api-server` 并检查 `/healthz`;不要使用旧 `api-server:maincloud` 或任何 `GENARRATIVE_SPACETIME_MAINCLOUD_*` 口径。
开发态 `npm run dev``npm run dev:api-server` 会默认注入 `GENARRATIVE_DEV_PASSWORD_ENTRY_AUTO_REGISTER_ENABLED=true`,因此密码登录在本地开发环境可直接注册未知手机号账号;生产环境仍按 `api-server` 配置默认关闭该开关。
如果本地 `GET /api/creation-entry/config` 返回 `No such procedure`,或 `api-server` 日志出现 `no such table: puzzle_gallery_card_view` / `no such table: wooden_fish_gallery_card_view` 这类公开 view 缺失,通常是 `.env.local` 指向的 SpacetimeDB 库还没有发布当前 `spacetime-module`,或当前 CLI 身份无权发布该库。debug 构建的 `api-server` 会临时使用后端默认入口配置兜底,避免创作作品架整块消失;正式修复仍应切换到拥有目标库权限的 SpacetimeDB 身份后重新运行 `npm run dev` 完成发布,或用 gitignored 的 `spacetime.local.json` 指向可发布的本地库。
本地排查 schema 漂移时,先用当前 dev server 显式查询目标库,例如:
@@ -59,7 +61,7 @@ spacetime sql <database> "SELECT * FROM puzzle_gallery_card_view LIMIT 1" --serv
本地 `spacetime` CLI / standalone 版本必须和 `server-rs/Cargo.toml` 里锁定的 `spacetimedb` 版本一致。若版本错配procedure 返回值可能在宿主侧触发 `Failed to BSATN deserialize procedure return value`api-server 最终表现为敲木鱼等创作动作的 `SpacetimeDB procedure 调用超时`。排障时先运行 `spacetime --version`,再对照 `server-rs/Cargo.toml``spacetimedb = "..."`;需要切版本时执行 `spacetime version install <version> && spacetime version use <version>`,然后重新启动 `npm run dev:spacetime`。当前 `scripts/dev.mjs` 会在启动和复用本地 SpacetimeDB 前写入并校验 `dev-spacetime-tool-version`,避免把旧 standalone 继续带进新一轮创作。
本地 `.env``.env.local``.env.secrets.local` 修改后必须重启 `api-server` 才会生效;若已经通过 `npm run dev` 启动完整联调,可在该终端输入 `rs api-server`。排查 RPG / 拼图 / 抓大鹅等 VectorEngine 生图链路时,确认 `VECTOR_ENGINE_BASE_URL``VECTOR_ENGINE_API_KEY``VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 只在本地或服务器密钥文件中配置,不能写入 Git。开局 CG 故事板、首图、背景和图集都属于长耗时图片请求;后端默认会把 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 下限收口到 `1000000`,旧进程仍可能沿用重启前的短超时。若开局 CG 故事板在 `send()` 阶段失败且日志显示 `SendRequest`,先看同一 request_id 的 `request_body_bytes``reference_data_url_bytes``sourceChain``rootSource`;当前开局 CG 会把角色图与首幕背景图压到单边 768 的 JPEG 后再作为 generations `image` 数组发送,`/v1/images/generations` 使用默认 HTTP 协商,只有 multipart `/v1/images/edits` 单独强制 HTTP/1.1。
本地 `.env``.env.local``.env.secrets.local` 修改后必须重启 `api-server` 才会生效;若已经通过 `npm run dev` 启动完整联调,可在该终端输入 `rs api-server`。排查 RPG / 拼图 / 抓大鹅等 VectorEngine 生图链路时,确认 `VECTOR_ENGINE_BASE_URL``VECTOR_ENGINE_API_KEY``VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 只在本地或服务器密钥文件中配置,不能写入 Git。VectorEngine `gpt-image-2` 图片协议、URL / base64 响应解析、远端图片下载和 provider 侧结构化日志在 `server-rs/crates/platform-image``api-server` 只做配置、玩法编排、OSS / asset 持久化、计费和失败审计落库。开局 CG 故事板、首图、背景和图集都属于长耗时图片请求;后端默认会把 `VECTOR_ENGINE_IMAGE_REQUEST_TIMEOUT_MS` 下限收口到 `1000000`,旧进程仍可能沿用重启前的短超时。若开局 CG 故事板在 `send()` 阶段失败且日志显示 `SendRequest`,先看同一 request_id 的 `request_body_bytes``reference_data_url_bytes``sourceChain``rootSource`;当前开局 CG 会把角色图与首幕背景图压到单边 768 的 JPEG 后再作为 generations `image` 数组发送,`/v1/images/generations` 使用默认 HTTP 协商,只有 multipart `/v1/images/edits` 单独强制 HTTP/1.1。
查看本地 Rust / SpacetimeDB 日志:
@@ -142,6 +144,7 @@ Codex 项目级 hook 已放在 `.codex/config.toml` 与 `.codex/hooks/`
后端代码修改后,按变更范围选择:
- `cargo test -p <crate> --manifest-path server-rs/Cargo.toml`
- `cargo test -p platform-image --manifest-path server-rs/Cargo.toml`
- `cargo check -p api-server --manifest-path server-rs/Cargo.toml`
- `cargo check -p spacetime-client --manifest-path server-rs/Cargo.toml`
- `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`
@@ -152,7 +155,7 @@ Codex 项目级 hook 已放在 `.codex/config.toml` 与 `.codex/hooks/`
```bash
cargo check -p api-server --manifest-path server-rs/Cargo.toml
npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "logged out recommend page can enter runtime without login gate|logged out desktop recommend page renders runtime directly without login gate"
npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "logged out recommend tab enters runtime without login modal|logged out desktop recommend page renders runtime directly|logged out desktop recommend rail enters runtime without login modal"
```
涉及 SpacetimeDB schema 时必须补:
@@ -202,6 +205,8 @@ Jenkins 按 web / api / Spacetime module / build / deploy / publish 拆分
`Genarrative-Web-Build` 的主站构建失败若出现 Rollup 报错 `"xxx" is not exported by "src/services/publicWorkCode.ts"`,优先按前端公开作品号工具缺失处理,而不是排查 Jenkins 节点环境。修复时要让 `publicWorkCode.ts``build<Play>PublicWorkCode``isSame<Play>PublicWorkCode` 成对导出,并补 `src/services/publicWorkCode.test.ts` 覆盖对应玩法前缀;随后用 `npm run build:production-release -- --component web --name <临时名>` 复现 Jenkins web 构建路径。
生产 Jenkins 的 `Pipeline script from SCM` 由 Windows controller 读取 JenkinsfileSCM URL 继续使用 `https://git.genarrative.world/GenarrativeAI/Genarrative.git`。运行在 `linux && genarrative-build` 构建机上的 `Genarrative-Full-Build-And-Deploy` 源码解析阶段和 `Genarrative-Web-Build` checkout 阶段,优先使用 `http://127.0.0.1:3000/GenarrativeAI/Genarrative.git`,失败后回退到 `https://git.genarrative.world/GenarrativeAI/Genarrative.git`;两层 checkout 都必须保留单分支 refspec、`shallow=true``depth=1``noTags=true``honorRefspec=true`,后续二次源码确认继续走 `scripts/jenkins-checkout-source.sh`
`Genarrative-Stdb-Module-Build` 或 SpacetimeDB module 构建失败若出现 Rust `E0425 cannot find function migrate_*`,优先排查 `server-rs/crates/spacetime-module/src/runtime/creation_entry_config.rs` 等同文件内默认种子迁移 helper 是否在分支合并时只保留了调用、漏掉了函数定义。修复时不要直接删除迁移调用;应恢复只纠偏历史默认种子且不覆盖后台手动配置的 helper并用 `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml` 复现 Jenkins module 编译路径。
Windows Stdb module 构建流水线运行在 Jenkins `windows` 节点上。该流水线需要执行 PowerShell 逻辑时,统一通过 `bat` 显式调用 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe`,不要直接使用 Jenkins `powershell` step本地 Jenkins durable-task 曾在 `Genarrative-Stdb-Module-Build` workspace 中启动裸 `powershell` 时触发 `CreateProcess error=5, 拒绝访问`。临时 `.ps1` 由 Jenkins `writeFile` 写出后要先转成 UTF-8 with BOM 再交给 Windows PowerShell 5.1 `-File` 解析,避免中文错误消息在无 BOM UTF-8 下被当成本地 ANSI 误解码。Checkout 阶段要优先复用 Jenkins GitSCM 已经完成的结果:`COMMIT_HASH` 为空或与当前 `HEAD` 一致时,不要再额外 `git clean` / `git checkout`,只在确实需要切到别的指定 commit 时才补 fetch、校验和切换。排查时先看对应 build log、`@tmp/durable-*` 下的 `powershellWrapper.ps1`,以及日志中的 `[jenkins-powershell] user/exe`
@@ -219,7 +224,7 @@ Windows Stdb module 构建流水线运行在 Jenkins `windows` 节点上。该
- Windows 下载阶段如果出现 `curl: (18)` 或响应体截断,流水线会保留同名 `.download` 临时文件并用 `curl -C -` 断点续传;只有完整返回但 SHA256 digest 仍不匹配时才删除临时文件后重新下载。目标 Linux 节点仍只接收 `stash/unstash` 带过去的本地下载件,不回退外网下载。
- Windows 下载阶段如果走代理,在 `Genarrative-Server-Provision` 参数 `PROVISION_DOWNLOAD_PROXY` 填写 Windows Jenkins 节点可访问的 HTTP 代理,例如 `http://127.0.0.1:7890`;不要填写目标 release 机器视角的 `127.0.0.1`,除非代理确实运行在该 Windows 节点本机。Linux 目标机阶段会强制要求使用本地下载件,缺少文件直接失败,不再回退到外网下载。
- `otelcol-contrib.service` 作为可选系统服务加入 provision默认监听 `127.0.0.1:4317/4318` 并使用 `deploy/otelcol/genarrative-debug.yaml`。api-server 是否发送 OTLP 仍由 `GENARRATIVE_OTEL_ENABLED` 控制,服务 unit 见 `deploy/systemd/otelcol-contrib.service`
- Nginx `/api/``/admin/api/` 通过 `genarrative_api` upstream 代理到 `127.0.0.1:8082`upstream keepalive 为 64`limit_conn` 负责连接 / 并发保护,`limit_req` 负责入口 RPS 快拒绝。当前模板把公开 gallery list 单独放到 `genarrative_gallery_rps`,默认 `rate=5000r/s``burst=4096``limit_conn=320`;公开详情和普通 API 放到 `genarrative_api_rps`,后台 API 放到 `genarrative_admin_rps`。通用 `/api` location 设置 `client_max_body_size 64m` 是反代兜底,防止旧客户端或兼容请求在到达 `api-server` 前被默认 1 MiB 上限拦截;长期主链不得依赖大 JSON body 承载图片,拼图参考图应先直传 OSS只向创作接口提交 `referenceImageAssetObjectId(s)`,由后端签只读 URL 给外部模型读取。真实业务上限仍由 Rust 路由 `DefaultBodyLimit`、资产确认时 OSS HEAD 和解码后字节校验控制。若线上出现 `413 Request Entity Too Large` 且 access log 中 `request_time=0.000``upstream_status=-`,说明请求在 Nginx 层被拦截,先用 `nginx -T | grep client_max_body_size` 检查 release 模板是否已渲染并 reload同时检查前端是否仍在提交 Data URL 而不是 `assetObjectId``limit_conn_status 429``limit_req_status 429` 必须在 HTTP 与 HTTPS server 中同时生效;若线上压测看到 `limiting connections by zone "genarrative_api_conn"` 却返回 503优先检查 `nginx -T` 里 HTTPS server 是否缺少这些状态码,以及 `/api/runtime/puzzle/gallery` 是否误落到通用 `location ~ ^/api``limit_conn=64`。压测时看 `/var/log/nginx/genarrative.access.log` 中的 `request_time``upstream_connect_time``upstream_header_time``upstream_response_time``upstream_status``request_id`
- Nginx `/api/``/admin/api/` 通过 `genarrative_api` upstream 代理到 `127.0.0.1:8082`upstream keepalive 为 64`limit_conn` 负责连接 / 并发保护,`limit_req` 负责入口 RPS 快拒绝。当前模板把公开 gallery list 单独放到 `genarrative_gallery_rps`,默认 `rate=5000r/s``burst=4096``limit_conn=320`;公开详情和普通 API 放到 `genarrative_api_rps`,后台 API 放到 `genarrative_admin_rps`。通用 `/api` location 设置 `client_max_body_size 64m` 是反代兜底,防止拼图入口页 / 新增关卡本地参考图 Data URL 或旧兼容请求在到达 `api-server` 前被默认 1 MiB 上限拦截;拼图本地参考图前后端统一限制 6MB历史图片仍提交 `referenceImageAssetObjectId(s)`。若线上出现 `413 Request Entity Too Large` 且 access log 中 `request_time=0.000``upstream_status=-`,说明请求在 Nginx 层被拦截,先用 `nginx -T | grep client_max_body_size` 检查 release 模板是否已渲染并 reload同时检查前端是否超出 6MB 或错误提交了未压缩大图`limit_conn_status 429``limit_req_status 429` 必须在 HTTP 与 HTTPS server 中同时生效;若线上压测看到 `limiting connections by zone "genarrative_api_conn"` 却返回 503优先检查 `nginx -T` 里 HTTPS server 是否缺少这些状态码,以及 `/api/runtime/puzzle/gallery` 是否误落到通用 `location ~ ^/api``limit_conn=64`。压测时看 `/var/log/nginx/genarrative.access.log` 中的 `request_time``upstream_connect_time``upstream_header_time``upstream_response_time``upstream_status``request_id`
- 作品列表 K6 脚本一次 iteration 默认请求两个公开接口,因此约 50 HTTP req/s 的目标命令使用 `SCENARIO=spike START_RPS=5 PEAK_RPS=25 HOLD=60s END_RPS=5 DETAIL_RATIO=0 npm run loadtest:k6:works`
- 作品列表短期继续由 `api-server` / BFF 订阅 SpacetimeDB 公开 read model 后读本地 cache不让浏览器前端直接订阅完整列表未来如新增 `public_work_gallery_entry` 等专用公开作品列表 read model前端只可订阅稳定、低基数、公开的专用投影禁止订阅 `puzzle_work_profile``custom_world_profile` 等玩法源表后自行 join、聚合或判断权限。前端直订阅落地前必须先补齐权限、字段契约、排序 / 分页、埋点和 BFF 回退策略。
- 50 HTTP req/s 验收目标为 `http_req_failed < 1%``p95 < 2s``dropped_iterations = 0`,同时压测窗口内 Nginx 无新增 502。2026-05-19 容器 2C / 2G 连续 10 轮不重启 SpacetimeDB 压测:`PEAK_RPS=2500` 等价约 5000 HTTP req/s平均实际吞吐约 `4219 HTTP req/s`10 轮总计 `1,897,357` 个 200、`212,542` 个 429、`0` 个 5xx200 请求平均 `p95=123ms``p99=234ms`;该档会把 SpacetimeDB 容器内存从约 `366MiB` 推到约 `885MiB / 896MiB`,因此当前不要继续抬公开 gallery 入口并发,应优先处理 SpacetimeDB 侧连接 / 订阅 / tracking 写入后的内存高水位。
@@ -248,7 +253,7 @@ OpenTelemetry 现阶段默认开启 OTLP traces / metrics / logs但本地日
- debug exporter / Rider 转发都会同时接收 traces、metrics 和 logs。
- api-server 会随 metrics 发送进程级指标:`process.memory.usage``process.memory.virtual``process.cpu.time``genarrative.process.cpu.usage_percent``process.thread.count``genarrative.process.memory.private`Windows 额外发送 `process.windows.handle.count`Linux 额外发送 `process.unix.file_descriptor.count`。这些指标只描述当前进程,不携带请求、用户或作品 label。
- HTTP 运行态补充发送 `genarrative.http.server.response_bodies.in_flight``genarrative.http.server.request_permits.available`,后者带低基数 `pool=default|gallery|detail|admin` label用于区分业务 handler / 背压 permit 是否仍被占用;拼图广场热点缓存补充发送 `genarrative.puzzle_gallery.cache.*` 指标,记录 fresh hit、stale hit、未命中、后台刷新开始 / 失败、重建耗时和预序列化 data JSON 字节数。
- 外部 API 失败统一发送 OTLP 并落库。当前 VectorEngine `gpt-image-2-all` 图片生成 / 编辑失败会输出 `外部 API 调用失败` trace/log记录指标 `genarrative.external_api.failures{provider,failure_stage,status_class,retryable}`;同时写入 `tracking_event``event_key = external_api_call_failure``module_key = external-api``scope_kind = module``scope_id = provider`。排障时先按 provider / failureStage 聚合,再结合 request 日志和上游响应 excerpt 判断是限流、超时、解析失败还是未返回图片。
- 外部 API 失败统一发送 OTLP 并落库。当前 VectorEngine `gpt-image-2` 图片生成 / 编辑失败`platform-image` provider 输出低基数字段结构化日志,字段包括 provider、endpoint、failure_stage、status、status_class、timeout、retryable、latency_ms、prompt_chars、reference_image_count、image_model 和 raw_excerpt`api-server`记录指标 `genarrative.external_api.failures{provider,failure_stage,status_class,retryable}`,并写入 `tracking_event``event_key = external_api_call_failure``module_key = external-api``scope_kind = module``scope_id = provider`。排障时先按 provider / failureStage 聚合,再结合 request 日志和上游响应 excerpt 判断是限流、超时、解析失败还是未返回图片。
- SpacetimeDB 观测分为两类procedure / reducer 调用继续用 `genarrative.spacetime.procedure.*`,订阅本地 cache 读使用 `genarrative.spacetime.read.*``read=list_puzzle_gallery` 表示拼图广场当前从 `puzzle_gallery_card_view` 本地 cache 读取,不再每个 HTTP 请求调用 `list_puzzle_gallery` procedure。
- 本地 Windows 直连压测的内存高水位要结合 K6 VU / 连接数解释。250 RPS 下过高 `PREALLOCATED_VUS` 可能让 300 个本地 Established 连接把 `api-server` private memory 瞬时推到 GB 级,且 `/healthz` 小响应也能复现;若压测结束后回落、`response_bodies.in_flight` 和背压 permit 未显示业务积压,应优先按连接 / 发送链路高水位处理,而不是判断为 SpacetimeDB 或 JSON 缓存泄漏。
- Rider 的 Logs 面板只展示 log event 自身字段,不会自动展开父 span 的全部 attributes请求完成日志会直接带 `request_id``http.request.method``http.route``url.scheme``url.path``http.response.status_code``status_class``latency_ms``slow_request`,完整链路继续到 Traces 面板按 trace/span 查看。

View File

@@ -6,10 +6,16 @@
创作入口配置事实源在 SpacetimeDB通过 `GET /api/creation-entry/config` 下发;后台通过 `/admin/api/creation-entry/config` 管理。前端只在展示层派生可见卡片和入口状态,`api-server` 路由熔断也使用同一份配置。不要恢复前端硬编码入口配置文件。
当前创作 Tab 固定为智能创作首页与模板入口,草稿 Tab 承接作品架。点击独立入口后应切换到对应内嵌创作表单或生成页;不要额外做一张平行配置页,除非玩法本身需要完整独立工作台
当前创作 Tab 只承载赛事 banner、玩法模板分类和两列模板卡点击模板卡后直接进入对应玩法已有的入口创作表单 stage不再经过空白占位页也不把旧表单嵌进创作 Tab 首屏。移动端创作 Tab 顶栏在 `陶泥儿` 品牌同一行显示真实账户泥点数,数据来自 `profileDashboard.walletBalance`,不得再把活动奖池当作账号余额展示。首屏 banner 结构按参考图拆成横向可滑动赛事卡、主体宣传图文区、奖池胶囊、开始 / 结束时间条和卡片内分页点;轮播只保留 `拼图主题创作赛``抓大鹅主题创作赛`,两个主题赛事奖池均为 `1000` 泥点数。玩法列表不再套外部边框卡片,移动端需要压缩横向边距和两列间距;玩法卡统一按“上图、左上状态标签(仅非开放态显示)、封面右下 `10-20泥点数`、下方白底标题/描述”结构展示,卡片高度保持紧凑但标题、描述和预估消耗点数都必须可见。创作 Tab 根容器不再使用 `platform-page-stage` 这类全局内容卡片壳,但继续保留 `platform-remap-surface` 作为主题和输入框样式命中钩子。创作首屏字号需要对齐平台普通 UI 档位顶栏泥点组件、banner 正文、分类 Tab 和玩法卡标题 / 副标题 / 消耗说明优先使用 `11px``14px`,不使用 `text-lg``text-xl` 或更大的展示级字号。草稿 Tab 继续承接作品架。RPG、RPG 之外的各玩法入口分别落到既有的 `agent-workspace``big-fish-agent-workspace``match3d-agent-workspace``square-hole-agent-workspace``jump-hop-workspace``wooden-fish-workspace``puzzle-agent-workspace``bark-battle-workspace``visual-novel-agent-workspace``baby-object-match-workspace`,这些入口继续承接各玩法自己的表单、草稿恢复和后续编排,不作为创作 Tab 首屏内容
创作恢复参数只保留 `sessionId``profileId``draftId``workId` 这四个私有 query。它们只允许在同一条创作链路的结果页、生成页、工作台之间保留切到首页、公开作品详情、runtime 或另一条玩法链路时必须清掉。生成页恢复时只认当前进入页的时间作为新的 `startedAtMs`,作品摘要里的 `updatedAt` 只用于排序与摘要展示,不再作为生成进度起点。
创作表单提交前的泥点余额前置校验只允许用独立弹窗提示失败原因,不得把用户退回创作入口或玩法模板列表,也不得清空当前表单状态。当前适用拼图、抓大鹅和汪汪声浪等会在前端提交前校验泥点的生成入口;余额不足、余额读取失败都应停留在当前工作台,由用户关闭提示后继续编辑或自行补足泥点。
`PlatformEntryFlowShellImpl.tsx` 仍是平台入口编排壳,后续维护时应优先把独立 UI 片段、公开作品映射、草稿生成 notice 和运行态状态 helper 拆到 `src/components/platform-entry/PlatformEntryFlowShellImpl/` 或同目录紧邻 helper 文件。拆分只允许改变文件组织不改变入口配置事实源、默认导出、props、页面阶段、UI 文案或现有交互;其中拼图首访 onboarding 已拆为 `PlatformEntryFlowShellImpl/PuzzleOnboardingView.tsx`
`platformEntryCreationTypes.ts` 只做前端展示派生,分组时必须把后端 `creationTypes` 里的 `categoryId` / `categoryLabel` 当作可缺失字段处理,空值统一回退到 `recent` / `最近创作`,避免旧数据、局部 mock 或异常返回把创作入口初始化直接打崩。
移动端底部一级导航是全局平台样式,不按单一玩法分叉。当前视觉统一为米白浮动胶囊底座、浅棕分隔线、棕色线性图标、橘色选中态和底部短下划线;中间 `创作` 入口保持凸起圆形主按钮,但凸起位移只能作用在按钮内容层,不能移动承载分隔线的 Tab 按钮容器确保创作左右分隔线与其他分隔线垂直位置一致。Tab 名称和可见性仍由现有 `PlatformHomeTab` / 登录态规则决定,样式调整不得改写 Tab 文案或导航状态。
## 新增玩法创作工具平台 SOP
@@ -26,16 +32,20 @@
`api-server``generated_asset_sheets` 是当前通用系列素材图集模块:`n` 是必选参数,模块负责组装 `n*n` sheet prompt、按 `n*n` 切片、绿幕 / 近白底透明化、导出 PNG 和 OSS 持久化请求。物品名称 prompt 和特殊设定 prompt 是可选输入;调用方可传入类似“每个物品生成五个不同视图”的视角约束,通用模块会把 sheet prompt、物品行 prompt、特殊设定 prompt 编码写入 OSS 元数据。玩法仍负责计费、物品规划、slot 映射、失败回写和把通用切片结果映射回自己的草稿 / profile / runtime 字段。
当前所有玩法生成页 UI 统一收敛为圆环主视觉:`media/create_bg_video.mp4` 作为生成页固定全屏背景层循环静音播放,主进度圆环居中覆盖在背景之上,围绕陶泥儿视觉展示;页面只保留当前步骤名称和当前步骤进度,不再渲染步骤列表块。视频层需要显式触发播放,不能只依赖 `autoPlay/loop/muted` 属性。共用生成页 `CustomWorldGenerationView` 和汪汪声浪生成页都必须遵循这一口径。
## 草稿与作品架
1. 草稿页作品卡对齐发现页列表卡风格:左侧信息,右侧封面图,移动端单列,桌面两到三列。
2. 草稿 / 已发布状态尽量图标化,不使用大段状态文案
3. 草稿卡常态不外露低频动作;已发布作品卡右上角直接显示无边框分享 icon删除等破坏性动作继续收口到左滑或长按操作层。
2. 草稿页顶部 `全部 / 草稿 / 已发布` 筛选与发现页 `推荐 / 今日 / 分类 / 排行` 频道标签复用同一选中 / 未选中视觉,即 `platform-mobile-home-channel``platform-mobile-home-channel--active`,不使用`platform-tab` 胶囊样式
3. 草稿页与底部导航的未读提示点统一使用平台暖棕色点和暖棕光晕,不再使用红点或红色 glow草稿 Tab 作品架卡片无论草稿 / 已发布都不外露作者信息;已发布作品卡右上角直接显示无边框分享 icon删除等破坏性动作继续收口到左滑或长按操作层。
4. 生成中作品在整卡上加等待遮罩,但不移除作品基础信息。
5. 生成中状态不能只存在前端内存 notice。后端作品摘要必须下发可恢复的 `generationStatus`;前端刷新或退出产品后,作品架优先用摘要状态恢复等待遮罩,本轮内存 notice 只作为即时反馈。
6. 点击 `generationStatus=generating` 的草稿卡必须恢复对应玩法的生成进度页,不能进入空白结果页或普通工作区;恢复生成页的 `startedAtMs` 使用作品摘要 `updatedAt` 推导
6. 点击 `generationStatus=generating` 的草稿卡必须恢复对应玩法的生成进度页,不能进入空白结果页或普通工作区;恢复生成页的 `startedAtMs` 使用进入生成页的当前时间,作品摘要 `updatedAt` 只用于排序和摘要展示,不参与假进度起算
7. 私有 generated 图片必须通过 `ResolvedAssetImage` / `/api/assets/read-url` 换签读取。
发现 Tab、创作 Tab 与草稿 Tab 的页面根内容区不再套 `platform-page-stage` 外层全局卡片壳,让列表、筛选和玩法卡获得更宽的横向空间;推荐页和我的页仍按各自页面设计保留原有全局卡片口径。移动端“我的”页仍按顶部头像 / 昵称 / 陶泥号、会员横幅、三张统计卡、每日任务、五项常用功能宫格、设置入口、次级入口带和法律信息组织,但字号必须维持平台普通 UI 档位,不能因为窄屏把卡片标题、功能 label 或法律信息撑成展示级字号;最后一屏内容必须能在底部 dock 上方完整滚动露出,不得被固定底部导航遮挡。
## RPG / 自定义世界
当前 RPG 创作入口使用 `playId = rpg`,工程域和运行态源类型沿用历史 `custom-world`。默认入口状态为 `visible=true``open=true`,对外展示为“文字冒险”;`airp` 仍是独立的“AI RPG”占位入口保持 `open=false`,不要把它当作当前 RPG 创作链路开放。
@@ -62,7 +72,7 @@ RPG 从作品架、广场详情或作品号搜索点击“启动”前,入口
RPG 运行态的战斗终局、继续冒险、继续探索和切场景都属于服务端 runtime 快照真相:`module-runtime-story` 必须在终局战斗 action 后调用 post-battle finalization持久写入 `story_continue_adventure``deferredOptions``deferredRuntimeState.storyEngineMemory.currentSceneActState` 和清理后的战斗状态;`idle_travel_next_scene` / `camp_travel_home_scene` 必须由后端写入新的 `currentScenePreset``currentSceneActState``currentEncounter``runtimeStats.scenesTraveled`。前端只播放退场、进场和继续按钮表现,不能用默认 `观察/试探/调息` fallback 或本地动画假装推进剧情。旧 bootstrap 快照可能只有 `connectedSceneIds` / `forwardSceneId` 而没有 `connections`,后端生成战后旅行选项时必须兼容这些字段。
RPG / 拼图等运行态存档选择入口统一在个人中心 `常用功能 > 存档` 暴露为独立弹窗;“玩过”弹窗可以继续合并展示可继续存档,但不能成为唯一入口。前端只展示 `/api/profile/save-archives` 返回的列表并在用户选择后调用对应恢复接口,不能本地拼装或筛选正式存档真相。
RPG / 拼图等运行态存档仍以 `/api/profile/save-archives` 的后端列表为真相,恢复动作继续走对应恢复接口,但移动端“我的”页已经不再提供独立的 `次级入口 > 存档` 和设置入口存档按钮;“玩过”弹窗可以继续合并展示可继续存档,个人中心只保留设置、扫码、常用功能和条件性次级入口。移动端“我的”页的五项常用功能宫格只放泥点充值、邀请好友、兑换码、玩家社区、反馈与建议,避免把存档挤入主宫格破坏参考图布局。前端只展示 `/api/profile/save-archives` 返回的列表并在用户选择后调用对应恢复接口,不能本地拼装或筛选正式存档真相。
## 拼图
@@ -77,17 +87,19 @@ RPG / 拼图等运行态存档选择入口统一在个人中心 `常用功能 >
- 图像输入复用 `CreativeImageInputPanel`
- 结果页每关画面编辑复用 `CreativeImageInputPanel`;入口页和关卡画面只共享受控 UI 模块不共享数据源、状态、action 或存储位置:入口页继续写 `formDraft` 与草稿编译 payload关卡画面写 `levels[].pictureReference/pictureDescription` 并触发 `generate_puzzle_images`。结果页删除独立“素材配置”Tab不再提供单独 UI 背景生成入口。通用图片面板的展示图和 AI 重绘参考图能力必须分开控制:结果页正式关卡图只作为预览图,不因存在正式图自动暴露 AI 重绘开关;只有本地上传、历史选择或已保存 `pictureReference` 可作为重绘参考图时,才显示 AI 重绘开关并把状态带入 `generate_puzzle_images`。用户在本次编辑中上传或选择历史图后,该图优先占据主图卡片,可删除、切换 AI 重绘,也可关闭 AI 重绘直用;仅有正式图预览时,画面描述框仍可上传多张参考图。关卡详情弹窗应使用加宽面板,关卡名称、画面图和画面描述合并在同一个纵向列表中,名称输入和画面编辑模块外层不再包独立 `platform-subpanel`;画面图卡仍必须保留稳定最小高度,避免弹窗内 `flex-1` 布局坍缩后只剩标题、描述输入和操作按钮。
- 支持画面描述生图、多参考图生图、上传或历史生成主图后 AI 重绘、上传或历史生成主图后不重绘;主链要求浏览器先经 `/api/assets/direct-upload-tickets` 直传 OSS 并确认 `asset_object`,创作 action 只提交 `referenceImageAssetObjectId(s)`,由后端校验 owner / bucket / kind / MIME / size 后签发 OSS 只读 URL 并下载为 VectorEngine `/v1/images/edits` 的 multipart `image` part。本地上传 Data URL 与历史 `/generated-*` 图片路径仅保留为旧草稿、旧入口或未迁移客户端的兼容输入;关闭 AI 重绘时,后端统一解析为首关或当前关卡正式图后再持久化,不调用第一段拼图首图生成。
- 草稿生成会先持久化 `generationStatus=generating` 的作品摘要生成完成并回写关卡拼图画面、关卡画面参考图、UI spritesheet 和关卡背景图后再变为 `ready`;当前不自动生成背景音乐。生成页进度不再按固定 5 分钟展示,而按实际开始时间和当前路径的分步骤预计时长推进任一同步 action 回包到达时立即以真实完成/失败结果冻结进度。
- 草稿生成会先持久化 `generationStatus=generating` 的作品摘要生成完成并回写关卡拼图画面、关卡画面参考图、UI spritesheet 和关卡背景图后再变为 `ready`;当前不自动生成背景音乐。生成页步骤推进必须跟随后端 session `progressPercent` 的真实里程碑:`88` 表示草稿编译完成并进入出图步骤,`94` 表示生成图已保存并进入 UI / 背景步骤,`96` 表示正式图与 UI 背景已确认并进入写入步骤,最终 action 成功或发布才进入完成态;每个步骤内部可以按实际等待时间使用假进度平滑推进,总进度按 `0-88``88-94``94-96``96-98` 的真实里程碑区间平滑推进任一同步 action 回包到达时立即以真实完成/失败结果冻结进度。
- 作品架拼图草稿的“生成中”遮罩只表示初始草稿还没有可查看结果;只要作品摘要、首关封面或任一关卡候选图已经可用,后续 UI 背景重生成和追加关卡生图都必须作为结果页局部生成态处理,不能阻止打开草稿结果页。
- 拼图草稿编译是长耗时 action前端 action 请求默认等待 `1_800_000ms`30 分钟)且不自动重试。每次 `gpt-image-2` 调用的预期用时按 90 秒计算;完整 AI 重绘路径为 `编译首关草稿` 8 秒、`生成关卡名称` 10 秒、`生成拼图首图` 90 秒`生成关卡画面` 90 秒、`生成UI与背景` 90 秒、`写入正式草稿` 10 秒,合计约 298 秒。上传图且关闭 AI 重绘时必须跳过 `生成拼图首图`,直接进入 `生成关卡画面``生成UI与背景`,合计约 208 秒。生成页恢复时必须沿用作品摘要 `updatedAt` 作为原始 `startedAtMs`失败/完成态用 `finishedAtMs` 冻结耗时,不能在锁屏或返回草稿页后重新从 0 计时。未收到 action 回包前,总进度仍最多停在 98%,但当预计写入时长耗尽且仍处于 `写入正式草稿` 时,该步骤自身应显示已完成,不能出现“进行中 100%”
- 拼图草稿编译是长耗时 action前端 action 请求默认等待 `1_800_000ms`30 分钟)且不自动重试。每次 `gpt-image-2` 调用的预期用时按 90 秒计算,但 `生成拼图首图` 单独按 4 分钟展示;完整 AI 重绘路径为 `编译首关草稿` 8 秒、`生成关卡名称` 10 秒、`生成拼图首图` 4 分钟`生成关卡画面` 90 秒、`生成UI与背景` 90 秒、`写入正式草稿` 10 秒,合计约 448 秒。上传图且关闭 AI 重绘时必须跳过 `生成拼图首图`,直接进入 `生成关卡画面``生成UI与背景`,合计约 208 秒。生成页恢复时必须使用进入生成页的当前时间作为原始 `startedAtMs`失败/完成态用 `finishedAtMs` 冻结耗时。未收到对应后端里程碑前,后续步骤保持待处理;即使当前步骤预计时长耗尽,也只能让当前步骤内部进度停在 `98%` 内,不能自动完成当前步骤或跳到后续步骤。生成页每个步骤只展示标题和进度,不展示步骤详细描述
- 若浏览器锁屏、息屏或网络切换导致 compile 请求失败,前端在标记失败前必须先复读 `getPuzzleAgentSession(sessionId)`;只有最新 session 仍缺 `draft.coverImageSrc`、首关 `coverImageSrc` 或候选图时才展示失败,复读到已生成草稿时按成功收尾、刷新作品架并继续自动试玩/结果页链路。
- 拼图参考图 AI 重绘走 VectorEngine `/v1/images/edits`;无参考图时走 `/v1/images/generations`。两者模型都使用 `gpt-image-2`,参考图由后端作为 multipart `image` part 传入编辑接口。
- 每次新建关卡生成或重新生成关卡图都必须由 `api-server` 串起当前关卡资产包AI 重绘开启时第一段沿用草稿生成第一关的拼图主图提示词配置和模型 / 尺寸 / 参考图规则生成 `coverImageSrc/coverAssetId` 作为关卡拼图画面和结果页预览图,提示词来源同样按显式画面描述、关卡画面描述、草稿摘要顺序回退,且固定要求输出画面比例为 `1:1`;上传图且关闭 AI 重绘时跳过这一段,把上传图或历史图持久化为 `sourceType=uploaded` 的正式候选。随后用正式候选图作为参考,`9:16` 生成完整拼图游戏关卡画面并写入 `levelSceneImageSrc/levelSceneImageObjectKey`提示词必须要求道具按钮上不要显示次数标注且返回按钮和设置按钮旁禁止标注文字UI spritesheet 与关卡纯背景在关卡画面完成后并发生成spritesheet 用 `1:1``1k` 先生成纯绿色绿幕背景图,后端上传 OSS 前必须把绿幕扣成透明 PNG再写入 `uiSpritesheetImageSrc/uiSpritesheetImageObjectKey`,按钮顺序固定为返回、设置、下一关、提示、原图、冻结,按钮素材自身保留对应中文文字,返回和设置按钮不得额外生成白色外圈、白底圆环或浮雕外框;纯背景用 `9:16``1k` 写入 `levelBackgroundImageSrc/levelBackgroundImageObjectKey`,提示词必须包含“禁止在背景中出现人像或和拼图画面中主体一致的内容”。运行态不直接使用第二段完整关卡画面,但必须持久化它用于追踪和后续再生成。结果页局部关卡生成进度按 AI 重绘开启约 270 秒、关闭 AI 重绘约 180 秒展示。
- 结果页允许多关卡并行编辑和生成;某一关卡图片生成完成回包只静默更新该关卡素材与生成态,不得自动打开或切换关卡详情面板,避免打断用户正在编辑的其它关卡。
- 结果页关卡图片生成只标记对应关卡的局部生成进度,不禁用“新增关卡”、其它关卡详情编辑和结果页导航。
- 结果页单关测试只能把完整草稿持久化,并通过 `levelId` 指定运行态起始关卡;不得把单关快照作为整份草稿调用 `updatePuzzleWork`,否则 source session 和作品 profile 的 `levels` 会被覆盖成单关,退出重进后其它关卡会丢失。
- 拼图试玩和正式运行态刷新恢复不复用创作私有 query。进入 `/runtime/puzzle` 时必须写入 `runtimeProfileId`、草稿 `runtimeSessionId`、可选 `runtimeLevelId`、公开作品 `work``mode=draft|published`;进入运行态的导航顺序必须先切到 `/runtime/puzzle`,再写这些 runtime query避免被阶段导航清掉后刷新停在“正在进入拼图关卡”。
- 结果页生成关卡图时若关卡名为空,前端必须传 `shouldAutoNameLevel=true`,后端复用首关命名契约先按画面描述生成关卡名,再在图片生成后用视觉命名结果精修,并把生成名和 UI 背景提示词随本次关卡快照写回。
- 拼图运行态背景优先读取当前关卡 `levelBackgroundImageSrc/levelBackgroundImageObjectKey`,旧数据才兼容 `uiBackgroundImageSrc/uiBackgroundImageObjectKey`;本地试玩、直达指定关卡和正式 `next-level` 推进时,目标关卡缺关卡背景时必须继承同作品首个可用关卡背景,仍缺失时才沿用当前运行态快照背景或默认 UI。运行态按钮视觉优先读取当前关卡 `uiSpritesheetImageSrc/uiSpritesheetImageObjectKey`,先按透明 alpha 自动边界检测识别 spritesheet 中的独立按钮展示矩形,再按原图位置从左到右、从上到下映射到返回、设置、下一关、提示、原图、冻结;同一组件还要按较高 alpha 阈值派生紧致点击热区,透明留白和柔边低 alpha 区域尽量不响应点击。检测失败时回退旧固定六格裁切,缺失时才用现有图标按钮兜底。有 spritesheet 时,返回和设置按钮的点击容器只提供透明点击区,不再叠加默认白色圆形底;底部提示、原图、冻结三枚素材按检测矩形的原始宽高比显示,不能强行拉伸成正圆或铺满整列。底部道具区不再使用连片胶囊背景,提示、原图、冻结三个按钮均匀分布;运行态只展示按钮素材本身,不额外叠加“提示 / 原图 / 冻结”文字。
- 推荐页本身不是登录门禁入口,未登录用户点击底部或侧边栏的推荐 Tab 应直接进入嵌入运行态,不主动打开登录弹窗。推荐页嵌入运行态必须按真实身份分流:已登录用户或本地已有 access token 时,启动拼图和后续排行榜 / 下一关等正式请求继续走账号 Bearer只有确认为匿名访客时才申请并透传 runtime guest token。`/api/runtime/puzzle/runs*` 后端统一接受 `RuntimePrincipal`,可识别账号用户和匿名 runtime guest推荐卡片的后台读写请求仍使用 local auth impact避免单卡 401 清空整站登录态。创作、个人作品、删除、发布、Remix 等账号或所有权动作仍保持普通用户鉴权。
- 拼图运行态棋盘不叠加分块蒙版、描边、阴影、选中底色或合并块 SVG 轮廓;拼图片本体需要裁切为圆角形状,单块使用独立圆角裁切,合并块使用 SVG 原生 `clipPath` 裁切整体外轮廓,外凸角和内凹角分别计算半径,内凹角半径要比外凸角更明显以避免手机 WebView 中看起来仍是直角。原图道具只在用户主动确认后打开独立原图查看层,不在当前拼图棋盘上叠加原图。
- 拼图运行态拖拽必须完全跟随手指或鼠标位置,`pointermove` 期间即时写入可见拼块的 transform不依赖等待后端回包、React 重渲染或下一帧动画队列;进入拖动后不展示拼块选中态或“已选择”提示,松手后再提交目标格同步规则真相。
- 拼图运行态的提示、设置等点击弹层跟随当前运行态主色主题,使用普通圆角主题面板,不复用像素九宫格素材框。
@@ -120,7 +132,11 @@ RPG / 拼图等运行态存档选择入口统一在个人中心 `常用功能 >
平台首页推荐、精选、最新、公开详情、搜索、已玩作品和公开试玩统一按 `sourceType='jump-hop'``JH-*` 公开作品号识别跳一跳作品;从公开详情或推荐流启动运行态时,若卡片摘要不足以携带角色图、地块图集和路径配置,必须先补读完整 work profile 再传入运行态。平台壳层必须同步注册 `jump-hop-workspace``jump-hop-generating``jump-hop-result``jump-hop-runtime``jump-hop-gallery-detail` 阶段,并在 `appPageRoutes.ts` 映射 `/creation/jump-hop/workspace``/creation/jump-hop/generating``/creation/jump-hop/result``/gallery/jump-hop/detail``/runtime/jump-hop`,同时持有 session、work、run、gallery、busy/error 与生成进度状态,避免只合入渲染分支但遗漏状态源或分享路径导致 typecheck 失败、刷新回首页。
推荐页允许未登录直接游玩跳一跳运行态;`/api/runtime/jump-hop/runs``/jump``/restart` 采用可选鉴权,未登录时仍记录 `work_play_start`,但埋点需标记匿名语义
跳一跳作品架走创作中心的统一作品列表:前端通过 `/api/creation/jump-hop/works` 拉取作品摘要,草稿态会与 pending notice 合并后显示在作品架里,已发布作品点击后会先按 profileId 读取完整详情再进入详情或运行态。生成中作品仍以后端摘要里的 `generationStatus` 为准,刷新后应能恢复等待遮罩,不能只依赖内存 notice
删除等破坏性动作当前未接入 jump-hop 删除 API如果后续要在作品架提供删除入口必须先补齐后端/SpacetimeDB/前端整条删除链路,再开放按钮。
推荐页匿名游玩不再限定为跳一跳。移动端一级 `推荐` Tab 是内嵌运行态刷卡流,会自动选择推荐作品并启动对应玩法;桌面端首页不启动这套移动推荐运行态,而是渲染桌面发现壳,展示 `今日游戏``推荐``作品分类` 等桌面内容。断点事实统一走 `platformEntryResponsive.ts``usePlatformDesktopLayout()`,平台壳和首页视图必须共用同一个判断,避免桌面发现页与移动推荐页同时挂载、重复触发请求或启动运行态。推荐页嵌入运行态启动时按真实身份分流:已登录用户或本地已有 access token 时继续使用账号 Bearer但请求选项必须是 local auth impact避免单卡 401 清空整站登录态;只有确认为匿名访客时才申请短期 Runtime Guest Token并只把它作为局部请求头传给运行态客户端不写入全局登录态、不触发 refresh也不把匿名流量伪装成普通用户。当前覆盖矩阵为跳一跳、视觉小说、抓大鹅 Match3D、方洞挑战、拼图、敲木鱼、大鱼吃小鱼、汪汪声浪。每个模板的启动请求、推荐页内后续运行态动作以及需要上报的 play/finish/leaderboard/next-level 类请求都必须继续按该身份分流公开读取入口仍可匿名读取创作、个人作品、删除、发布、Remix 等账号/所有权动作仍保持普通用户鉴权。
## 敲木鱼
@@ -240,10 +256,10 @@ RPG / 拼图等运行态存档选择入口统一在个人中心 `常用功能 >
- 后端裁决结果:后端根据 start run 与 finish 派生指标校验后的正式单局结果。
- 基础统计:只记录正式 `published` run 的开始、结算和派生指标,草稿试玩不写正式统计。
- 公开广场:统一读取 `bark_battle_gallery_view` 这类 read model不再由前端自己拼公开列表。
- 创作者信息:草稿架、已发布作品架、统一作品详情和公开广场都必须展示后端返回的 `authorDisplayName`,不得只在详情页内层可见。
- 创作者信息:统一作品详情和公开广场都必须展示后端返回的 `authorDisplayName`,不得只在详情页内层可见;草稿 Tab 作品架遵循平台作品架统一口径,无论草稿 / 已发布都不外露作者信息
- 拟声词:配置字段为 `onomatopoeia`。创作者未手动编辑时,前端根据主题 / 竞技背景描述、玩家形象描述和对手形象描述生成高能词池;创作者手动编辑后按自定义词池发布。默认词池只在命中狗相关主题时加入狗叫词,不能把非狗主题强行带回狗语义。
当前入口默认开放:`visible=true``open=true``badge=可创建`,入口参考图使用 `/creation-type-references/bark-battle.webp`。创作入口使用 7 字段表单(作品标题、简介、主题 / 竞技背景描述 `themeDescription`、玩家形象描述、对手形象描述、拟声词、难度);提交后先进入 `bark-battle-generating` 独立生成页,自动生成玩家形象、对手形象和竞技背景三图。生成页即使部分槽位失败也要继续落到结果页,失败槽位保留错误态和单槽重试入口,不在生成页停留。结果页只保留单槽重试、重新生成和上传,不再展示一次生成按钮、音频配置入口、皮肤预设入口或排名配置。发布成功后先跳统一作品详情页 `/works/detail?work=BB-xxxxxxxx`,正式 `published` runtime 从作品详情页进入并必须使用真实麦克风;`draft` 可试玩,可使用 mock 输入,且不写正式统计。草稿与已发布作品在外部卡片、作品架和广场列表展示创作者名称。
当前入口默认开放:`visible=true``open=true``badge=可创建`,入口参考图使用 `/creation-type-references/bark-battle.webp`。创作入口使用 7 字段表单(作品标题、简介、主题 / 竞技背景描述 `themeDescription`、玩家形象描述、对手形象描述、拟声词、难度);提交后先进入 `bark-battle-generating` 独立生成页,自动生成玩家形象、对手形象和竞技背景三图。生成页即使部分槽位失败也要继续落到结果页,失败槽位保留错误态和单槽重试入口,不在生成页停留。结果页只保留单槽重试、重新生成和上传,不再展示一次生成按钮、音频配置入口、皮肤预设入口或排名配置。发布成功后先跳统一作品详情页 `/works/detail?work=BB-xxxxxxxx`,正式 `published` runtime 从作品详情页进入并必须使用真实麦克风;`draft` 可试玩,可使用 mock 输入,且不写正式统计。统一作品详情和广场列表展示创作者名称;草稿 Tab 作品架不外露创作者名称,已发布作品只在右上角常驻分享入口
移动端创作 Tab 内嵌 Bark Battle 表单时,只保留外层 Tab 面板承担纵向滚动;表单自身移动端不再创建独立纵向滚动容器,底部“生成草稿”按钮作为普通表单尾部并保留 safe-area 底部间距,避免与最后一组输入框、移动端键盘或底部 TabBar 形成套滚动 / 遮挡。
@@ -251,7 +267,7 @@ RPG / 拼图等运行态存档选择入口统一在个人中心 `常用功能 >
- 创作 Tab 表单:填写作品标题、简介、主题 / 竞技背景描述、玩家形象描述、对手形象描述、拟声词和难度。拟声词支持换行、逗号、顿号、斜杠或竖线分隔;未手动编辑时随主题 / 形象描述自动重算,手动编辑后保持创作者自定义。
- 草稿编译:`POST /api/creation/bark-battle/drafts` 写入配置 JSON返回包含 `draftId`、稳定 `workId``configVersion``rulesetVersion` 的草稿结果。
- 生成页:`bark-battle-generating` 自动并行产出玩家形象、对手形象和竞技背景三图;前端按槽位实时显示生成中 / 已生成 / 失败状态,三图都走 Bark Battle 专用后端生图接口 `POST /api/creation/bark-battle/images/generate`,由后端按 `player-character``opponent-character``ui-background` 分别拼装正式提示词、写入 `generated-bark-battle-assets` 私有资产前缀并返回实际 prompt。玩家 / 对手形象提示词必须保持用户形象描述,不强行注入狗相关主体,并要求正面、单个完整形象和透明背景。部分失败也继续进入结果页。
- 生成页:`bark-battle-generating` 自动并行产出玩家形象、对手形象和竞技背景三图;前端生成页 UI 和其它玩法保持同一圆环主视觉,`media/create_bg_video.mp4` 作为固定全屏页面背景层循环静音播放,主进度圆环居中展示总进度,只保留当前步骤名称和当前步骤进度,不再渲染三行槽位列表。视频层需要显式触发播放。三图都走 Bark Battle 专用后端生图接口 `POST /api/creation/bark-battle/images/generate`,由后端按 `player-character``opponent-character``ui-background` 分别拼装正式提示词、写入 `generated-bark-battle-assets` 私有资产前缀并返回实际 prompt。玩家 / 对手形象提示词必须保持用户形象描述,不强行注入狗相关主体,并要求正面、单个完整形象和透明背景。部分失败也继续进入结果页。
- 结果页:围绕三图槽位展示错误态与已生成结果,只保留单槽重试、重新生成和上传,不再提供一次生成按钮、音频配置入口或排名配置。
- 手动上传:结果页通过平台资产直传 `/api/assets/direct-upload-tickets``/api/assets/objects/confirm` 写入私有资产,再把返回的历史 generated 路径写回草稿配置。
- 发布:结果页确认后必须携带草稿返回的同一个 `workId` 和结果页最终 `publishedSnapshot` 调用 `POST /api/creation/bark-battle/works/publish`SpacetimeDB 发布态的 `config_json` 必须使用该最终快照works summary 若拿到 `publishedSnapshotJson` 也优先使用最终快照映射封面三图。发布成功后先进入统一作品详情页,再由详情页进入正式 runtime缺少 `workId` 的旧草稿状态需要重新生成草稿。

View File

@@ -0,0 +1,29 @@
# 拼图生成页进度口径
更新时间:`2026-05-24`
## 目标
拼图草稿生成页的步骤推进只跟随真实生成结果;步骤内部允许使用本地假进度增强等待反馈。未收到当前步骤完成信号前,生成页必须停留在当前步骤,不得按预计耗时自动跳到后续步骤。
## 落地口径
- 总进度和当前步骤内百分比可以按已耗时平滑增长,但进入生成页的初始帧必须从 `0%` 开始,非完成态最多停在 `98%`
- 未收到首个真实里程碑前,页面仍停留在当前步骤,总进度在 `0-88` 区间内平滑推进;收到 `88/94/96` 里程碑后,分别在 `88-94``94-96``96-98` 区间内推进,避免步骤不跳时总进度也停死。
- 后端 `progressPercent` 低于 `88` 只作为当前会话状态记录,不得把生成页阶段推到首个图片里程碑;低于首个里程碑时页面仍按当前视图进入时间从 `0%` 平滑展示。
- 步骤状态以真实阶段为准:`phase` / 后端会话进度 / 最终完成或失败回包才允许跨步。
- 拼图生成页恢复持久化 `generationStatus=generating` 草稿时,展示进度使用“进入生成页的当前时间”作为 `startedAtMs`;不得再用作品摘要 `updatedAt` 推导展示起点,避免刷新后首帧直接跳到 `80%+`
- 拼图和抓大鹅等生成页从作品架 / 刷新恢复进入时,前端应把展示态生成状态重基准到进入页面的当前时间;后台 session 的 `progressPercent` 与历史里程碑只保留为状态事实,不得直接作为首帧总进度。
- 当前步骤未完成时,后续步骤保持待处理;即使预计时间耗尽,也只能让当前步骤内部进度接近或达到上限,不能自动完成后续步骤。
- 抓大鹅等非拼图小游戏的生成页也遵守初始帧 `0%`:没有后端资产计数时,当前步骤内假进度按玩法预计等待总时长从 `0` 平滑推进,不使用固定 `0.5` 这类常量起步。
- 步骤卡片只展示标题和进度,不展示详细描述。
- 生成拼图首图步骤按 4 分钟预估;完整 AI 重绘路径总预计时长为 448 秒,上传图且关闭 AI 重绘时跳过首图生成,仍为 208 秒。
## 验收
- `src/services/miniGameDraftGenerationProgress.test.ts` 覆盖拼图步骤不会单纯按时间推进。
- `src/services/miniGameDraftGenerationProgress.test.ts` 覆盖后端 `progressPercent < 88` 时不会抬高进入生成页的初始总进度。
- `src/services/miniGameDraftGenerationProgress.test.ts` 覆盖抓大鹅等非拼图生成页初始总进度为 `0%`
- `src/components/CustomWorldGenerationView.test.tsx` 覆盖步骤详情不在生成页渲染。
- `src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "persisted generating"` 覆盖刷新后继续生成中拼图 / 抓大鹅草稿不会继承旧 `updatedAt` 导致总进度首帧过高。
- 文档主图谱的拼图章节同步保留该口径。

View File

@@ -0,0 +1,28 @@
# 生成页圆环布局口径
更新时间:`2026-05-24`
## 目标
所有玩法的生成页统一收敛为参考图同款等待态:顶部只保留返回入口和生成状态胶囊,页面中段用大圆环展示总进度,圆环左右悬浮“预计等待 / 已耗时”,下方只保留当前步骤单卡和当前作品信息卡,不再渲染步骤列表块。
## 落地口径
- 共用生成页 `CustomWorldGenerationView` 的主进度条使用居中 SVG 大圆弧,默认保留正下方 90 度留空,`media/create_bg_video.mp4` 作为固定全屏背景层循环静音播放;圆弧覆盖在背景之上展示总进度。视频层需要显式触发播放,不能只依赖 `autoPlay/loop/muted` 属性。
- 生成页背景视频必须留在生成页容器内部,直接作为 `fixed inset-0` 的底层背景,不要再通过 portal 挂到 `document.body`;页面根容器使用 `z-[1]`、背景容器使用 `z-0`,确保顶部导航、圆环和当前步骤卡都稳定覆盖在视频之上。
- 预计等待 / 已耗时信息卡要压缩为更轻的半透明窄卡,标签使用 `9px-10px`,数值使用 `12px-13px`,字号对齐其他生成页 UI 的小字号,不再使用偏大的提示文本;卡片标题和时间值都居中显示,两个数值只展示时间本身,调用侧不要再拼接“预计还需”或“已耗时”前缀。圆环中心不再保留独立白底块,空心圆环只保留条状进度,圆弧半径继续加大,进度数字与“总进度”标题整体上移,靠近圆环上半区。
- 顶部导航区采用“返回创作中心 / 状态胶囊”结构,返回按钮使用左箭头图标,字号使用 `text-xs-sm`,状态胶囊使用 `11px-12px`,展示 `素材生成中``草稿生成中` 等调用侧传入文案。
- 圆弧区域不再包独立大卡片,左右悬浮信息卡只展示“预计等待”和“已耗时”;总进度数值放在圆弧内侧偏上的位置并保持更小字号。当前圆环外径以 `w-[min(35rem,94vw)] sm:w-[52rem]` 为基准,圆弧使用 `r=166``strokeWidth=18` 的 SVG 描边,不再使用 `conic-gradient + mask`,避免进度条边缘模糊。
- 从作品架或刷新后的持久化生成中草稿进入生成页时,前端必须重置“展示态 startedAtMs”为进入生成页的当前时间后端 `progressPercent` 只用于后续真实步骤推进,不得参与首帧总进度展示,避免恢复生成页首帧直接显示 `80%+`
- 生成页只展示半透明“当前步骤”单卡,卡片内只保留步骤名称、步骤状态、步骤进度条和轻量加载指示;“当前步骤”标签使用 `10px-11px`,步骤名称使用 `14px-15px`,状态使用 `11px-12px`,不再渲染步骤列表或步骤详情。
- 当前作品信息放在圆角信息卡中,标题固定使用 `13px`;有结构化字段时以两列信息块展示,例如“题材 / 素材数量”,无结构化字段时才展示纯文本设定。
- 汪汪声浪生成页 `BarkBattleGeneratingView` 也必须对齐同一垂直布局,不再继续展示三行槽位列表或左右分栏抢占主视觉。
- 汪汪声浪的总进度按三槽位已完成数量换算;当前步骤只显示第一个未完成槽位的名称与进度。
## 验收
- `src/components/CustomWorldGenerationView.test.tsx` 覆盖圆环主视觉和单步卡片。
- `src/components/bark-battle-creation/BarkBattleGeneratingView.test.tsx` 覆盖汪汪声浪生成页对齐后的圆环布局。
- 两个生成页都应在测试里断言页面根容器层级高于背景视频容器,且背景视频确实是页面子节点,避免 portal 背景把业务 UI 压住。
- 还应断言圆弧正下方留空、圆环中心没有独立底色块,时间卡和总进度字号缩小后仍能在桌面与移动端正常排版;同时断言时间卡 `text-center`、标题行 `justify-center`、总进度内容区上移到 `pt-[4%]`,圆弧 DOM 为 SVG包含清晰的 track/fill circle 描边。
- 页面在桌面和移动端都不应再出现生成步骤列表块,圆环和当前步骤卡不能被外层卡片嵌套出双层面板感。

View File

@@ -93,9 +93,11 @@ server-rs + Axum + SpacetimeDB
7. 主站入口已锁定移动端页面级缩放;单个游戏页面不要再重复实现整页缩放锁定。
8. 图像输入通用 UI 统一走 `src/components/common/CreativeImageInputPanel.tsx`。外层页面持有业务状态组件只承担上传卡、预览、参考图缩略图、AI 重绘开关、错误展示和提交按钮。
9. 发现页 `分类` 子频道的筛选必须打开独立 dialog / drawer / modal至少支持玩法类型过滤与排序切换筛选结果为空时显示空状态不把筛选内容展开在当前列表下方。
10. “我的”页泥点、游戏时长、玩过三张统计卡只展示各自标签和值,内容居中且不换行,不在统计区底部展示“更新于”时间
11. RPG 等运行态的战斗飘字、血量变化和即时反馈必须在暗色、噪声高的场景背景上保持可读:使用高亮文字、深色描边、强阴影或小面积半透明底,不只依赖红/绿文字本身表达伤害或治疗
11. 平台亮色 UI 配色以陶泥儿主视觉为准:暖白 / 米杏底、陶土橙主按钮、深棕正文与浅杏边框;新增界面优先复用 `src/index.css``--platform-*` 主题变量和 `apps/admin-web/src/styles/admin.css` 的同系色值,不再引入粉红、蓝绿等独立主色方案
10. 移动端“我的”页顶部品牌行承载扫码和设置入口,正文按参考图顺序组织为头像 / 昵称 / 陶泥号、会员横幅、三张统计卡、每日任务、五项常用功能宫格、设置入口、可选次级入口和法律信息;`media/profile/` 中的陶泥素材作为该页图形资产。常用功能宫格固定承载泥点充值、邀请好友、兑换码、玩家社区、反馈与建议;页面不再提供独立存档按钮入口,填邀请码仅在新用户可填写窗口内展示为次级入口
11. “我的”页泥点、游戏时长、已玩游戏数量三张统计卡只展示各自标签和值,三个统计 icon 使用小尺寸普通 UI 档位,内容不换行,不在统计区底部展示“更新于”时间;移动端昵称、会员卡、每日任务、常用功能和法律信息也应保持 `10px``14px` 的普通 UI 字号区间,避免展示级字号挤压内容
12. 移动端“我的”页需要兼容窄屏:头像 / 昵称 / 陶泥号、三张统计卡、每日任务、五项常用功能、可选次级入口和法律信息都必须能在底部固定 TabBar 上方完整滚动露出,不得与底部 dock、刘海 safe-area 或相邻 UI 元素遮挡重叠
13. RPG 等运行态的战斗飘字、血量变化和即时反馈必须在暗色、噪声高的场景背景上保持可读:使用高亮文字、深色描边、强阴影或小面积半透明底,不只依赖红/绿文字本身表达伤害或治疗。
14. 平台亮色 UI 配色以陶泥儿主视觉为准:暖白 / 米杏底、陶土橙主按钮、深棕正文与浅杏边框;新增界面优先复用 `src/index.css``--platform-*` 主题变量和 `apps/admin-web/src/styles/admin.css` 的同系色值,不再引入粉红、蓝绿等独立主色方案。
## 文案与编码