feat: 新增会话历史侧边栏,支持新建/切换/删除/重命名会话
类似 ChatGPT 的侧边栏布局,消息历史持久化到 localStorage。 - 新增 SessionSummary 类型和 localStorage 读写函数 - 新增 useSessionList Hook 管理会话列表 CRUD - 新增 SessionSidebar 组件(展开/折叠、行内重命名) - App.tsx 协调 useSessionList 和 useVisionSession - 消息变化时自动持久化,切换/新建会话时保存并加载 - 新增 i18n 翻译 key(中/英/日)
This commit is contained in:
@@ -81,6 +81,15 @@ export const enUS: TranslationMap = {
|
||||
"error.INTERNAL_ERROR": "Internal server error, please retry",
|
||||
"error.unknown": "Unknown error",
|
||||
|
||||
// Sidebar
|
||||
"sidebar.new": "New Chat",
|
||||
"sidebar.expand": "Expand sidebar",
|
||||
"sidebar.collapse": "Collapse sidebar",
|
||||
"sidebar.empty": "No chat history",
|
||||
"sidebar.messages": " messages",
|
||||
"sidebar.rename": "Rename",
|
||||
"sidebar.delete": "Delete",
|
||||
|
||||
// Device errors
|
||||
"error.vadInit": "VAD initialization failed",
|
||||
"error.cameraAccess": "Cannot access camera",
|
||||
|
||||
@@ -81,6 +81,15 @@ export const jaJP: TranslationMap = {
|
||||
"error.INTERNAL_ERROR": "サーバー内部エラー。再試行してください",
|
||||
"error.unknown": "不明なエラー",
|
||||
|
||||
// Sidebar
|
||||
"sidebar.new": "新しいチャット",
|
||||
"sidebar.expand": "サイドバーを展開",
|
||||
"sidebar.collapse": "サイドバーを折りたたむ",
|
||||
"sidebar.empty": "会話履歴がありません",
|
||||
"sidebar.messages": "件のメッセージ",
|
||||
"sidebar.rename": "名前を変更",
|
||||
"sidebar.delete": "削除",
|
||||
|
||||
// Device errors
|
||||
"error.vadInit": "VAD初期化に失敗しました",
|
||||
"error.cameraAccess": "カメラにアクセスできません",
|
||||
|
||||
@@ -81,6 +81,15 @@ export const zhCN: TranslationMap = {
|
||||
"error.INTERNAL_ERROR": "服务内部错误,请重试",
|
||||
"error.unknown": "未知错误",
|
||||
|
||||
// Sidebar
|
||||
"sidebar.new": "新对话",
|
||||
"sidebar.expand": "展开侧边栏",
|
||||
"sidebar.collapse": "收起侧边栏",
|
||||
"sidebar.empty": "暂无会话记录",
|
||||
"sidebar.messages": "条消息",
|
||||
"sidebar.rename": "重命名",
|
||||
"sidebar.delete": "删除",
|
||||
|
||||
// Device errors
|
||||
"error.vadInit": "VAD 初始化失败",
|
||||
"error.cameraAccess": "无法访问摄像头",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// 职责:会话配置持久化
|
||||
// ============================================================
|
||||
|
||||
import type { SessionConfig, Theme } from "../types";
|
||||
import type { ChatMessage, SessionConfig, SessionSummary, Theme } from "../types";
|
||||
|
||||
const CONFIG_KEY = "camtalk:config";
|
||||
const THEME_KEY = "camtalk:theme";
|
||||
@@ -52,3 +52,51 @@ export function saveTheme(theme: Theme): void {
|
||||
localStorage.setItem(THEME_KEY, theme);
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
// ---- 会话历史存储 ----
|
||||
|
||||
const SESSIONS_KEY = "camtalk:sessions";
|
||||
const SESSION_MSG_PREFIX = "camtalk:session:";
|
||||
|
||||
/** 加载所有会话摘要(按 lastActiveAt 倒序) */
|
||||
export function loadSessionSummaries(): SessionSummary[] {
|
||||
try {
|
||||
const raw = localStorage.getItem(SESSIONS_KEY);
|
||||
if (!raw) return [];
|
||||
return (JSON.parse(raw) as SessionSummary[]).sort((a, b) => b.lastActiveAt - a.lastActiveAt);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** 保存会话摘要列表 */
|
||||
export function saveSessionSummaries(sessions: SessionSummary[]): void {
|
||||
try {
|
||||
localStorage.setItem(SESSIONS_KEY, JSON.stringify(sessions));
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
/** 加载单个会话的消息历史 */
|
||||
export function loadSessionMessages(sessionId: string): ChatMessage[] {
|
||||
try {
|
||||
const raw = localStorage.getItem(SESSION_MSG_PREFIX + sessionId);
|
||||
if (!raw) return [];
|
||||
return JSON.parse(raw) as ChatMessage[];
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** 保存单个会话的消息历史 */
|
||||
export function saveSessionMessages(sessionId: string, messages: ChatMessage[]): void {
|
||||
try {
|
||||
localStorage.setItem(SESSION_MSG_PREFIX + sessionId, JSON.stringify(messages));
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
/** 删除单个会话的消息历史 */
|
||||
export function deleteSessionMessages(sessionId: string): void {
|
||||
try {
|
||||
localStorage.removeItem(SESSION_MSG_PREFIX + sessionId);
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user