diff --git a/src/api/client.ts b/src/api/client.ts index 9c0f672..70ad5ec 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -2147,3 +2147,20 @@ export function subscribeSessionEvents( } }; } + +// ── Design Skill API ───────────────────────────────────────────────────────── + +export async function listDesignStyles(): Promise { + const result = await portalFetch<{ designs: string[] }>('/admin-api/skills/designs'); + return result.designs ?? []; +} + +export async function invokeDesignSkill( + design: string, + task: string, +): Promise<{ invocation_id: number; output: string }> { + return portalFetch('/admin-api/skills/awesome-design-md/invoke', { + method: 'POST', + body: JSON.stringify({ design, task }), + }); +} diff --git a/src/components/ChatPanel.tsx b/src/components/ChatPanel.tsx index b77fbd8..25fa6c6 100644 --- a/src/components/ChatPanel.tsx +++ b/src/components/ChatPanel.tsx @@ -4,6 +4,7 @@ import { openAvatarPicker } from '../utils/userAvatar'; import { CHAT_SKILL_OPTIONS, filterChatSkills } from '../utils/chatSkills'; import { AvatarPicker } from './AvatarPicker'; import { ChatSkillPicker } from './ChatSkillPicker'; +import { DesignSkillPanel } from './DesignSkillPanel'; import { MessageList } from './MessageList'; import { PageSaveDialog } from './PageSaveDialog'; import { VoiceInputButton } from './VoiceInputButton'; @@ -67,6 +68,7 @@ export function ChatPanel({ }) { const online = useNetworkStatus(); const [input, setInput] = useState(''); + const [designPanelOpen, setDesignPanelOpen] = useState(false); const [voiceRecording, setVoiceRecording] = useState(false); const [pageSource, setPageSource] = useState(null); const [voiceNotice, setVoiceNotice] = useState(null); @@ -455,6 +457,25 @@ export function ChatPanel({ onPrefill={setInput} /> )} + + {designPanelOpen && ( + setDesignPanelOpen(false)} + onResult={(md) => { + setInput(md); + setDesignPanelOpen(false); + }} + /> + )} {chatState === 'streaming' ? ( + + +
+

选择设计风格

+ {fetching ? ( +
加载中…
+ ) : ( +
+ {designs.map((d) => ( + + ))} +
+ )} + + {selected && ( + <> +

+ 描述 UI 任务 + — {formatBrandLabel(selected)} 风格 +

+