继续收口RPG发布检查弹窗壳层
RPG结果页发布检查弹窗复用 PlatformToolModalShell 保留发布检查、封面预览和发布动作业务语义 补充组件测试断言共享白底工具弹窗壳层 同步 PlatformUiKit 文档和 Hermes 决策记录
This commit is contained in:
@@ -2098,6 +2098,7 @@
|
|||||||
- 决策:`CustomWorldNpcVisualEditor.tsx` 的本地 `ActionButton` 和 `SkillEffectPreview.tsx` 的“重新预览”按钮也继续并入这条暗色按钮收口线,统一委托 `PlatformActionButton surface="editorDark"`;局部包装层只保留 `stopPropagation`、图标排布、`tone` 映射和极少量视觉微调。后续暗色编辑器里的局部动作按钮若只是普通 CTA,不再新增原生 `<button>` 实现,优先沿用“薄包装 + 共享按钮本体”模式。
|
- 决策:`CustomWorldNpcVisualEditor.tsx` 的本地 `ActionButton` 和 `SkillEffectPreview.tsx` 的“重新预览”按钮也继续并入这条暗色按钮收口线,统一委托 `PlatformActionButton surface="editorDark"`;局部包装层只保留 `stopPropagation`、图标排布、`tone` 映射和极少量视觉微调。后续暗色编辑器里的局部动作按钮若只是普通 CTA,不再新增原生 `<button>` 实现,优先沿用“薄包装 + 共享按钮本体”模式。
|
||||||
- 决策:RPG 创作侧标准 dark header / footer 动作也继续纳入同一条按钮收口线。`RpgCreationRoleAssetStudioModalImpl.tsx` 的 header“关闭”、`RpgCreationEntityEditorShared.tsx` 的 footer“取消”以及 `RpgCreationRoleAssetStudioFooter.tsx` 的“保存到当前角色”都改为委托 `PlatformActionButton surface="editorDark"`;局部壳层只保留布局、宽度/字号贴合和少量 tone 语义,不再为标准 dark close / cancel / save CTA 单独维护原生 `<button>` 基础 chrome。
|
- 决策:RPG 创作侧标准 dark header / footer 动作也继续纳入同一条按钮收口线。`RpgCreationRoleAssetStudioModalImpl.tsx` 的 header“关闭”、`RpgCreationEntityEditorShared.tsx` 的 footer“取消”以及 `RpgCreationRoleAssetStudioFooter.tsx` 的“保存到当前角色”都改为委托 `PlatformActionButton surface="editorDark"`;局部壳层只保留布局、宽度/字号贴合和少量 tone 语义,不再为标准 dark close / cancel / save CTA 单独维护原生 `<button>` 基础 chrome。
|
||||||
- 决策:RPG runtime overlay 里的标准 dark CTA 和可点击 dark row 也继续纳入这条收口线。`RpgAdventurePanelOverlays.tsx` 的 goal panel“知道了”、任务详情里的“领取任务 / 返回交付”、任务完成提示里的“打开任务日志”都改为委托 `PlatformActionButton surface="editorDark"`;设置面板里的“运行统计”入口改为 `PlatformSubpanel as="button" surface="dark"`。像素风 choice button、HUD launcher、奖励物品格和输入 composer 保持 runtime 专属语义,不继续硬并到普通平台按钮。
|
- 决策:RPG runtime overlay 里的标准 dark CTA 和可点击 dark row 也继续纳入这条收口线。`RpgAdventurePanelOverlays.tsx` 的 goal panel“知道了”、任务详情里的“领取任务 / 返回交付”、任务完成提示里的“打开任务日志”都改为委托 `PlatformActionButton surface="editorDark"`;设置面板里的“运行统计”入口改为 `PlatformSubpanel as="button" surface="dark"`。像素风 choice button、HUD launcher、奖励物品格和输入 composer 保持 runtime 专属语义,不继续硬并到普通平台按钮。
|
||||||
|
- 决策:`PlatformToolModalShell` 继续承接 RPG 结果页发布检查弹窗;`RpgCreationResultActionBar.tsx` 只保留发布检查、封面预览、封面设置和发布动作语义,不再直接维护 `createPortal`、平台主题 overlay、白底 remap panel、header close、body/footer spacing 和遮罩关闭逻辑。后续结果页 / 工具页里同形态的白底 portal 弹窗优先迁移到 `PlatformToolModalShell`;编辑器大壳、暗色 runtime overlay 和需要专属布局的面板继续保留局部 shell。
|
||||||
- 决策:NPC dark modal footer 和暗色明细空态也继续纳入同一条收口线。`NpcModals.tsx` 里的交易 / 赠礼 / 招募弹窗 footer 按钮和物品详情“关闭”按钮都改为委托 `PlatformActionButton surface="editorDark"`,交易右侧“请选择一件物品”提示改为 `PlatformEmptyState surface="editorDark"`;`CharacterInfoShared.tsx` 的 `BuildContributionDetailPanel` 空明细也改为 `PlatformEmptyState surface="editorDark"`。数量 stepper、赠礼 / 招募 option card、标签强度按钮这类带独立业务语义的控件继续保留局部实现。
|
- 决策:NPC dark modal footer 和暗色明细空态也继续纳入同一条收口线。`NpcModals.tsx` 里的交易 / 赠礼 / 招募弹窗 footer 按钮和物品详情“关闭”按钮都改为委托 `PlatformActionButton surface="editorDark"`,交易右侧“请选择一件物品”提示改为 `PlatformEmptyState surface="editorDark"`;`CharacterInfoShared.tsx` 的 `BuildContributionDetailPanel` 空明细也改为 `PlatformEmptyState surface="editorDark"`。数量 stepper、赠礼 / 招募 option card、标签强度按钮这类带独立业务语义的控件继续保留局部实现。
|
||||||
- 决策:详情页头部动作组合统一收口到 `src/components/common/PlatformDetailTopbar.tsx` 与 `src/components/common/PlatformDetailShareActions.tsx`。`PlatformDetailTopbar` 只负责返回按钮、标题居中槽位和右侧动作槽位的布局,可在 `pill` / `icon` 返回入口之间切换;`PlatformDetailShareActions` 只负责“前置 badge 区块 + 作品号复制 + 分享复制”这组稳定动作,并允许按页面关闭复制或分享其中一项。`RpgEntryWorldDetailView.tsx` 已接入 overlay 版完整动作组,`PlatformWorkDetailView.tsx` 已接入 icon topbar 与 solid 版作品号复制动作,同时继续保留公开详情页自己的顶部 icon 分享入口和分享反馈提示。后续详情页若只是复用返回、标题、作品号复制或分享动作排列,优先组合这两个薄组件,不把作者、摘要、封面、轮播或业务 CTA 塞进共享配置对象。
|
- 决策:详情页头部动作组合统一收口到 `src/components/common/PlatformDetailTopbar.tsx` 与 `src/components/common/PlatformDetailShareActions.tsx`。`PlatformDetailTopbar` 只负责返回按钮、标题居中槽位和右侧动作槽位的布局,可在 `pill` / `icon` 返回入口之间切换;`PlatformDetailShareActions` 只负责“前置 badge 区块 + 作品号复制 + 分享复制”这组稳定动作,并允许按页面关闭复制或分享其中一项。`RpgEntryWorldDetailView.tsx` 已接入 overlay 版完整动作组,`PlatformWorkDetailView.tsx` 已接入 icon topbar 与 solid 版作品号复制动作,同时继续保留公开详情页自己的顶部 icon 分享入口和分享反馈提示。后续详情页若只是复用返回、标题、作品号复制或分享动作排列,优先组合这两个薄组件,不把作者、摘要、封面、轮播或业务 CTA 塞进共享配置对象。
|
||||||
- 验证方式:`npm run test -- src/components/common/PlatformAsyncStatePanel.test.tsx src/components/platform-entry/PlatformProfileReferralModal.test.tsx src/components/platform-entry/PlatformProfileWalletLedgerModal.test.tsx src/components/platform-entry/PlatformProfilePlayedWorksModal.test.tsx src/components/platform-entry/PlatformProfileTaskCenterModal.test.tsx src/components/platform-entry/PlatformProfileRechargeModal.test.tsx src/components/common/PlatformSegmentedTabs.test.tsx src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx`、`npm run test -- src/components/common/PlatformModalCloseButton.test.tsx src/components/PixelCloseButton.test.tsx src/components/CharacterChatModal.test.tsx src/components/MapModal.test.tsx`、`npm run test -- src/components/common/useMudPointConfirmController.test.tsx src/components/match3d-result/Match3DResultView.test.tsx src/components/unified-creation/workspaces/PuzzleCreationWorkspace.interaction.test.tsx src/components/unified-creation/workspaces/Match3DCreationWorkspace.interaction.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/platform-entry/PlatformProfileRechargeModal.test.tsx src/components/CustomWorldEntityEditorModal.test.tsx src/components/rpg-creation-result/RpgCreationResultActionBar.test.tsx src/components/unified-creation/shared/PuzzleHistoryAssetPickerDialog.test.tsx src/components/puzzle-result/PuzzleResultView.test.tsx`、`npm run test -- src/components/common/CopyFeedbackButton.test.tsx src/components/common/PlatformActionButton.test.tsx src/components/AdventureEntityModal.test.tsx src/components/InventoryPanel.test.tsx src/components/rpg-creation-result/RpgCreationAssetDebugPanel.test.tsx src/components/visual-novel-result/VisualNovelResultView.test.tsx src/components/common/PlatformEmptyState.test.tsx src/components/rpg-creation-asset-studio/RpgCreationRoleAssetStudioModal.test.tsx src/components/auth/AccountModal.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.npcChat.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.questOffer.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。
|
- 验证方式:`npm run test -- src/components/common/PlatformAsyncStatePanel.test.tsx src/components/platform-entry/PlatformProfileReferralModal.test.tsx src/components/platform-entry/PlatformProfileWalletLedgerModal.test.tsx src/components/platform-entry/PlatformProfilePlayedWorksModal.test.tsx src/components/platform-entry/PlatformProfileTaskCenterModal.test.tsx src/components/platform-entry/PlatformProfileRechargeModal.test.tsx src/components/common/PlatformSegmentedTabs.test.tsx src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx`、`npm run test -- src/components/common/PlatformModalCloseButton.test.tsx src/components/PixelCloseButton.test.tsx src/components/CharacterChatModal.test.tsx src/components/MapModal.test.tsx`、`npm run test -- src/components/common/useMudPointConfirmController.test.tsx src/components/match3d-result/Match3DResultView.test.tsx src/components/unified-creation/workspaces/PuzzleCreationWorkspace.interaction.test.tsx src/components/unified-creation/workspaces/Match3DCreationWorkspace.interaction.test.tsx src/components/rpg-entry/RpgEntryHomeView.recharge.test.tsx src/components/platform-entry/PlatformProfileRechargeModal.test.tsx src/components/CustomWorldEntityEditorModal.test.tsx src/components/rpg-creation-result/RpgCreationResultActionBar.test.tsx src/components/unified-creation/shared/PuzzleHistoryAssetPickerDialog.test.tsx src/components/puzzle-result/PuzzleResultView.test.tsx`、`npm run test -- src/components/common/CopyFeedbackButton.test.tsx src/components/common/PlatformActionButton.test.tsx src/components/AdventureEntityModal.test.tsx src/components/InventoryPanel.test.tsx src/components/rpg-creation-result/RpgCreationAssetDebugPanel.test.tsx src/components/visual-novel-result/VisualNovelResultView.test.tsx src/components/common/PlatformEmptyState.test.tsx src/components/rpg-creation-asset-studio/RpgCreationRoleAssetStudioModal.test.tsx src/components/auth/AccountModal.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.npcChat.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.questOffer.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。
|
||||||
|
|||||||
@@ -259,6 +259,7 @@
|
|||||||
19.3.33. `PlatformAsyncStatePanel` 从 profile modal 扩展到作品架:`CustomWorldCreationHub.tsx` 的作品架主体现在也统一通过 `loadingState / emptyState / children` 三个 slot 切换,保留外层 error + 重试提示不并入共享状态骨架。后续白底作品架或列表 panel 若只是互斥的 `loading / empty / content`,优先直接复用 `PlatformAsyncStatePanel`,不要再在业务 JSX 中重复拼 skeleton 和“当前筛选下没有内容”的分支。验证命令:`npx vitest run src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx`、`npm run check:encoding`。
|
19.3.33. `PlatformAsyncStatePanel` 从 profile modal 扩展到作品架:`CustomWorldCreationHub.tsx` 的作品架主体现在也统一通过 `loadingState / emptyState / children` 三个 slot 切换,保留外层 error + 重试提示不并入共享状态骨架。后续白底作品架或列表 panel 若只是互斥的 `loading / empty / content`,优先直接复用 `PlatformAsyncStatePanel`,不要再在业务 JSX 中重复拼 skeleton 和“当前筛选下没有内容”的分支。验证命令:`npx vitest run src/components/custom-world-home/CustomWorldCreationHub.test.tsx src/components/custom-world-home/CustomWorldCreationHub.interaction.test.tsx`、`npm run check:encoding`。
|
||||||
19.3.34. `CopyFeedbackButton.tsx` 的 `actionSurface` 分支继续向共享按钮收口:带平台动作外观的复制按钮现在直接组合 `PlatformActionButton`,仅保留 `pill` 分支继续复用 `PlatformPillBadge` 风格。复制反馈按钮不再手动调用 `getPlatformActionButtonClassName` 拼平台按钮基础 chrome;后续同类“复制状态机 + 平台动作按钮”组合也优先走 `CopyFeedbackButton + PlatformActionButton`,不要在业务页或按钮组件里重新混写图标、文案、aria 和 class。验证命令:`npm run test -- src/components/common/CopyFeedbackButton.test.tsx src/components/common/PlatformActionButton.test.tsx`。
|
19.3.34. `CopyFeedbackButton.tsx` 的 `actionSurface` 分支继续向共享按钮收口:带平台动作外观的复制按钮现在直接组合 `PlatformActionButton`,仅保留 `pill` 分支继续复用 `PlatformPillBadge` 风格。复制反馈按钮不再手动调用 `getPlatformActionButtonClassName` 拼平台按钮基础 chrome;后续同类“复制状态机 + 平台动作按钮”组合也优先走 `CopyFeedbackButton + PlatformActionButton`,不要在业务页或按钮组件里重新混写图标、文案、aria 和 class。验证命令:`npm run test -- src/components/common/CopyFeedbackButton.test.tsx src/components/common/PlatformActionButton.test.tsx`。
|
||||||
19.3.35. 详情页头部动作组合收口到 `src/components/common/PlatformDetailTopbar.tsx` 与 `src/components/common/PlatformDetailShareActions.tsx`;前者只承接“返回 / 标题 / 右侧动作槽位”的 topbar 骨架,并允许 `pill` / `icon` 两种返回按钮语义,后者只承接“前置 badge 区块 + 作品号复制 + 分享复制”这一组稳定动作,不吸收详情页自己的标题、摘要、作者、封面轮播或业务 CTA。`RpgEntryWorldDetailView.tsx` 已接入完整的 overlay 版动作组合,统一世界主题 badge、作者、发布时间、作品号和分享入口;`PlatformWorkDetailView.tsx` 已接入 icon topbar 与 solid 版作品号复制动作,并继续保留公开详情页自己的顶部 icon 分享入口和分享反馈提示。后续同类详情页若只是复用返回按钮骨架、标题居中布局或作品号 / 分享动作排列,优先直接组合这两个 Module,不要把整页 detail header 抽成巨型配置对象。验证命令:`npx vitest run src/components/common/PlatformDetailTopbar.test.tsx src/components/common/PlatformDetailShareActions.test.tsx src/components/rpg-entry/RpgEntryWorldDetailView.test.tsx src/components/platform-entry/PlatformWorkDetailView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check -- src/components/common/PlatformDetailTopbar.tsx src/components/common/PlatformDetailTopbar.test.tsx src/components/common/PlatformDetailShareActions.tsx src/components/common/PlatformDetailShareActions.test.tsx src/components/rpg-entry/RpgEntryWorldDetailView.tsx src/components/platform-entry/PlatformWorkDetailView.tsx`。
|
19.3.35. 详情页头部动作组合收口到 `src/components/common/PlatformDetailTopbar.tsx` 与 `src/components/common/PlatformDetailShareActions.tsx`;前者只承接“返回 / 标题 / 右侧动作槽位”的 topbar 骨架,并允许 `pill` / `icon` 两种返回按钮语义,后者只承接“前置 badge 区块 + 作品号复制 + 分享复制”这一组稳定动作,不吸收详情页自己的标题、摘要、作者、封面轮播或业务 CTA。`RpgEntryWorldDetailView.tsx` 已接入完整的 overlay 版动作组合,统一世界主题 badge、作者、发布时间、作品号和分享入口;`PlatformWorkDetailView.tsx` 已接入 icon topbar 与 solid 版作品号复制动作,并继续保留公开详情页自己的顶部 icon 分享入口和分享反馈提示。后续同类详情页若只是复用返回按钮骨架、标题居中布局或作品号 / 分享动作排列,优先直接组合这两个 Module,不要把整页 detail header 抽成巨型配置对象。验证命令:`npx vitest run src/components/common/PlatformDetailTopbar.test.tsx src/components/common/PlatformDetailShareActions.test.tsx src/components/rpg-entry/RpgEntryWorldDetailView.test.tsx src/components/platform-entry/PlatformWorkDetailView.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check -- src/components/common/PlatformDetailTopbar.tsx src/components/common/PlatformDetailTopbar.test.tsx src/components/common/PlatformDetailShareActions.tsx src/components/common/PlatformDetailShareActions.test.tsx src/components/rpg-entry/RpgEntryWorldDetailView.tsx src/components/platform-entry/PlatformWorkDetailView.tsx`。
|
||||||
|
19.3.36. `PlatformToolModalShell` 继续承接 RPG 结果页发布检查弹窗;`RpgCreationResultActionBar.tsx` 只保留发布检查、封面预览、封面设置和发布动作语义,不再直接维护 `createPortal`、平台主题 overlay、白底 remap panel、header close、body/footer spacing 和遮罩关闭逻辑。后续结果页 / 工具页里同形态的白底 portal 弹窗优先迁移到 `PlatformToolModalShell`;编辑器大壳、暗色 runtime overlay 和需要专属布局的面板继续保留局部 shell。
|
||||||
19.3.35. 白底 / 暗色面板里的轻量空态和普通 CTA 继续按共享组件收口:`PuzzleResultView.tsx` 的“还没有可编辑的拼图草稿”、`RpgCreationAssetDebugPanel.tsx` 的“没有可诊断项”、`VisualNovelEntityGrid` 的空实体列表、`AccountModal.tsx` 里账号安全分区的“无安全限制 / 无登录设备 / 无操作记录”以及 `LoginScreen.tsx` 的“当前登录入口暂不可用”都改为 `PlatformEmptyState`;`Match3DResultView.tsx` 的引用素材列表直接交给 `PlatformAssetPickerGrid` 自己处理空态。`AdventureEntityModal.tsx` 的私聊按钮、`InventoryPanel.tsx` 的锻造 / 合成按钮、`RpgAdventurePanel.tsx` 底部 `队伍 / 背包 / 换一换 / 退出聊天` 按钮,以及 `RpgAdventurePanelOverlays.tsx` 里的“查看任务 / 保存并退出”都改为 `PlatformActionButton surface="editorDark"`,业务页只贴回局部 sky / emerald / runtime 皮肤。后续白底子面板里的只读空态优先使用 `PlatformEmptyState surface="subpanel"`;暗色编辑 / 运行面板里的普通动作优先使用 `PlatformActionButton surface="editorDark"`,若还需要 stopPropagation、局部字号或图标排版,可保留薄包装层,但不要再回退到原生 `<button>` 基础 chrome。验证命令:`npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx src/components/rpg-creation-result/RpgCreationAssetDebugPanel.test.tsx src/components/AdventureEntityModal.test.tsx src/components/InventoryPanel.test.tsx src/components/auth/AccountModal.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.npcChat.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.questOffer.test.tsx src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformActionButton.test.tsx`、`npm run check:encoding`。
|
19.3.35. 白底 / 暗色面板里的轻量空态和普通 CTA 继续按共享组件收口:`PuzzleResultView.tsx` 的“还没有可编辑的拼图草稿”、`RpgCreationAssetDebugPanel.tsx` 的“没有可诊断项”、`VisualNovelEntityGrid` 的空实体列表、`AccountModal.tsx` 里账号安全分区的“无安全限制 / 无登录设备 / 无操作记录”以及 `LoginScreen.tsx` 的“当前登录入口暂不可用”都改为 `PlatformEmptyState`;`Match3DResultView.tsx` 的引用素材列表直接交给 `PlatformAssetPickerGrid` 自己处理空态。`AdventureEntityModal.tsx` 的私聊按钮、`InventoryPanel.tsx` 的锻造 / 合成按钮、`RpgAdventurePanel.tsx` 底部 `队伍 / 背包 / 换一换 / 退出聊天` 按钮,以及 `RpgAdventurePanelOverlays.tsx` 里的“查看任务 / 保存并退出”都改为 `PlatformActionButton surface="editorDark"`,业务页只贴回局部 sky / emerald / runtime 皮肤。后续白底子面板里的只读空态优先使用 `PlatformEmptyState surface="subpanel"`;暗色编辑 / 运行面板里的普通动作优先使用 `PlatformActionButton surface="editorDark"`,若还需要 stopPropagation、局部字号或图标排版,可保留薄包装层,但不要再回退到原生 `<button>` 基础 chrome。验证命令:`npm run test -- src/components/puzzle-result/PuzzleResultView.test.tsx src/components/rpg-creation-result/RpgCreationAssetDebugPanel.test.tsx src/components/AdventureEntityModal.test.tsx src/components/InventoryPanel.test.tsx src/components/auth/AccountModal.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.npcChat.test.tsx src/components/rpg-runtime-panels/RpgAdventurePanel.questOffer.test.tsx src/components/common/PlatformEmptyState.test.tsx src/components/common/PlatformActionButton.test.tsx`、`npm run check:encoding`。
|
||||||
19.3.36. `VisualNovelEntityGrid` 的空态也继续收口到 `PlatformEmptyState surface="subpanel" size="inline"`;角色 / 场景 / 剧情阶段共用这一网格组件后,白底实体列表里的“暂无角色 / 暂无场景 / 暂无剧情阶段”等同构空态不再回退成 `PlatformSubpanel`。同时,`RpgCreationRoleAssetStudioModalImpl.tsx` 与 `RpgCreationEntityEditorShared.tsx` 保留局部 `ActionButton` 语义壳,但按钮本体已统一委托给 `PlatformActionButton surface="editorDark"`,只在包装层补最小的 `stopPropagation`、tone 映射和局部 class 适配。后续类似“暗色编辑器局部包装按钮”优先沿用这种薄包装模式,不再直接手写原生 `<button>` 基础 chrome。验证命令:`npm run test -- src/components/visual-novel-result/VisualNovelResultView.test.tsx src/components/common/PlatformEmptyState.test.tsx src/components/rpg-creation-asset-studio/RpgCreationRoleAssetStudioModal.test.tsx src/components/CustomWorldEntityEditorModal.test.tsx src/components/common/PlatformActionButton.test.tsx`、`npm run check:encoding`。
|
19.3.36. `VisualNovelEntityGrid` 的空态也继续收口到 `PlatformEmptyState surface="subpanel" size="inline"`;角色 / 场景 / 剧情阶段共用这一网格组件后,白底实体列表里的“暂无角色 / 暂无场景 / 暂无剧情阶段”等同构空态不再回退成 `PlatformSubpanel`。同时,`RpgCreationRoleAssetStudioModalImpl.tsx` 与 `RpgCreationEntityEditorShared.tsx` 保留局部 `ActionButton` 语义壳,但按钮本体已统一委托给 `PlatformActionButton surface="editorDark"`,只在包装层补最小的 `stopPropagation`、tone 映射和局部 class 适配。后续类似“暗色编辑器局部包装按钮”优先沿用这种薄包装模式,不再直接手写原生 `<button>` 基础 chrome。验证命令:`npm run test -- src/components/visual-novel-result/VisualNovelResultView.test.tsx src/components/common/PlatformEmptyState.test.tsx src/components/rpg-creation-asset-studio/RpgCreationRoleAssetStudioModal.test.tsx src/components/CustomWorldEntityEditorModal.test.tsx src/components/common/PlatformActionButton.test.tsx`、`npm run check:encoding`。
|
||||||
19.3.37. 暗色编辑器里的局部动作按钮继续往共享 `editorDark` button 收口:`CustomWorldNpcVisualEditor.tsx` 的本地 `ActionButton` 和 `SkillEffectPreview.tsx` 的“重新预览”按钮都改为委托 `PlatformActionButton surface="editorDark"`。这类局部包装仍可保留 `stopPropagation`、图标布局、`tone` 映射和少量局部视觉覆写,但按钮本体不再直接使用原生 `<button>` 承接边框 / 底色 / hover / disabled chrome。验证命令:`npm run test -- src/components/common/PlatformActionButton.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。
|
19.3.37. 暗色编辑器里的局部动作按钮继续往共享 `editorDark` button 收口:`CustomWorldNpcVisualEditor.tsx` 的本地 `ActionButton` 和 `SkillEffectPreview.tsx` 的“重新预览”按钮都改为委托 `PlatformActionButton surface="editorDark"`。这类局部包装仍可保留 `stopPropagation`、图标布局、`tone` 映射和少量局部视觉覆写,但按钮本体不再直接使用原生 `<button>` 承接边框 / 底色 / hover / disabled chrome。验证命令:`npm run test -- src/components/common/PlatformActionButton.test.tsx`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ test('RPG result publish dialog uses PlatformPillBadge and PlatformSubpanel for
|
|||||||
const coverBadge = within(dialog).getByText('上传封面');
|
const coverBadge = within(dialog).getByText('上传封面');
|
||||||
const coverShell = within(dialog).getByLabelText('封面预览外壳');
|
const coverShell = within(dialog).getByLabelText('封面预览外壳');
|
||||||
|
|
||||||
|
expect(dialog.className).toContain('platform-remap-surface');
|
||||||
|
expect(dialog.className).toContain('shadow-[0_24px_80px_rgba(0,0,0,0.55)]');
|
||||||
expect(coverBadge.className).toContain('rounded-full');
|
expect(coverBadge.className).toContain('rounded-full');
|
||||||
expect(coverBadge.className).toContain('bg-white/72');
|
expect(coverBadge.className).toContain('bg-white/72');
|
||||||
expect(coverShell.className).toContain('platform-subpanel');
|
expect(coverShell.className).toContain('platform-subpanel');
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
import { type ReactNode, useState } from 'react';
|
import { type ReactNode, useState } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
|
||||||
|
|
||||||
import { resolveCustomWorldCoverPresentation } from '../../services/customWorldCover';
|
import { resolveCustomWorldCoverPresentation } from '../../services/customWorldCover';
|
||||||
import type { CustomWorldProfile } from '../../types';
|
import type { CustomWorldProfile } from '../../types';
|
||||||
import { useAuthUi } from '../auth/AuthUiContext';
|
|
||||||
import { PlatformActionButton } from '../common/PlatformActionButton';
|
import { PlatformActionButton } from '../common/PlatformActionButton';
|
||||||
import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
|
import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
|
||||||
import { PlatformModalCloseButton } from '../common/PlatformModalCloseButton';
|
|
||||||
import { PlatformPillBadge } from '../common/PlatformPillBadge';
|
import { PlatformPillBadge } from '../common/PlatformPillBadge';
|
||||||
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
|
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
|
||||||
import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
import { PlatformSubpanel } from '../common/PlatformSubpanel';
|
||||||
|
import { PlatformToolModalShell } from '../common/PlatformToolModalShell';
|
||||||
import { CustomWorldCoverArtwork } from '../CustomWorldCoverArtwork';
|
import { CustomWorldCoverArtwork } from '../CustomWorldCoverArtwork';
|
||||||
|
|
||||||
function SmallButton({
|
function SmallButton({
|
||||||
@@ -54,112 +52,21 @@ function PublishPanelDialog({
|
|||||||
onEditCover: () => void;
|
onEditCover: () => void;
|
||||||
onPublish: () => void;
|
onPublish: () => void;
|
||||||
}) {
|
}) {
|
||||||
const platformTheme = useAuthUi()?.platformTheme ?? 'light';
|
|
||||||
const coverPresentation = resolveCustomWorldCoverPresentation(profile);
|
const coverPresentation = resolveCustomWorldCoverPresentation(profile);
|
||||||
|
|
||||||
if (typeof document === 'undefined') {
|
return (
|
||||||
return null;
|
<PlatformToolModalShell
|
||||||
}
|
open
|
||||||
|
title="发布作品"
|
||||||
return createPortal(
|
description="发布前检查与封面设置"
|
||||||
<div
|
onClose={onClose}
|
||||||
className={`platform-theme platform-theme--${platformTheme} platform-overlay fixed inset-0 z-[140] flex items-end justify-center p-3 backdrop-blur-sm sm:items-center sm:p-4`}
|
closeLabel="关闭发布作品"
|
||||||
onClick={(event) => {
|
zIndexClassName="z-[140]"
|
||||||
if (event.target === event.currentTarget) {
|
size="xl"
|
||||||
onClose();
|
panelClassName="!max-h-[min(90vh,46rem)] !max-w-4xl"
|
||||||
}
|
footerClassName="flex-col-reverse sm:flex-row sm:justify-end"
|
||||||
}}
|
footer={
|
||||||
>
|
<>
|
||||||
<div
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
aria-label="发布作品"
|
|
||||||
className="platform-modal-shell platform-remap-surface flex max-h-[min(90vh,46rem)] w-full max-w-4xl flex-col overflow-hidden rounded-t-[1.75rem] shadow-[0_24px_80px_rgba(0,0,0,0.55)] sm:rounded-[1.75rem]"
|
|
||||||
onClick={(event) => event.stopPropagation()}
|
|
||||||
>
|
|
||||||
<div className="flex items-center justify-between gap-3 border-b border-[var(--platform-subpanel-border)] px-5 py-4">
|
|
||||||
<div>
|
|
||||||
<div className="text-base font-semibold text-[var(--platform-text-strong)]">
|
|
||||||
发布作品
|
|
||||||
</div>
|
|
||||||
<div className="mt-1 text-sm leading-6 text-[var(--platform-text-soft)]">
|
|
||||||
发布前检查与封面设置
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<PlatformModalCloseButton
|
|
||||||
variant="platformIcon"
|
|
||||||
label="关闭发布作品"
|
|
||||||
onClick={onClose}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="min-h-0 flex-1 overflow-y-auto px-5 py-4">
|
|
||||||
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(18rem,0.78fr)]">
|
|
||||||
<div className="space-y-3">
|
|
||||||
<PlatformFieldLabel variant="section">
|
|
||||||
发布检查
|
|
||||||
</PlatformFieldLabel>
|
|
||||||
{blockers.length > 0 ? (
|
|
||||||
<div className="space-y-2">
|
|
||||||
{blockers.map((blocker, index) => (
|
|
||||||
<PlatformStatusMessage
|
|
||||||
key={`publish-blocker-${index}-${blocker}`}
|
|
||||||
tone="warning"
|
|
||||||
surface="platform"
|
|
||||||
>
|
|
||||||
<div className="text-xs font-semibold tracking-[0.14em] text-[var(--platform-warm-text)] opacity-80">
|
|
||||||
阻断项 {index + 1}
|
|
||||||
</div>
|
|
||||||
<div className="mt-1 text-[var(--platform-text-strong)]">
|
|
||||||
{blocker}
|
|
||||||
</div>
|
|
||||||
</PlatformStatusMessage>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<PlatformStatusMessage tone="success" surface="platform">
|
|
||||||
当前作品已满足发布条件。
|
|
||||||
</PlatformStatusMessage>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-3">
|
|
||||||
<div className="flex items-center justify-between gap-3">
|
|
||||||
<PlatformFieldLabel variant="section">
|
|
||||||
封面设置
|
|
||||||
</PlatformFieldLabel>
|
|
||||||
<PlatformPillBadge
|
|
||||||
tone="neutral"
|
|
||||||
size="xs"
|
|
||||||
className="px-2.5 py-1 text-[10px]"
|
|
||||||
>
|
|
||||||
{coverPresentation.sourceType === 'uploaded'
|
|
||||||
? '上传封面'
|
|
||||||
: coverPresentation.sourceType === 'generated'
|
|
||||||
? 'AI封面'
|
|
||||||
: '默认封面'}
|
|
||||||
</PlatformPillBadge>
|
|
||||||
</div>
|
|
||||||
<PlatformSubpanel
|
|
||||||
padding="none"
|
|
||||||
aria-label="封面预览外壳"
|
|
||||||
className="p-2"
|
|
||||||
>
|
|
||||||
<CustomWorldCoverArtwork
|
|
||||||
imageSrc={coverPresentation.imageSrc}
|
|
||||||
title={profile.name}
|
|
||||||
fallbackLabel={profile.name.slice(0, 4) || '封面'}
|
|
||||||
renderMode={coverPresentation.renderMode}
|
|
||||||
characterImageSrcs={coverPresentation.characterImageSrcs}
|
|
||||||
className="aspect-[16/9] max-h-[15rem] rounded-[1rem]"
|
|
||||||
/>
|
|
||||||
</PlatformSubpanel>
|
|
||||||
<SmallButton onClick={onEditCover} tone="sky">
|
|
||||||
设置封面
|
|
||||||
</SmallButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col-reverse gap-3 border-t border-[var(--platform-subpanel-border)] px-5 py-4 sm:flex-row sm:justify-end">
|
|
||||||
<SmallButton onClick={onClose}>取消</SmallButton>
|
<SmallButton onClick={onClose}>取消</SmallButton>
|
||||||
<PlatformActionButton
|
<PlatformActionButton
|
||||||
onClick={onPublish}
|
onClick={onPublish}
|
||||||
@@ -167,10 +74,71 @@ function PublishPanelDialog({
|
|||||||
>
|
>
|
||||||
{isPublishing ? '发布中...' : '发布到广场'}
|
{isPublishing ? '发布中...' : '发布到广场'}
|
||||||
</PlatformActionButton>
|
</PlatformActionButton>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(18rem,0.78fr)]">
|
||||||
|
<div className="space-y-3">
|
||||||
|
<PlatformFieldLabel variant="section">发布检查</PlatformFieldLabel>
|
||||||
|
{blockers.length > 0 ? (
|
||||||
|
<div className="space-y-2">
|
||||||
|
{blockers.map((blocker, index) => (
|
||||||
|
<PlatformStatusMessage
|
||||||
|
key={`publish-blocker-${index}-${blocker}`}
|
||||||
|
tone="warning"
|
||||||
|
surface="platform"
|
||||||
|
>
|
||||||
|
<div className="text-xs font-semibold tracking-[0.14em] text-[var(--platform-warm-text)] opacity-80">
|
||||||
|
阻断项 {index + 1}
|
||||||
|
</div>
|
||||||
|
<div className="mt-1 text-[var(--platform-text-strong)]">
|
||||||
|
{blocker}
|
||||||
|
</div>
|
||||||
|
</PlatformStatusMessage>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<PlatformStatusMessage tone="success" surface="platform">
|
||||||
|
当前作品已满足发布条件。
|
||||||
|
</PlatformStatusMessage>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex items-center justify-between gap-3">
|
||||||
|
<PlatformFieldLabel variant="section">封面设置</PlatformFieldLabel>
|
||||||
|
<PlatformPillBadge
|
||||||
|
tone="neutral"
|
||||||
|
size="xs"
|
||||||
|
className="px-2.5 py-1 text-[10px]"
|
||||||
|
>
|
||||||
|
{coverPresentation.sourceType === 'uploaded'
|
||||||
|
? '上传封面'
|
||||||
|
: coverPresentation.sourceType === 'generated'
|
||||||
|
? 'AI封面'
|
||||||
|
: '默认封面'}
|
||||||
|
</PlatformPillBadge>
|
||||||
|
</div>
|
||||||
|
<PlatformSubpanel
|
||||||
|
padding="none"
|
||||||
|
aria-label="封面预览外壳"
|
||||||
|
className="p-2"
|
||||||
|
>
|
||||||
|
<CustomWorldCoverArtwork
|
||||||
|
imageSrc={coverPresentation.imageSrc}
|
||||||
|
title={profile.name}
|
||||||
|
fallbackLabel={profile.name.slice(0, 4) || '封面'}
|
||||||
|
renderMode={coverPresentation.renderMode}
|
||||||
|
characterImageSrcs={coverPresentation.characterImageSrcs}
|
||||||
|
className="aspect-[16/9] max-h-[15rem] rounded-[1rem]"
|
||||||
|
/>
|
||||||
|
</PlatformSubpanel>
|
||||||
|
<SmallButton onClick={onEditCover} tone="sky">
|
||||||
|
设置封面
|
||||||
|
</SmallButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</PlatformToolModalShell>
|
||||||
document.body,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user