diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 198792e..8301a1d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -21,6 +21,15 @@ import { loadConfig, loadTheme, saveTheme } from "./lib/storage"; import { I18nContext, parseLocale, t } from "./lib/i18n"; import { renderScenarioIconById } from "./lib/scenarioIcons"; import type { Locale } from "./lib/i18n"; + +/** SVG 图标 ID → emoji 映射(用于纯文本场景,如系统消息) */ +const ICON_ID_TO_EMOJI: Record = { + sparkles: "✨", theater: "🎭", palette: "🎨", target: "🎯", film: "🎬", + "book-open": "📖", book: "📚", edit: "✏️", clipboard: "📋", "map-pin": "📍", + search: "🔍", lightbulb: "💡", briefcase: "💼", code: "💻", "graduation-cap": "🎓", + mic: "🎤", music: "🎵", globe: "🌐", heart: "❤️", shield: "🛡️", + zap: "⚡", coffee: "☕", tool: "🔧", "message-circle": "💬", +}; import type { Theme } from "./types"; import type { UserScenario } from "./lib/api/scenarios"; import "./App.css"; @@ -228,10 +237,14 @@ function AppContent() { } } updateConfig(updates); - // 插入系统提示消息 - const scenarioName = sc - ? `${sc.icon} ${sc.nameKey ? tr(sc.nameKey) : sc.name}` + // 插入系统提示消息(自建情景的 icon 是 SVG ID,需转为 emoji) + const iconText = sc + ? (ICON_ID_TO_EMOJI[sc.icon] || sc.icon) + : ""; + const displayName = sc + ? (sc.nameKey ? tr(sc.nameKey) : sc.name) : scenarioId; + const scenarioName = iconText ? `${iconText} ${displayName}` : displayName; setMessages(prev => [...prev, { id: uuidv4(), role: "system", @@ -607,6 +620,7 @@ function AppContent() { currentReply={currentReply} connectionStatus={connectionStatus} currentScenario={config.scenario} + allScenarios={allScenarios} isProcessing={isProcessing} isVADReady={isVADReady} vadError={vadError ?? undefined} diff --git a/frontend/src/components/ChatPanel/index.tsx b/frontend/src/components/ChatPanel/index.tsx index 741b825..1fa1f26 100644 --- a/frontend/src/components/ChatPanel/index.tsx +++ b/frontend/src/components/ChatPanel/index.tsx @@ -7,6 +7,7 @@ import { useEffect, useRef, useState, type ReactNode } from "react"; import { useI18n } from "../../lib/i18n"; import { scenarios } from "../../lib/scenarios"; +import type { ExtendedScenario } from "../../hooks/useScenarios"; import type { ChatMessage } from "../../types"; import type { ConnectionStatus } from "../../lib/websocket"; @@ -15,6 +16,7 @@ interface ChatPanelProps { currentReply?: string; connectionStatus: ConnectionStatus; currentScenario?: string; + allScenarios?: ExtendedScenario[]; isProcessing?: boolean; isVADReady?: boolean; vadError?: string | null; @@ -43,6 +45,7 @@ export function ChatPanel({ currentReply, connectionStatus, currentScenario, + allScenarios, isProcessing, isVADReady, vadError, @@ -103,6 +106,10 @@ export function ChatPanel({ } }; + // 当前情景对象(优先从 allScenarios 查找,含自建情景;兜底用系统情景) + const scenarioList = allScenarios || scenarios; + const activeScenarioObj = scenarioList.find(sc => sc.id === activeScenario); + return (
@@ -111,11 +118,13 @@ export function ChatPanel({
- {scenarios.find(s => s.id === activeScenario)?.icon} + {activeScenarioObj?.icon}
- {t(scenarios.find(s => s.id === activeScenario)?.nameKey || "")} -

{t(`scenario.${activeScenario}.hint`)}

+ {activeScenarioObj ? (activeScenarioObj.nameKey ? t(activeScenarioObj.nameKey) : activeScenarioObj.name) : ""} + {activeScenarioObj && (activeScenarioObj.descKey || activeScenarioObj.description) && ( +

{activeScenarioObj.descKey ? t(activeScenarioObj.descKey) : activeScenarioObj.description}

+ )}
@@ -124,7 +133,7 @@ export function ChatPanel({ {/* 空状态:欢迎信息 */} {isEmpty && (
- {scenarios.find(s => s.id === activeScenario)?.icon || } + {activeScenarioObj?.icon || }

{isConnected ? t("chat.welcome.prompt") : t("chat.empty.prompt")}

{isConnected ? t("chat.welcome.hint") : t("chat.empty.hint")}