diff --git a/.hermes/shared-memory/decision-log.md b/.hermes/shared-memory/decision-log.md
index 478cd318..534f6046 100644
--- a/.hermes/shared-memory/decision-log.md
+++ b/.hermes/shared-memory/decision-log.md
@@ -56,6 +56,7 @@
- 2026-06-10 追加:`PlatformModalCloseButton variant="pixel"` 承接 `UnifiedModal variant="pixel"` 头部圆形关闭入口;`UnifiedModal` 只选择 `platformIcon / pixel` 变体并保留 closeDisabled、Backdrop、Escape 和 portal 语义,不再手写 X 图标、aria 和关闭按钮 class。验证命令:`npm run test -- src/components/common/UnifiedModal.test.tsx src/components/common/PlatformModalCloseButton.test.tsx src/components/common/UnifiedConfirmDialog.test.tsx`。
- 2026-06-09 追加:RPG 大编辑器暗色面板内的保存和角色槽动作继续走本地 `ActionButton`,不再混用白底平台 `platform-button` class;平台白底动作收口和编辑器暗色动作收口保持两套视觉边界。
- 2026-06-10 追加:`PlatformActionButton surface="editorDark"` 承接 RPG 暗色弹窗 / 运行面板里的普通取消、确认、刷新和编组动作,支持 `size="xxs"` 与 `tone="success" | "warning"`;`tone="accent"` 承接暗色壳层内的琥珀实心 CTA,`tone="accentSoft"` 承接依赖局部 accent 变量的柔和强调按钮。角色自定义 footer、自定义世界生成 footer、地图切换确认、营地编组普通动作和角色聊天刷新动作已迁移。暗色可选项卡仍使用 `PlatformDarkOptionCard`,像素风发送 / 强品牌动作继续保留专用布局。验证命令:`npm run test -- src/components/common/platformActionButtonModel.test.ts src/components/common/PlatformActionButton.test.tsx src/components/SelectionCustomizationModals.test.tsx src/components/CompanionCampModal.test.tsx src/components/MapModal.test.tsx src/components/CharacterChatModal.test.tsx`。
+- 2026-06-10 追加:RPG 首页创作 / 草稿顶栏的钱包快捷入口通过同文件 `TopbarWalletShortcutButton` 复用 `PlatformActionButton tone="accentSoft" shape="pill" size="xs"` 与 `PlatformIconBadge`;移动端 / 桌面端继续保留 `.platform-mobile-create-wallet-chip`、`.platform-desktop-create-wallet-chip` 和 `.platform-desktop-search` 兼容 class,承接余额截断、桌面顶栏胶囊壳和既有测试锚点,点击语义仍统一走 `openRechargeOrRewardCodeModal`。验证命令:`npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`。
- 2026-06-10 追加:RPG 大编辑器里的当前角色、可选角色、预设背景和场景连接关系等暗色信息面板通过本地 `EditorInfoPanel` 复用 `PlatformSubpanel surface="dark"`;有右侧动作的面板也只向适配器传 actions,不再在业务 JSX 中重复手写暗色面板边框、底色、圆角、标题行和内容间距。验证命令:`npm run test -- src/components/CustomWorldEntityEditorModal.test.tsx -t "场景编辑器会在场景内展示槽位化多幕配置并保存"`。
- 2026-06-10 追加:作品详情底部“作品改造 / 作品编辑”和“启动”使用 `PlatformActionButton surface="platform" shape="pill" size="lg" fullWidth`;详情页保留 `platform-work-detail__remix / start` 局部 class 控制 sticky 底部栏位置、比例和品牌背景。验证命令:`npm run test -- src/components/platform-entry/PlatformWorkDetailView.test.tsx src/components/common/PlatformActionButton.test.tsx`。
- 2026-06-10 追加:作品详情点赞按钮使用 `PlatformActionButton tone="accentSoft"`;详情页只保留纵向排布、尺寸和 `--platform-action-accent` 局部变量,不再手写点赞按钮边框、底色、文字和阴影 chrome。验证命令:`npm run test -- src/components/platform-entry/PlatformWorkDetailView.test.tsx src/components/common/PlatformActionButton.test.tsx src/components/common/platformActionButtonModel.test.ts`。
diff --git a/docs/technical/【前端架构】PlatformUiKit弹窗组件收口计划-2026-06-08.md b/docs/technical/【前端架构】PlatformUiKit弹窗组件收口计划-2026-06-08.md
index 8b45c4d3..bfb3d416 100644
--- a/docs/technical/【前端架构】PlatformUiKit弹窗组件收口计划-2026-06-08.md
+++ b/docs/technical/【前端架构】PlatformUiKit弹窗组件收口计划-2026-06-08.md
@@ -222,6 +222,7 @@
19.1. `CopyFeedbackButton` 支持 `actionShape`,用于在复用共享复制状态机时直接对齐 `PlatformActionButton` 的圆角外观;拼图广场详情 hero 的“分享作品”已使用 `actionSurface="editorDark" actionShape="pill"`,不再手写复制按钮 rounded / border / bg class。
19.2. 拼图广场详情 hero 的返回、上一张 / 下一张关卡图入口迁移到 `PlatformIconButton variant="darkMini"`,修改作品和进入第 1 关迁移到 `PlatformActionButton`,分享动作继续使用 `CopyFeedbackButton` 但复用共享动作按钮 chrome;详情页只保留轮播、复制和跳转语义,不再手写 hero 区按钮壳。
19.3. 个人中心充值商品卡里的“购买 / 处理中”胶囊暂保留局部 `span`,不直接套用 `PlatformActionButton`,避免在 `PlatformSubpanel as="button"` 内再嵌套交互按钮;待出现第二个同形态的非交互 action chip 后,再决定是否沉淀独立的共享展示基元。
+19.3.1. RPG 首页创作 / 草稿顶栏的钱包快捷入口迁移到同文件适配器 `TopbarWalletShortcutButton`,内部复用 `PlatformActionButton tone="accentSoft" shape="pill" size="xs"` 与 `PlatformIconBadge`;移动端和桌面端继续保留 `.platform-mobile-create-wallet-chip`、`.platform-desktop-create-wallet-chip` 和 `.platform-desktop-search` 兼容 class,承接移动端余额截断、桌面顶栏胶囊底色以及既有测试锚点。入口点击仍统一走 `openRechargeOrRewardCodeModal`,不把充值 / 兑换码平台分流逻辑改散到两个顶栏分支里。
19.3. creative-agent 首页的侧边栏菜单、账号入口、开启新对话、我的创作、首页激励 CTA 和 prompt suggestion 按钮迁移到 `PlatformIconButton` / `PlatformActionButton`;首页继续保留 `creative-agent-home__*` 本地 class 承接透明顶栏、抽屉和品牌化胶囊视觉,不把视觉回收和语义收口绑成一次大改。`Beta` 徽标和历史记录纯文本行暂保留本地实现,等出现更多同构轻量列表行后再评估是否抽新的共享 row primitive。
19.4. 大鱼吃小鱼结果页 hero 的返回入口迁移到 `PlatformIconButton variant="darkMini"`,测试 / 发布动作迁移到 `PlatformActionButton surface="editorDark"`;结果页只保留测试运行、发布提交和文案状态语义,不再手写 hero 顶栏按钮壳。
20. 平台方形上传入口和紧凑虚线新增入口迁移到 `PlatformUploadTile`,上传后的图片预览迁移到 `PlatformUploadPreviewCard`;反馈页上传凭证入口 / 预览、敲木鱼工作台新增功德词条入口、通用创作图片面板的提示词参考图缩略图、抓大鹅封面编辑参考图缩略图、通用输入 Composer 已选参考图条、creation-agent 已选参考图条和拼图结果页关卡引用图横条已先迁移。方形缩略图使用默认 `layout="square"`,横向“已选择参考图 / 文件名 / 素材名 / 移除”条使用 `layout="inline"`;只读引用图条不传 `onRemove`,避免公共组件额外渲染删除入口。后续继续收口结果页素材上传、工作台参考图上传、紧凑虚线新增入口等上传 / 动作块时,业务页只保留文件选择、预览数组、预览回调、删除回调、校验逻辑或新增回调,上传方块外观、主副文案、缩略图壳、预览按钮、标题行、横向已选条、移除按钮和禁用态统一由 Module 承接;工具栏中的小图标上传仍继续使用 `PlatformIconButton asChild="label"`。
@@ -236,6 +237,7 @@
- `npm run test -- src/components/creative-agent/CreativeAgentHome.test.tsx src/components/auth/BindPhoneScreen.test.tsx`
- `npm run test -- src/components/creative-agent/CreativeAgentHome.test.tsx src/components/big-fish-result/BigFishResultView.test.tsx`
- `npm run test -- src/components/big-fish-result/BigFishResultView.test.tsx -t "renders generated formal previews with accurate status copy"`
+- `npm run test -- src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx`
- `npm run test -- src/components/common/UnifiedConfirmDialog.test.tsx`
- `npm run test -- src/components/common/useCopyFeedback.test.tsx`
- `npm run test -- src/components/common/CopyFeedbackButton.test.tsx`
diff --git a/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx b/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx
index 1ed70113..d59c9cc9 100644
--- a/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx
+++ b/src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx
@@ -3535,24 +3535,37 @@ test('logged in create tab shows real wallet balance beside the brand', () => {
const topbar = container.querySelector('.platform-mobile-topbar');
expect(topbar).toBeTruthy();
expect(
- topbar?.querySelector('.platform-mobile-create-wallet-chip'),
+ within(topbar as HTMLElement).getByRole('img', {
+ name: /陶泥儿 GENARRATIVE/u,
+ }),
).toBeTruthy();
- expect(topbar?.textContent).toContain('陶泥儿');
- expect(topbar?.textContent).toContain('1,234泥点');
+
+ const walletButton = within(topbar as HTMLElement).getByRole('button', {
+ name: /^1,234泥点$/u,
+ });
+
+ expect(walletButton.className).toContain('platform-mobile-create-wallet-chip');
+ expect(walletButton.className).toContain('platform-action-button--accent-soft');
+ expect(walletButton.querySelector('.platform-icon-badge')).toBeTruthy();
});
test('create tab wallet chip opens reward code when recharge entry is hidden', async () => {
const user = userEvent.setup();
mockNarrowMobileLayout();
- render(
+ const { container } = render(
,
);
- await user.click(screen.getByRole('button', { name: /^70泥点$/u }));
+ const topbar = container.querySelector('.platform-mobile-topbar');
+ expect(topbar).toBeTruthy();
+
+ await user.click(
+ within(topbar as HTMLElement).getByRole('button', { name: /^70泥点$/u }),
+ );
expect(await screen.findByPlaceholderText('输入兑换码')).toBeTruthy();
expect(mockGetRpgProfileRechargeCenter).not.toHaveBeenCalled();
@@ -3562,14 +3575,25 @@ test('create tab wallet chip opens recharge when recharge entry is enabled', asy
const user = userEvent.setup();
mockWechatDesktopLayout();
- render(
+ const { container } = render(
,
);
- await user.click(screen.getByRole('button', { name: /^70泥点$/u }));
+ const topbar = container.querySelector('.platform-desktop-topbar');
+ expect(topbar).toBeTruthy();
+
+ const walletButton = within(topbar as HTMLElement).getByRole('button', {
+ name: /^70泥点$/u,
+ });
+ expect(walletButton.className).toContain('platform-desktop-create-wallet-chip');
+ expect(walletButton.className).toContain('platform-desktop-search');
+ expect(walletButton.className).toContain('platform-action-button--accent-soft');
+ expect(walletButton.querySelector('.platform-icon-badge')).toBeTruthy();
+
+ await user.click(walletButton);
expect(await screen.findByText('账户充值')).toBeTruthy();
expect(mockGetRpgProfileRechargeCenter).toHaveBeenCalledTimes(1);
diff --git a/src/components/rpg-entry/RpgEntryHomeView.tsx b/src/components/rpg-entry/RpgEntryHomeView.tsx
index 7b00c8c8..edb28f69 100644
--- a/src/components/rpg-entry/RpgEntryHomeView.tsx
+++ b/src/components/rpg-entry/RpgEntryHomeView.tsx
@@ -1118,6 +1118,48 @@ function PublicCodeSearchBar({
);
}
+function TopbarWalletShortcutButton({
+ variant,
+ balanceLabel,
+ onClick,
+}: {
+ variant: 'mobile' | 'desktop';
+ balanceLabel: string;
+ onClick: () => void;
+}) {
+ const isMobile = variant === 'mobile';
+
+ return (
+
+ }
+ size="xs"
+ tone="neutral"
+ className={
+ isMobile
+ ? '!h-6 !w-6 !bg-[#ffe0ab] !text-[#cf7b34]'
+ : '!bg-[#ffe0ab] !text-[#cf7b34]'
+ }
+ />
+ {balanceLabel}
+
+ );
+}
+
function SaveArchivePreview({
entry,
className,
@@ -7369,21 +7411,13 @@ export function RpgEntryHomeView({
) : isAuthenticated &&
(activeTab === 'create' || activeTab === 'saves') ? (
-
+ onClick={openRechargeOrRewardCodeModal}
+ />
) : !isAuthenticated ? (
{isAuthenticated &&
(activeTab === 'create' || activeTab === 'saves') ? (
-
+ onClick={openRechargeOrRewardCodeModal}
+ />
) : null}