收口前端平台组件库能力

新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件
迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome
补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
This commit is contained in:
2026-06-10 10:24:18 +08:00
parent a4ee6ff698
commit 1ad25e30f8
226 changed files with 23364 additions and 7825 deletions

View File

@@ -3,6 +3,12 @@ import { useEffect, useRef } from 'react';
import type { CharacterChatModalState } from '../hooks/rpg-runtime-story';
import { getNineSliceStyle, UI_CHROME } from '../uiAssets';
import { PlatformActionButton } from './common/PlatformActionButton';
import { PlatformDarkOptionCard } from './common/PlatformDarkOptionCard';
import { PlatformEmptyState } from './common/PlatformEmptyState';
import { PlatformStatusMessage } from './common/PlatformStatusMessage';
import { PlatformSubpanel } from './common/PlatformSubpanel';
import { PlatformTextField } from './common/PlatformTextField';
import { PixelCloseButton } from './PixelCloseButton';
interface CharacterChatModalProps {
@@ -68,23 +74,45 @@ export function CharacterChatModal({
<div className="pixel-nine-slice pixel-panel" style={getNineSliceStyle(UI_CHROME.panel)}>
<div className="mb-2 text-xs font-bold text-white"></div>
<div className="space-y-2 text-sm text-zinc-300">
<div className="rounded-xl border border-white/8 bg-black/18 px-3 py-2">
<PlatformSubpanel
as="div"
surface="dark"
radius="xs"
padding="row"
>
{modal.target.hp} / {modal.target.maxHp}
</div>
<div className="rounded-xl border border-white/8 bg-black/18 px-3 py-2">
</PlatformSubpanel>
<PlatformSubpanel
as="div"
surface="dark"
radius="xs"
padding="row"
>
{modal.target.mana} / {modal.target.maxMana}
</div>
<div className="rounded-xl border border-white/8 bg-black/18 px-3 py-2 text-xs leading-relaxed text-zinc-400">
</PlatformSubpanel>
<PlatformSubpanel
as="div"
surface="dark"
radius="xs"
padding="row"
className="text-xs leading-relaxed text-zinc-400"
>
{modal.target.character.personality}
</div>
</PlatformSubpanel>
</div>
</div>
<div className="pixel-nine-slice pixel-panel" style={getNineSliceStyle(UI_CHROME.panel)}>
<div className="mb-2 text-xs font-bold text-white"></div>
<div className="rounded-xl border border-white/8 bg-black/18 px-3 py-3 text-sm leading-relaxed text-zinc-300">
<PlatformSubpanel
as="div"
surface="dark"
radius="xs"
padding="md"
className="text-sm leading-relaxed text-zinc-300"
>
{modal.summary || '你们还没有形成新的私下聊天总结。'}
</div>
</PlatformSubpanel>
</div>
</div>
@@ -115,51 +143,57 @@ export function CharacterChatModal({
</div>
))
) : (
<div className="rounded-2xl border border-dashed border-white/10 bg-black/18 px-4 py-6 text-sm leading-relaxed text-zinc-500">
<PlatformEmptyState
surface="editorDark"
size="inline"
className="py-6 font-normal leading-relaxed text-zinc-500"
>
</div>
</PlatformEmptyState>
)}
</div>
<div className="mt-4 space-y-3">
<div className="flex items-center justify-between gap-3">
<div className="text-xs font-bold text-white"></div>
<button
type="button"
<PlatformActionButton
surface="editorDark"
tone="ghost"
size="xxs"
shape="pill"
onClick={onRefreshSuggestions}
disabled={modal.isLoadingSuggestions || modal.isSending}
className={`rounded-full border px-3 py-1 text-[10px] transition-colors ${
modal.isLoadingSuggestions || modal.isSending
? 'border-white/8 bg-black/20 text-zinc-600'
: 'border-white/10 bg-black/20 text-zinc-200 hover:text-white'
}`}
>
{modal.isLoadingSuggestions ? '生成中...' : '换一组'}
</button>
</PlatformActionButton>
</div>
<div className="grid gap-2 sm:grid-cols-3">
{modal.suggestions.map((suggestion, index) => (
<button
<PlatformDarkOptionCard
key={`${suggestion}-${index}`}
type="button"
onClick={() => onUseSuggestion(suggestion)}
disabled={modal.isSending}
className={`rounded-xl border px-3 py-2 text-left text-xs leading-relaxed transition ${
modal.isSending
? 'border-white/8 bg-black/20 text-zinc-600'
: 'border-white/8 bg-black/20 text-zinc-200 hover:border-sky-300/30 hover:bg-sky-500/10 hover:text-white'
}`}
selected={false}
tone="sky"
radius="md"
padding="sm"
className="text-xs leading-relaxed"
>
{suggestion}
</button>
</PlatformDarkOptionCard>
))}
</div>
{modal.error && (
<div className="rounded-xl border border-amber-400/20 bg-amber-500/10 px-3 py-2 text-xs leading-relaxed text-amber-100">
<PlatformStatusMessage
tone="warning"
surface="editorDark"
size="xs"
className="leading-relaxed"
>
{modal.error}
</div>
</PlatformStatusMessage>
)}
<form
@@ -169,13 +203,18 @@ export function CharacterChatModal({
onSendDraft();
}}
>
<textarea
<PlatformTextField
variant="textarea"
value={modal.draft}
onChange={event => onDraftChange(event.target.value)}
placeholder={`${modal.target.character.name}说点什么...`}
disabled={modal.isSending}
rows={4}
className="w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-3 text-sm leading-relaxed text-zinc-100 outline-none transition focus:border-sky-300/35"
surface="editorDark"
tone="sky"
size="md"
density="roomy"
className="rounded-2xl bg-black/25 leading-relaxed text-zinc-100 focus:border-sky-300/35"
/>
<div className="flex justify-end">
<button