收口智能创作首页空态

将智能创作首页抽屉空态迁移到 PlatformEmptyState

将智能创作首页错误提示迁移到 PlatformStatusMessage

删除智能创作首页本地空态和错误提示 chrome

新增 CreativeAgentHome 公共组件断言

更新 PlatformUiKit 文档和 Hermes 决策记录
This commit is contained in:
2026-06-10 14:26:41 +08:00
parent 9b36903021
commit 694b2fa209
5 changed files with 66 additions and 21 deletions
File diff suppressed because one or more lines are too long
@@ -67,6 +67,7 @@
- `PlatformStatusMessage` 补充:大鱼吃小鱼结果页发布校验阻断项使用 `tone="warning" surface="platform" size="xs"`;结果页只保留阻断项裁剪和文案,不再手写 amber 文本列表。
- `PlatformStatusMessage` 补充:拼图首访 onboarding 的输入错误和登录保存错误使用 `surface="editorDark"`onboarding 只保留错误文案和条件渲染,不再手写暗色红色错误条。
- `PlatformStatusMessage` 补充:平台作品详情页分享复制反馈使用 `surface="platform"` 并按 `shareState` 映射 `success / error`;详情页只保留复制状态机和文案,不再为失败态复用成功 toast chrome。
- `PlatformStatusMessage` 补充:creative-agent 首页错误提示使用 `tone="error" surface="platform" size="md"`;首页只保留宽度对齐布局 class 和错误文案,不再手写 danger panel chrome。
- `PlatformRuntimeStatusToast`:接收 `tone="error" | "success" | "info" | "warning" | "neutral"``surface="light" | "dark" | "solid"``size="xs" | "sm" | "md"``shape="pill" | "rounded"``children``className`;根节点固定带 `platform-runtime-status-toast` 稳定类名,默认按 `tone` 写入 `role="alert/status"``aria-live`。它只承接运行态 HUD 中短错误、成功和反馈 chip 的圆角、字号、阴影、色值和可访问语义,具体浮层位置、玩法资产按钮、计分牌、蓄力提示、强品牌 primary 按钮仍由玩法 runtime 控制。跳一跳、拼图、敲木鱼、方洞和宝贝爱画运行态的短错误 / 成功 / 投放反馈已先迁移;后续同类短 toast 不再手写 `rounded-full bg-white/* text-*`、暗色 `border-rose/emerald bg-*/text-*` 或单玩法 `*-runtime-error-chip`
- `PlatformDarkOptionCard`:接收 `selected``tone="emerald" | "sky" | "rose" | "amber"``radius="sm" | "md" | "lg"``padding="sm" | "md" | "lg"``children``className` 和原生 button props;根节点固定带 `platform-dark-option-card` 稳定类名,统一承接 RPG 暗色弹窗 / 面板中的 selected / idle / hover / disabled 可选项卡按钮外观。NPC 交易模式、交易物品行、赠礼候选、招募替换候选、角色素材工作室动作预览格、营地编组替换位按钮和角色聊天建议按钮已先迁移;业务页只保留选中判断、点击回调和内容布局,不再重复手写 `rounded-* border px-3 py-*``border-*-400/* bg-*-500/10``border-white/* bg-black/20 hover:border-white/15`
- `PlatformEmptyState`:接收 `surface="soft" | "dashed" | "subpanel" | "editorDark"``size="compact" | "panel" | "inline"``tone="base" | "soft"``children``className`;根节点固定带 `platform-empty-state` 稳定类名,业务测试可断言公共空态接入。`soft + compact` 用于公开广场、排行和作品架内的轻量空态,`soft + panel` 用于创作中心作品架整块空态,`dashed + panel` 用于素材选择、历史资源等弹窗的大面积空态或读取态,`subpanel + inline` 用于视觉小说 runtime、个人中心充值 / 任务等白底子面板内的无操作空态,`editorDark + compact/inline` 用于 RPG 大编辑器、实体详情弹窗、营地编组、角色聊天和运行态设置弹窗等暗色面板里的纯展示空态 / 禁用提示。组件只承接外观,不内置业务文案。
@@ -75,6 +76,7 @@
- `PlatformEmptyState` 补充:个人中心邀请弹窗里的“已填写邀请码 / 暂无成功邀请”使用 `surface="subpanel"`;业务组件保留面板分支和邀请状态机,不再为无操作提示手写白底空态。
- `PlatformEmptyState` 补充:creation-agent 聊天区里的“暂无消息”使用 `surface="subpanel" size="compact"`;工作台保留消息列表滚动容器和文案,不再手写居中空态字号、颜色和高度 class。
- `PlatformEmptyState` 补充:大鱼吃小鱼结果页缺少可编辑草稿时使用 `surface="subpanel" size="compact"`;结果页只保留草稿分支和文案,不再为白底无操作提示手写 `PlatformSubpanel` 空面板。
- `PlatformEmptyState` 补充:creative-agent 首页抽屉“暂无创作记录”使用 `surface="subpanel" size="inline"`;抽屉只保留分组和历史条目分支,不再手写白底 bordered empty chrome。
- `PlatformTextField`:接收 `variant="input" | "textarea"``surface="platform" | "editorDark"``size="xs" | "sm" | "md" | "lg"``density="default" | "compact" | "roomy"``tone="warm" | "rose" | "emerald" | "sky"``className` 和原生 input / textarea props;统一承接平台白底与 RPG 暗色弹窗里的圆角输入框、文本域、禁用态、密度、字号 / 行高和焦点色,暗色 surface 根节点固定带 `platform-text-field--editor-dark` 稳定类名。`PlatformSelectField` 复用同一套输入 chrome 承接下拉框。业务页继续持有 `value``onChange``aria-label``rows``placeholder``option` 等语义,不再重复拼 `rounded-[1rem] border border-[var(--platform-subpanel-border)] bg-white/86 px-3 py-3``rounded-[0.85rem] bg-white/90 px-3 py-2``bg-white/90 px-4 py-3`、暗色 `border-white/10 bg-black/30 px-4 py-3``focus:border-* focus:ring-*`。抓大鹅结果页作品信息、封面描述、素材名称和批量物品名称,方洞结果页主信息表单和形状 / 洞口选项字段,拼图 / 敲木鱼结果页作品信息字段,视觉小说结果页的音乐生成、作品信息、开场、运行配置、角色、场景、阶段和世界观普通文本 / 下拉字段,以及视觉小说 / 抓大鹅 / 汪汪声浪 / 宝贝识物 / 拼消消 / 跳一跳创作工作台普通输入字段已先迁移;自定义选择弹窗角色名字 / 背景补充 / 生成模式 / 世界描述和角色聊天草稿等暗色字段使用 `surface="editorDark"`。通用创作图片输入面板的提示词文本域也使用该 Module,只通过局部 class 保留高度和底部浮动上传按钮避让。认证图形验证码答案、短信 / 密码登录、重置密码、绑定手机号、邀请码和账号安全表单字段,以及个人中心兑换码 / 邀请码输入使用 `surface="platform"`,业务层只保留认证 / 兑换流程、受控值、原生属性和校验提示。
- `PlatformTextField` 补充:个人中心昵称弹窗输入框使用 `surface="editorDark" size="lg" density="roomy"`,业务组件保留外层原生 `label` / sr-only “新昵称”、`autoFocus``maxLength`、Enter 提交和保存状态;局部 class 只保留暗色弹窗里的 `bg-white/10`、文字色和焦点边框,不再手写 input chrome。
- `PlatformTextField` 补充:`PlatformTagEditor` 内部新增标签输入框使用 `density="compact" size="xs"` 复用同一输入 chrome;标签编辑器只保留新增输入状态、解析、Enter / Escape 行为和按钮组合,不再手写输入框边框、白底、字号、焦点色或禁用态。
@@ -300,6 +302,7 @@
- `npm run test -- src/components/common/PlatformTextField.test.tsx src/components/common/PlatformToggleRow.test.tsx src/components/puzzle-clear-creation/PuzzleClearWorkspace.test.tsx src/components/unified-creation/workspaces/JumpHopCreationWorkspace.test.tsx`
- `npm run test -- src/components/CustomWorldEntityEditorModal.test.tsx src/components/common/PlatformTextField.test.tsx src/components/common/PlatformEmptyState.test.tsx`
- `npm run test -- src/components/creative-agent/CreativeAgentInputComposer.test.tsx src/components/common/PlatformTextField.test.tsx src/components/common/PlatformStatusMessage.test.tsx src/components/common/PlatformSubpanel.test.tsx`
- `npm run test -- src/components/creative-agent/CreativeAgentHome.test.tsx src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformStatusMessage.test.tsx`
- `npm run test -- src/components/common/PlatformTextField.test.tsx src/components/common/CreativeImageInputPanel.test.tsx`
- `npm run test -- src/components/common/CreativeImageInputPanel.test.tsx src/components/common/PlatformFieldLabel.test.tsx`
- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx -t "profile nickname modal"`
@@ -0,0 +1,47 @@
/* @vitest-environment jsdom */
import { render, screen } from '@testing-library/react';
import { expect, test, vi } from 'vitest';
import { CreativeAgentHome } from './CreativeAgentHome';
function renderHome({
error = null,
}: {
error?: string | null;
} = {}) {
render(
<CreativeAgentHome
recentItems={[]}
isBusy={false}
error={error}
onStartNewChat={vi.fn()}
onOpenHistoryItem={vi.fn()}
onOpenDrafts={vi.fn()}
onOpenAccount={vi.fn()}
onOpenSettings={vi.fn()}
onSubmitMessage={vi.fn()}
/>,
);
}
test('CreativeAgentHome uses shared empty state for empty drawer history', () => {
renderHome();
const emptyState = screen.getByText('暂无创作记录');
expect(emptyState.className).toContain('platform-empty-state');
expect(emptyState.className).toContain('bg-white/74');
});
test('CreativeAgentHome uses shared status message for home error', () => {
renderHome({ error: '创作助手暂时不可用' });
const statusMessage = screen.getByText('创作助手暂时不可用');
expect(statusMessage.className).toContain('platform-status-message');
expect(statusMessage.className).toContain('creative-agent-home__error');
expect(statusMessage.className).toContain(
'border-[var(--platform-button-danger-border)]',
);
});
@@ -14,7 +14,9 @@ import {
import { useMemo, useState } from 'react';
import type { CreativeAgentInputPart } from '../../../packages/shared/src/contracts/creativeAgent';
import { PlatformEmptyState } from '../common/PlatformEmptyState';
import { PlatformIconButton } from '../common/PlatformIconButton';
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
import type { CreationWorkShelfItem } from '../custom-world-home/creationWorkShelf';
import { RpgEntryBrandLogo } from '../rpg-entry/RpgEntryBrandLogo';
import { CreativeAgentInputComposer } from './CreativeAgentInputComposer';
@@ -252,7 +254,9 @@ function CreativeAgentDrawer({
</section>
))
) : (
<div className="creative-agent-drawer__empty"></div>
<PlatformEmptyState surface="subpanel" size="inline">
</PlatformEmptyState>
)}
</div>
@@ -366,7 +370,14 @@ export function CreativeAgentHome({
</div>
{error ? (
<div className="creative-agent-home__error">{error}</div>
<PlatformStatusMessage
tone="error"
surface="platform"
size="md"
className="creative-agent-home__error font-semibold"
>
{error}
</PlatformStatusMessage>
) : null}
</main>
-19
View File
@@ -8963,14 +8963,6 @@ button {
.creative-agent-home__error {
max-width: 38rem;
border: 1px solid var(--platform-button-danger-border);
border-radius: 1rem;
background: var(--platform-button-danger-fill);
color: var(--platform-button-danger-text);
padding: 0.85rem 1rem;
font-size: 0.875rem;
font-weight: 800;
line-height: 1.6;
}
.creative-agent-home__composer {
@@ -9139,17 +9131,6 @@ button {
color 180ms ease;
}
.creative-agent-drawer__empty {
border: 1px solid var(--platform-subpanel-border);
border-radius: 1rem;
background: var(--platform-subpanel-fill);
color: var(--platform-text-soft);
padding: 0.9rem 1rem;
text-align: center;
font-size: 0.9rem;
font-weight: 800;
}
.creative-agent-drawer__avatar {
display: inline-flex;
width: 3rem;