收口运行态阶段加载提示
RPG runtime 主阶段懒加载提示改用 PlatformSubpanel 新增阶段路由加载提示的公共子面板断言 同步 PlatformUiKit 文档和 Hermes 决策记录
This commit is contained in:
@@ -70,6 +70,7 @@
|
|||||||
- 2026-06-10 追加:个人中心存档 / 玩过弹窗里的简单空态使用 `PlatformEmptyState surface="subpanel" size="inline"`,玩过弹窗的“可继续 / 玩过”分区标题使用 `PlatformFieldLabel variant="section"`,已玩作品白底按钮卡使用 `PlatformSubpanel as="button" surface="flat" radius="sm" padding="md" interactive`;`SaveArchiveCard` 因含图片遮罩和加载态暂不并入本轮。
|
- 2026-06-10 追加:个人中心存档 / 玩过弹窗里的简单空态使用 `PlatformEmptyState surface="subpanel" size="inline"`,玩过弹窗的“可继续 / 玩过”分区标题使用 `PlatformFieldLabel variant="section"`,已玩作品白底按钮卡使用 `PlatformSubpanel as="button" surface="flat" radius="sm" padding="md" interactive`;`SaveArchiveCard` 因含图片遮罩和加载态暂不并入本轮。
|
||||||
- 2026-06-10 追加:平台入口壳纯 Suspense fallback 使用 `PlatformSubpanel radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳;带恢复动作、错误语义或运行态遮罩的提示面板不和纯加载 fallback 同批迁移。
|
- 2026-06-10 追加:平台入口壳纯 Suspense fallback 使用 `PlatformSubpanel radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳;带恢复动作、错误语义或运行态遮罩的提示面板不和纯加载 fallback 同批迁移。
|
||||||
- 2026-06-10 追加:平台入口作品详情读取 / 错误提示、Agent 工作区恢复提示和生成结果恢复面板也迁移到 `PlatformSubpanel`;普通提示使用 `radius="sm" padding="none"`,带恢复动作的 `CreationResultRecoveryPanel` 使用 `radius="xl" padding="none"`,玩法 runtime overlay 继续保留专用层级语义。验证命令:`npm run test -- src/components/common/PlatformSubpanel.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts`。
|
- 2026-06-10 追加:平台入口作品详情读取 / 错误提示、Agent 工作区恢复提示和生成结果恢复面板也迁移到 `PlatformSubpanel`;普通提示使用 `radius="sm" padding="none"`,带恢复动作的 `CreationResultRecoveryPanel` 使用 `radius="xl" padding="none"`,玩法 runtime overlay 继续保留专用层级语义。验证命令:`npm run test -- src/components/common/PlatformSubpanel.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts`。
|
||||||
|
- 2026-06-10 追加:RPG runtime 主阶段路由里的平台首页、角色选择和冒险面板懒加载提示使用 `PlatformSubpanel radius="sm" padding="none"`;路由器只保留 Suspense 分流和提示文案,运行态 HUD / overlay 不并入该普通提示面板规则。验证命令:`npm run test -- src/components/rpg-runtime-shell/RpgRuntimeStageRouter.test.tsx src/components/common/PlatformSubpanel.test.tsx`。
|
||||||
- 2026-06-10 追加:个人中心钱包账单弹窗的“暂无账单记录”使用 `PlatformEmptyState surface="subpanel" size="inline"`,账单行使用 `PlatformSubpanel as="div" surface="flat" radius="xs" padding="none"`;业务 JSX 只保留来源、时间、收支色值、余额右对齐和局部间距 / 阴影。
|
- 2026-06-10 追加:个人中心钱包账单弹窗的“暂无账单记录”使用 `PlatformEmptyState surface="subpanel" size="inline"`,账单行使用 `PlatformSubpanel as="div" surface="flat" radius="xs" padding="none"`;业务 JSX 只保留来源、时间、收支色值、余额右对齐和局部间距 / 阴影。
|
||||||
- 2026-06-10 追加:个人中心邀请弹窗里的社区二维码卡、邀请码展示卡、成功邀请容器和邀请用户行使用 `PlatformSubpanel`,简单空态使用 `PlatformEmptyState`,小标题使用 `PlatformFieldLabel variant="section"`;外层弹窗、query 自动打开、复制邀请和提交邀请码状态机不随 UI chrome 收口改动。
|
- 2026-06-10 追加:个人中心邀请弹窗里的社区二维码卡、邀请码展示卡、成功邀请容器和邀请用户行使用 `PlatformSubpanel`,简单空态使用 `PlatformEmptyState`,小标题使用 `PlatformFieldLabel variant="section"`;外层弹窗、query 自动打开、复制邀请和提交邀请码状态机不随 UI chrome 收口改动。
|
||||||
- 2026-06-10 追加:个人中心任务中心任务条目使用 `PlatformSubpanel radius="sm" padding="md"` 承接原 `platform-subpanel` 外壳;业务组件只保留任务标题、进度、奖励、状态和领取按钮逻辑。
|
- 2026-06-10 追加:个人中心任务中心任务条目使用 `PlatformSubpanel radius="sm" padding="md"` 承接原 `platform-subpanel` 外壳;业务组件只保留任务标题、进度、奖励、状态和领取按钮逻辑。
|
||||||
|
|||||||
@@ -84,6 +84,7 @@
|
|||||||
- `PlatformSubpanel`:接收 `as="section" | "div" | "article" | "aside" | "button"`、`title`、`titleVariant="section" | "strong"`、`actions`、`interactive`、`padding="tight" | "row" | "xs" | "sm" | "md" | "lg" | "none"`、`radius="xs" | "sm" | "md" | "lg" | "xl"`、`surface="platform" | "flat" | "soft" | "dark" | "darkSky" | "darkEmerald" | "darkAmber" | "darkRose" | "danger"`、`className`、`headerClassName`、`titleClassName`、`actionsClassName`、`bodyClassName` 和 `children`;静态 element 透传 `aria-*`、`data-*` 等原生属性,`as="button"` 时透传普通 button 属性并默认 `type="button"`。Module 统一承接平台结果页 / 工作台 / 个人中心子面板外壳、`PlatformFieldLabel variant="section"` 标题、强标题、右侧动作区、内容容器和普通白底列表卡片的 hover / focus / disabled 交互态。`surface="platform"` 复用 `platform-subpanel` token;`surface="soft" + padding="tight"` 用于标签编辑新增输入行等白底柔和紧凑行,`surface="soft" + padding="row"` 用于上传预览横向已选素材条等白底柔和横向行;`surface="danger"` 用于整卡危险选中态;`radius="xl" + padding="lg"` 用于方洞等更大圆角的标准结果页面板;`surface="platform" + radius="xl" + padding="none"` 用于只需要公共边框 / 背景 / 大圆角且内部自带固定比例内容的静态封面壳,`surface="platform" + radius="xl" + padding="sm"` 可用局部 `sm:p-5` 保留物品详情类响应式内容面板;`surface="flat" + radius="sm" + padding="sm"` 用于素材 / 音频 / 排行榜 / 选项编辑 / 局部进度状态等小型白底卡片,`surface="flat" + radius="sm" + padding="none"` 仅用于只包已有图片、图集、角色或路径预览且不需要 fallback / overlay 的白底壳;需要图片源、fallback、固定比例或 overlay 时优先使用 `PlatformMediaFrame`。需要整卡点击或缩略图点击时组合 `as="button" interactive`。拼图结果页作品名称 / 描述 / 标签编辑 / 智能修订条 / 关卡卡片、拼图图库详情页封面轮播壳 / 题材标签 / 关卡摘要、敲木鱼结果页主预览面板 / 作品标题 / 简介 / 主题标签 / 飘字 / 音效、敲木鱼工作台功德词条面板、跳一跳结果页预览 / 操作面板 / 排行榜 / 轻量媒体壳、拼消消创作工作台左侧表单面板、拼消消结果页预览 / 统计 / 操作面板 / 轻量媒体壳、方洞结果页封面 / 主信息 / 形状 / 洞口标准面板、方洞形状 / 洞口选项卡与缩略图按钮、RPG 结果页开发资产诊断摘要 / 条目 / 空态、RPG 个人中心未登录提示、通用音频输入面板、视觉小说创作工作台画风选择面板、视觉小说结果页素材 / 音频小面板、视觉小说结果页作品 / 开场 / 运行配置 / 世界观标准编辑面板、视觉小说 runtime 历史条目 / 存档列表、抓大鹅创作工作台难度小面板、抓大鹅结果页作品 / 难度 / 统计 / UI素材预览标准面板 / 当前难度摘要小卡 / 物品详情五视角面板 / 物品图集分组卡 / 批量素材生成进度卡、汪汪声浪结果页草稿摘要 / 素材槽 / 预览卡、平台反馈页问题描述 / 上传凭证 / 联系方式区块、自定义世界实体目录世界基调 / 角色维度 / 基本设定条目 / 场景幕级缩略图 / 目录卡片媒体壳 / 目录卡片整卡壳、创作中心作品架加载骨架卡,以及 creative-agent 工作台目录 / 目标就绪 / 空消息 / 过程 / 关卡计划 / 关卡计划小卡 / 模板确认理由面板已先迁移;`PlatformTagEditor` 内部新增输入行使用 `surface="soft" padding="tight"`,`PlatformUploadPreviewCard layout="inline"` 内部横向已选素材条使用 `surface="soft" padding="row"`。后续同类白底面板、白底轻量媒体壳或白底交互列表卡片只传标题、动作、内容、可访问属性和点击回调,不再重复写 `platform-subpanel rounded-[1.25rem] p-4`、`rounded-[1.35rem] p-4 sm:p-5`、`platform-subpanel rounded-[1.5rem] p-4 sm:p-5`、`rounded-[1.5rem] border border-[var(--platform-subpanel-border)] bg-[var(--platform-subpanel-fill)]`、`rounded-[1rem] border ... bg-white/72 p-3`、`rounded-[1rem] border ... bg-white/68 p-2`、`rounded-[1rem] border ... bg-white/68 px-3 py-2`、`rounded-[1.1rem] border ... bg-white/58 p-3`、`rounded-[1rem] border ... bg-white/80`、`hover:bg-white disabled:cursor-not-allowed disabled:opacity-55`、标题行 flex 和 `text-xs font-bold tracking-[0.18em]`。
|
- `PlatformSubpanel`:接收 `as="section" | "div" | "article" | "aside" | "button"`、`title`、`titleVariant="section" | "strong"`、`actions`、`interactive`、`padding="tight" | "row" | "xs" | "sm" | "md" | "lg" | "none"`、`radius="xs" | "sm" | "md" | "lg" | "xl"`、`surface="platform" | "flat" | "soft" | "dark" | "darkSky" | "darkEmerald" | "darkAmber" | "darkRose" | "danger"`、`className`、`headerClassName`、`titleClassName`、`actionsClassName`、`bodyClassName` 和 `children`;静态 element 透传 `aria-*`、`data-*` 等原生属性,`as="button"` 时透传普通 button 属性并默认 `type="button"`。Module 统一承接平台结果页 / 工作台 / 个人中心子面板外壳、`PlatformFieldLabel variant="section"` 标题、强标题、右侧动作区、内容容器和普通白底列表卡片的 hover / focus / disabled 交互态。`surface="platform"` 复用 `platform-subpanel` token;`surface="soft" + padding="tight"` 用于标签编辑新增输入行等白底柔和紧凑行,`surface="soft" + padding="row"` 用于上传预览横向已选素材条等白底柔和横向行;`surface="danger"` 用于整卡危险选中态;`radius="xl" + padding="lg"` 用于方洞等更大圆角的标准结果页面板;`surface="platform" + radius="xl" + padding="none"` 用于只需要公共边框 / 背景 / 大圆角且内部自带固定比例内容的静态封面壳,`surface="platform" + radius="xl" + padding="sm"` 可用局部 `sm:p-5` 保留物品详情类响应式内容面板;`surface="flat" + radius="sm" + padding="sm"` 用于素材 / 音频 / 排行榜 / 选项编辑 / 局部进度状态等小型白底卡片,`surface="flat" + radius="sm" + padding="none"` 仅用于只包已有图片、图集、角色或路径预览且不需要 fallback / overlay 的白底壳;需要图片源、fallback、固定比例或 overlay 时优先使用 `PlatformMediaFrame`。需要整卡点击或缩略图点击时组合 `as="button" interactive`。拼图结果页作品名称 / 描述 / 标签编辑 / 智能修订条 / 关卡卡片、拼图图库详情页封面轮播壳 / 题材标签 / 关卡摘要、敲木鱼结果页主预览面板 / 作品标题 / 简介 / 主题标签 / 飘字 / 音效、敲木鱼工作台功德词条面板、跳一跳结果页预览 / 操作面板 / 排行榜 / 轻量媒体壳、拼消消创作工作台左侧表单面板、拼消消结果页预览 / 统计 / 操作面板 / 轻量媒体壳、方洞结果页封面 / 主信息 / 形状 / 洞口标准面板、方洞形状 / 洞口选项卡与缩略图按钮、RPG 结果页开发资产诊断摘要 / 条目 / 空态、RPG 个人中心未登录提示、通用音频输入面板、视觉小说创作工作台画风选择面板、视觉小说结果页素材 / 音频小面板、视觉小说结果页作品 / 开场 / 运行配置 / 世界观标准编辑面板、视觉小说 runtime 历史条目 / 存档列表、抓大鹅创作工作台难度小面板、抓大鹅结果页作品 / 难度 / 统计 / UI素材预览标准面板 / 当前难度摘要小卡 / 物品详情五视角面板 / 物品图集分组卡 / 批量素材生成进度卡、汪汪声浪结果页草稿摘要 / 素材槽 / 预览卡、平台反馈页问题描述 / 上传凭证 / 联系方式区块、自定义世界实体目录世界基调 / 角色维度 / 基本设定条目 / 场景幕级缩略图 / 目录卡片媒体壳 / 目录卡片整卡壳、创作中心作品架加载骨架卡,以及 creative-agent 工作台目录 / 目标就绪 / 空消息 / 过程 / 关卡计划 / 关卡计划小卡 / 模板确认理由面板已先迁移;`PlatformTagEditor` 内部新增输入行使用 `surface="soft" padding="tight"`,`PlatformUploadPreviewCard layout="inline"` 内部横向已选素材条使用 `surface="soft" padding="row"`。后续同类白底面板、白底轻量媒体壳或白底交互列表卡片只传标题、动作、内容、可访问属性和点击回调,不再重复写 `platform-subpanel rounded-[1.25rem] p-4`、`rounded-[1.35rem] p-4 sm:p-5`、`platform-subpanel rounded-[1.5rem] p-4 sm:p-5`、`rounded-[1.5rem] border border-[var(--platform-subpanel-border)] bg-[var(--platform-subpanel-fill)]`、`rounded-[1rem] border ... bg-white/72 p-3`、`rounded-[1rem] border ... bg-white/68 p-2`、`rounded-[1rem] border ... bg-white/68 px-3 py-2`、`rounded-[1.1rem] border ... bg-white/58 p-3`、`rounded-[1rem] border ... bg-white/80`、`hover:bg-white disabled:cursor-not-allowed disabled:opacity-55`、标题行 flex 和 `text-xs font-bold tracking-[0.18em]`。
|
||||||
- `PlatformSubpanel` 补充:个人中心玩过弹窗里的已玩作品按钮卡使用 `as="button" surface="flat" radius="sm" padding="md" interactive`,业务组件只保留作品标题 / 副标题 / 类型胶囊 / 作品号 / 最近游玩 / 时长内容和粉色 hover 边框,不再手写白底按钮卡 chrome。
|
- `PlatformSubpanel` 补充:个人中心玩过弹窗里的已玩作品按钮卡使用 `as="button" surface="flat" radius="sm" padding="md" interactive`,业务组件只保留作品标题 / 副标题 / 类型胶囊 / 作品号 / 最近游玩 / 时长内容和粉色 hover 边框,不再手写白底按钮卡 chrome。
|
||||||
- `PlatformSubpanel` 补充:平台入口壳纯 Suspense fallback、作品详情读取 / 错误提示和 Agent 工作区恢复提示使用 `radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳,业务层只保留居中布局、提示文案和局部内边距;生成结果恢复面板使用 `radius="xl" padding="none"` 保留恢复动作与固定内容间距。玩法 runtime overlay 仍保留专用层级语义,后续单独评估。
|
- `PlatformSubpanel` 补充:平台入口壳纯 Suspense fallback、作品详情读取 / 错误提示和 Agent 工作区恢复提示使用 `radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳,业务层只保留居中布局、提示文案和局部内边距;生成结果恢复面板使用 `radius="xl" padding="none"` 保留恢复动作与固定内容间距。玩法 runtime overlay 仍保留专用层级语义,后续单独评估。
|
||||||
|
- `PlatformSubpanel` 补充:RPG runtime 主阶段路由里的平台首页、角色选择和冒险面板懒加载提示使用 `radius="sm" padding="none"` 承接原 `platform-subpanel` 外壳;路由器只保留 Suspense 分流和提示文案,运行态 HUD / overlay 继续保留专用层级语义。
|
||||||
- `PlatformSubpanel` 补充:个人中心钱包账单行使用 `as="div" surface="flat" radius="xs" padding="none"`,业务组件只保留来源、时间、收入 / 支出色值、余额右对齐和局部 `px-3 py-3 shadow-sm`;后续同类白底数据行优先从该组合扩展。
|
- `PlatformSubpanel` 补充:个人中心钱包账单行使用 `as="div" surface="flat" radius="xs" padding="none"`,业务组件只保留来源、时间、收入 / 支出色值、余额右对齐和局部 `px-3 py-3 shadow-sm`;后续同类白底数据行优先从该组合扩展。
|
||||||
- `PlatformSubpanel` 补充:个人中心邀请弹窗里的社区二维码卡、邀请码展示卡、成功邀请容器和邀请用户行使用 `surface="flat" | "soft"` 的白底子面板;复制按钮、奖励说明卡和弹窗状态机不并入本轮。
|
- `PlatformSubpanel` 补充:个人中心邀请弹窗里的社区二维码卡、邀请码展示卡、成功邀请容器和邀请用户行使用 `surface="flat" | "soft"` 的白底子面板;复制按钮、奖励说明卡和弹窗状态机不并入本轮。
|
||||||
- `PlatformSubpanel` 补充:个人中心任务中心里的任务条目使用 `radius="sm" padding="md"` 承接原 `platform-subpanel` 外壳;业务组件只保留任务标题、进度、奖励、状态和领取按钮逻辑。
|
- `PlatformSubpanel` 补充:个人中心任务中心里的任务条目使用 `radius="sm" padding="md"` 承接原 `platform-subpanel` 外壳;业务组件只保留任务标题、进度、奖励、状态和领取按钮逻辑。
|
||||||
@@ -150,7 +151,7 @@
|
|||||||
18.2.1. 个人中心昵称弹窗输入框迁移到 `PlatformTextField surface="editorDark"`;昵称状态机、校验、保存和弹窗壳层不随输入框 chrome 收口改动。
|
18.2.1. 个人中心昵称弹窗输入框迁移到 `PlatformTextField surface="editorDark"`;昵称状态机、校验、保存和弹窗壳层不随输入框 chrome 收口改动。
|
||||||
18.3. 平台字段标签迁移到 `PlatformFieldLabel`;视觉小说结果页、抓大鹅结果页作品 / 封面 / 素材字段标题、方洞结果页主信息 / 形状 / 洞口 / 历史图片字段标题、拼图结果页关卡详情 / 发布弹窗字段标题、拼消消创作工作台作品标题 / 简介 / 主题词、跳一跳创作工作台主题、大鱼素材弹窗 prompt、RPG 发布弹窗发布检查 / 封面设置、汪汪声浪轻配置编辑器、宝贝识物工作台、通用创作图片输入面板主图 / 提示词标题,以及认证登录 / 绑定 / 邀请码 / 账号安全表单标题已先迁移。后续结果页、编辑弹窗、工作台、通用创作输入面板或认证表单中只表达字段名称的小标题,优先选择 `field` / `section` / `form` / `pill` / `accentPill`,不要在业务 JSX 中重复拼字段标题 class;认证表单和提示词字段保留外层原生 `label`,带品牌化插画、运行态 HUD 或复杂步骤标题时可暂保留专用标题。
|
18.3. 平台字段标签迁移到 `PlatformFieldLabel`;视觉小说结果页、抓大鹅结果页作品 / 封面 / 素材字段标题、方洞结果页主信息 / 形状 / 洞口 / 历史图片字段标题、拼图结果页关卡详情 / 发布弹窗字段标题、拼消消创作工作台作品标题 / 简介 / 主题词、跳一跳创作工作台主题、大鱼素材弹窗 prompt、RPG 发布弹窗发布检查 / 封面设置、汪汪声浪轻配置编辑器、宝贝识物工作台、通用创作图片输入面板主图 / 提示词标题,以及认证登录 / 绑定 / 邀请码 / 账号安全表单标题已先迁移。后续结果页、编辑弹窗、工作台、通用创作输入面板或认证表单中只表达字段名称的小标题,优先选择 `field` / `section` / `form` / `pill` / `accentPill`,不要在业务 JSX 中重复拼字段标题 class;认证表单和提示词字段保留外层原生 `label`,带品牌化插画、运行态 HUD 或复杂步骤标题时可暂保留专用标题。
|
||||||
18.3.1. 个人中心存档 / 玩过弹窗里的简单空态、分区标题和已玩作品白底按钮卡分别迁移到 `PlatformEmptyState`、`PlatformFieldLabel` 与 `PlatformSubpanel`;`SaveArchiveCard` 带图片遮罩和加载视觉,仍保留专用实现,后续需要单独视觉验收后再决定是否收口。
|
18.3.1. 个人中心存档 / 玩过弹窗里的简单空态、分区标题和已玩作品白底按钮卡分别迁移到 `PlatformEmptyState`、`PlatformFieldLabel` 与 `PlatformSubpanel`;`SaveArchiveCard` 带图片遮罩和加载视觉,仍保留专用实现,后续需要单独视觉验收后再决定是否收口。
|
||||||
18.3.2. 平台入口壳中的纯 Suspense fallback、作品详情读取 / 错误提示、Agent 工作区恢复提示和 `CreationResultRecoveryPanel` 外壳迁移到 `PlatformSubpanel`;加载 / 错误提示使用 `radius="sm" padding="none"`,带恢复动作的结果恢复面板使用 `radius="xl" padding="none"`,玩法 runtime overlay 后续单独评估。
|
18.3.2. 平台入口壳中的纯 Suspense fallback、作品详情读取 / 错误提示、Agent 工作区恢复提示、RPG runtime 主阶段懒加载提示和 `CreationResultRecoveryPanel` 外壳迁移到 `PlatformSubpanel`;加载 / 错误提示使用 `radius="sm" padding="none"`,带恢复动作的结果恢复面板使用 `radius="xl" padding="none"`,玩法 runtime overlay 后续单独评估。
|
||||||
18.3.3. 个人中心钱包账单弹窗里的空态和账单行分别迁移到 `PlatformEmptyState` 与 `PlatformSubpanel`;账单展示只保留收支内容、余额和时间,不在业务 JSX 重复白底列表行 chrome。
|
18.3.3. 个人中心钱包账单弹窗里的空态和账单行分别迁移到 `PlatformEmptyState` 与 `PlatformSubpanel`;账单展示只保留收支内容、余额和时间,不在业务 JSX 重复白底列表行 chrome。
|
||||||
18.3.4. 个人中心邀请弹窗内部的二维码卡、邀请码卡、成功邀请列表、邀请用户行、小标题和简单空态分别迁移到 `PlatformSubpanel`、`PlatformFieldLabel` 与 `PlatformEmptyState`;外层弹窗、query 自动打开、复制邀请、提交邀请码和社区面板信息架构不随本轮改变。
|
18.3.4. 个人中心邀请弹窗内部的二维码卡、邀请码卡、成功邀请列表、邀请用户行、小标题和简单空态分别迁移到 `PlatformSubpanel`、`PlatformFieldLabel` 与 `PlatformEmptyState`;外层弹窗、query 自动打开、复制邀请、提交邀请码和社区面板信息架构不随本轮改变。
|
||||||
18.3.5. 个人中心任务中心任务条目迁移到 `PlatformSubpanel`;任务选择、领取、奖励和完成态仍由任务 ViewModel / 业务流程控制。
|
18.3.5. 个人中心任务中心任务条目迁移到 `PlatformSubpanel`;任务选择、领取、奖励和完成态仍由任务 ViewModel / 业务流程控制。
|
||||||
@@ -290,6 +291,7 @@
|
|||||||
- `npm run test -- src/components/common/PlatformSubpanel.test.tsx`
|
- `npm run test -- src/components/common/PlatformSubpanel.test.tsx`
|
||||||
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "profile played modal|profile page keeps save archives inside played stats panel"`
|
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/rpg-entry/RpgEntryFlowShell.agent.interaction.test.tsx -t "profile played modal|profile page keeps save archives inside played stats panel"`
|
||||||
- `npm run test -- src/components/common/PlatformSubpanel.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts`
|
- `npm run test -- src/components/common/PlatformSubpanel.test.tsx src/components/platform-entry/PlatformEntryFlowShellImpl.test.ts`
|
||||||
|
- `npm run test -- src/components/rpg-runtime-shell/RpgRuntimeStageRouter.test.tsx src/components/common/PlatformSubpanel.test.tsx`
|
||||||
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "wallet ledger"`
|
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "wallet ledger"`
|
||||||
- `npm run test -- src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformSubpanel.test.tsx`
|
- `npm run test -- src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformSubpanel.test.tsx`
|
||||||
- `npm run test -- src/components/unified-creation/workspaces/WoodenFishCreationWorkspace.test.tsx src/components/common/PlatformTextField.test.tsx src/components/common/PlatformIconButton.test.tsx`
|
- `npm run test -- src/components/unified-creation/workspaces/WoodenFishCreationWorkspace.test.tsx src/components/common/PlatformTextField.test.tsx src/components/common/PlatformIconButton.test.tsx`
|
||||||
|
|||||||
161
src/components/rpg-runtime-shell/RpgRuntimeStageRouter.test.tsx
Normal file
161
src/components/rpg-runtime-shell/RpgRuntimeStageRouter.test.tsx
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
/* @vitest-environment jsdom */
|
||||||
|
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { expect, test, vi } from 'vitest';
|
||||||
|
|
||||||
|
import {
|
||||||
|
AnimationState,
|
||||||
|
type GameState,
|
||||||
|
} from '../../types';
|
||||||
|
import {
|
||||||
|
RpgRuntimeStageRouter,
|
||||||
|
type RpgRuntimeStageRouterProps,
|
||||||
|
} from './RpgRuntimeStageRouter';
|
||||||
|
|
||||||
|
vi.mock('../platform-entry/PlatformEntryFlowShell', () => ({
|
||||||
|
PlatformEntryFlowShell: () => <div>平台首页</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../rpg-entry/RpgEntryCharacterSelectView', () => ({
|
||||||
|
RpgEntryCharacterSelectView: () => <div>角色选择</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('../rpg-runtime-panels/RpgRuntimePanelRouter', () => ({
|
||||||
|
RpgRuntimePanelRouter: () => <div>冒险面板</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const noop = () => {};
|
||||||
|
|
||||||
|
function createGameState(overrides: Partial<GameState> = {}): GameState {
|
||||||
|
return {
|
||||||
|
worldType: null,
|
||||||
|
customWorldProfile: null,
|
||||||
|
playerCharacter: null,
|
||||||
|
runtimeStats: {
|
||||||
|
playTimeMs: 0,
|
||||||
|
lastPlayTickAt: null,
|
||||||
|
hostileNpcsDefeated: 0,
|
||||||
|
questsAccepted: 0,
|
||||||
|
itemsUsed: 0,
|
||||||
|
scenesTraveled: 0,
|
||||||
|
},
|
||||||
|
currentScene: 'test-scene',
|
||||||
|
storyHistory: [],
|
||||||
|
characterChats: {},
|
||||||
|
animationState: AnimationState.IDLE,
|
||||||
|
currentEncounter: null,
|
||||||
|
npcInteractionActive: false,
|
||||||
|
currentScenePreset: null,
|
||||||
|
sceneHostileNpcs: [],
|
||||||
|
playerX: 0,
|
||||||
|
playerOffsetY: 0,
|
||||||
|
playerFacing: 'right',
|
||||||
|
playerActionMode: 'idle',
|
||||||
|
scrollWorld: false,
|
||||||
|
inBattle: false,
|
||||||
|
playerHp: 100,
|
||||||
|
playerMaxHp: 100,
|
||||||
|
playerMana: 30,
|
||||||
|
playerMaxMana: 30,
|
||||||
|
playerSkillCooldowns: {},
|
||||||
|
activeCombatEffects: [],
|
||||||
|
playerCurrency: 0,
|
||||||
|
playerInventory: [],
|
||||||
|
playerEquipment: {
|
||||||
|
weapon: null,
|
||||||
|
armor: null,
|
||||||
|
relic: null,
|
||||||
|
},
|
||||||
|
npcStates: {},
|
||||||
|
quests: [],
|
||||||
|
roster: [],
|
||||||
|
companions: [],
|
||||||
|
currentBattleNpcId: null,
|
||||||
|
currentNpcBattleMode: null,
|
||||||
|
currentNpcBattleOutcome: null,
|
||||||
|
sparReturnEncounter: null,
|
||||||
|
sparPlayerHpBefore: null,
|
||||||
|
sparPlayerMaxHpBefore: null,
|
||||||
|
sparStoryHistoryBefore: null,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildProps(
|
||||||
|
overrides: Partial<RpgRuntimeStageRouterProps> = {},
|
||||||
|
): RpgRuntimeStageRouterProps {
|
||||||
|
const gameState = createGameState();
|
||||||
|
|
||||||
|
return {
|
||||||
|
gameState,
|
||||||
|
visibleGameState: gameState,
|
||||||
|
visibleCurrentStory: null,
|
||||||
|
isLoading: false,
|
||||||
|
aiError: null,
|
||||||
|
bottomTab: 'adventure',
|
||||||
|
setBottomTab: noop,
|
||||||
|
selectionStage: 'platform',
|
||||||
|
setSelectionStage: noop,
|
||||||
|
isCharacterSelectionStage: false,
|
||||||
|
hasSavedGame: false,
|
||||||
|
savedSnapshot: null,
|
||||||
|
handleContinueGame: noop,
|
||||||
|
handleStartNewGame: noop,
|
||||||
|
handleCustomWorldSelect: noop,
|
||||||
|
handleBackToWorldSelect: noop,
|
||||||
|
handleCharacterSelect: noop,
|
||||||
|
displayedOptions: [],
|
||||||
|
hideStoryOptions: false,
|
||||||
|
canRefreshOptions: false,
|
||||||
|
handleRefreshOptions: noop,
|
||||||
|
refreshNpcChatOptions: () => false,
|
||||||
|
handleSceneTransitionChoice: noop,
|
||||||
|
handleNpcChatInput: () => false,
|
||||||
|
exitNpcChat: () => false,
|
||||||
|
characterChatUi: {} as RpgRuntimeStageRouterProps['characterChatUi'],
|
||||||
|
inventoryUi: {} as RpgRuntimeStageRouterProps['inventoryUi'],
|
||||||
|
battleRewardUi: {} as RpgRuntimeStageRouterProps['battleRewardUi'],
|
||||||
|
questUi: {} as RpgRuntimeStageRouterProps['questUi'],
|
||||||
|
npcChatQuestOfferUi:
|
||||||
|
{} as RpgRuntimeStageRouterProps['npcChatQuestOfferUi'],
|
||||||
|
goalUi: {} as RpgRuntimeStageRouterProps['goalUi'],
|
||||||
|
companionRenderStates: [],
|
||||||
|
characterChatSummaries: {},
|
||||||
|
openOverlayPanel: noop,
|
||||||
|
openCampModal: noop,
|
||||||
|
openPartyMemberDetails: noop,
|
||||||
|
adventureStatistics: {
|
||||||
|
playTimeMs: 0,
|
||||||
|
hostileNpcsDefeated: 0,
|
||||||
|
questsAccepted: 0,
|
||||||
|
questsCompleted: 0,
|
||||||
|
questsTurnedIn: 0,
|
||||||
|
itemsUsed: 0,
|
||||||
|
scenesTraveled: 0,
|
||||||
|
currentSceneName: '测试场景',
|
||||||
|
playerCurrency: 0,
|
||||||
|
inventoryItemCount: 0,
|
||||||
|
inventoryStackCount: 0,
|
||||||
|
activeCompanionCount: 0,
|
||||||
|
rosterCompanionCount: 0,
|
||||||
|
},
|
||||||
|
musicVolume: 0.5,
|
||||||
|
onMusicVolumeChange: noop,
|
||||||
|
resetForSaveAndExit: noop,
|
||||||
|
handleSaveAndExit: noop,
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('renders the main content loading fallback with PlatformSubpanel chrome', async () => {
|
||||||
|
render(<RpgRuntimeStageRouter {...buildProps()} />);
|
||||||
|
|
||||||
|
const loadingLabel = screen.getByText('正在加载平台首页...');
|
||||||
|
const panel = loadingLabel.closest('.platform-subpanel');
|
||||||
|
|
||||||
|
expect(panel).not.toBeNull();
|
||||||
|
expect(panel?.className).toContain('rounded-[1rem]');
|
||||||
|
expect(panel?.className).toContain('px-5 py-4');
|
||||||
|
expect(panel?.className).toContain('text-zinc-300');
|
||||||
|
await screen.findByText('平台首页');
|
||||||
|
});
|
||||||
@@ -19,6 +19,7 @@ import type {
|
|||||||
StoryOption,
|
StoryOption,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
import { UI_CHROME } from '../../uiAssets';
|
import { UI_CHROME } from '../../uiAssets';
|
||||||
|
import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
||||||
import type { GameCanvasEntitySelection } from '../GameCanvas';
|
import type { GameCanvasEntitySelection } from '../GameCanvas';
|
||||||
import type { SelectionStage } from '../platform-entry/platformEntryTypes';
|
import type { SelectionStage } from '../platform-entry/platformEntryTypes';
|
||||||
import type { RpgAdventureStatistics } from './types';
|
import type { RpgAdventureStatistics } from './types';
|
||||||
@@ -47,9 +48,14 @@ const RpgRuntimePanelRouter = lazy(async () => {
|
|||||||
function MainContentLoadingFallback({ label }: { label: string }) {
|
function MainContentLoadingFallback({ label }: { label: string }) {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full min-h-0 items-center justify-center">
|
<div className="flex h-full min-h-0 items-center justify-center">
|
||||||
<div className="platform-subpanel rounded-2xl px-5 py-4 text-sm text-zinc-300">
|
<PlatformSubpanel
|
||||||
|
as="div"
|
||||||
|
radius="sm"
|
||||||
|
padding="none"
|
||||||
|
className="px-5 py-4 text-sm text-zinc-300"
|
||||||
|
>
|
||||||
{label}
|
{label}
|
||||||
</div>
|
</PlatformSubpanel>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user