feat: 新增会话历史侧边栏,支持新建/切换/删除/重命名会话

类似 ChatGPT 的侧边栏布局,消息历史持久化到 localStorage。

- 新增 SessionSummary 类型和 localStorage 读写函数
- 新增 useSessionList Hook 管理会话列表 CRUD
- 新增 SessionSidebar 组件(展开/折叠、行内重命名)
- App.tsx 协调 useSessionList 和 useVisionSession
- 消息变化时自动持久化,切换/新建会话时保存并加载
- 新增 i18n 翻译 key(中/英/日)
This commit is contained in:
2026-06-14 15:44:25 +08:00
parent da8818c3be
commit 92f3f45c41
10 changed files with 635 additions and 5 deletions

View File

@@ -208,6 +208,193 @@ body {
overflow: hidden;
}
/* ---- 会话历史侧边栏 ---- */
.sidebar {
width: 260px;
flex-shrink: 0;
display: flex;
flex-direction: column;
background: var(--color-surface-1);
border-right: 1px solid var(--color-border);
overflow: hidden;
}
.sidebar--collapsed {
width: 48px;
align-items: center;
padding: 8px 0;
gap: 8px;
}
.sidebar__header {
display: flex;
align-items: center;
gap: 6px;
padding: 12px;
border-bottom: 1px solid var(--color-border);
flex-shrink: 0;
}
.sidebar__toggle {
background: none;
border: none;
color: var(--color-text-muted);
cursor: pointer;
font-size: 1rem;
padding: 6px 8px;
border-radius: var(--radius-sm);
transition: background var(--transition-fast), color var(--transition-fast);
}
.sidebar__toggle:hover {
background: var(--color-surface-2);
color: var(--color-text);
}
.sidebar__new-btn {
background: none;
border: 1px solid var(--color-border);
color: var(--color-text);
cursor: pointer;
font-size: 0.82rem;
padding: 6px 10px;
border-radius: var(--radius-sm);
transition: background var(--transition-fast);
}
.sidebar__new-btn:hover {
background: var(--color-surface-2);
}
.sidebar__new-btn--full {
flex: 1;
text-align: left;
}
.sidebar__list {
flex: 1;
overflow-y: auto;
padding: 6px;
}
.sidebar__empty {
padding: 24px 12px;
text-align: center;
color: var(--color-text-muted);
font-size: 0.82rem;
}
.sidebar__item {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 12px;
border-radius: var(--radius-sm);
cursor: pointer;
transition: background var(--transition-fast);
position: relative;
}
.sidebar__item:hover {
background: var(--color-surface-2);
}
.sidebar__item:hover .sidebar__item-actions {
opacity: 1;
}
.sidebar__item--active {
background: var(--color-surface-2);
border-left: 3px solid var(--color-primary);
}
.sidebar__item-content {
flex: 1;
min-width: 0;
}
.sidebar__item-title {
font-size: 0.85rem;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--color-text);
}
.sidebar__item-meta {
font-size: 0.72rem;
color: var(--color-text-muted);
margin-top: 2px;
display: flex;
gap: 8px;
}
.sidebar__item-actions {
display: flex;
gap: 2px;
opacity: 0;
transition: opacity var(--transition-fast);
flex-shrink: 0;
}
.sidebar__action-btn {
background: none;
border: none;
cursor: pointer;
font-size: 0.75rem;
padding: 4px 6px;
border-radius: var(--radius-sm);
color: var(--color-text-muted);
transition: background var(--transition-fast), color var(--transition-fast);
}
.sidebar__action-btn:hover {
background: var(--color-surface-3);
color: var(--color-text);
}
.sidebar__action-btn--danger:hover {
color: #e74c3c;
}
.sidebar__edit {
display: flex;
gap: 4px;
width: 100%;
}
.sidebar__edit-input {
flex: 1;
font-size: 0.82rem;
padding: 4px 8px;
border: 1px solid var(--color-border);
border-radius: var(--radius-sm);
background: var(--color-surface-1);
color: var(--color-text);
outline: none;
}
.sidebar__edit-input:focus {
border-color: var(--color-primary);
}
.sidebar__edit-btn {
background: none;
border: none;
cursor: pointer;
font-size: 0.85rem;
padding: 4px 8px;
border-radius: var(--radius-sm);
color: var(--color-text-muted);
}
.sidebar__edit-btn:hover {
background: var(--color-surface-2);
color: var(--color-text);
}
/* ---- 左侧视频面板 ---- */
.video-panel {