ui: refactor session sidebar styles and widen history drawer
parent
b333600245
commit
1c2c7bd06a
|
|
@ -67,6 +67,19 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
};
|
||||
|
||||
const list = tab === 'active' ? active : archived;
|
||||
const styleVars = {
|
||||
['--ss-text' as any]: c.text,
|
||||
['--ss-text-dim' as any]: c.textDim,
|
||||
['--ss-text-active' as any]: c.textActive,
|
||||
['--ss-bg-active' as any]: c.bgActive,
|
||||
['--ss-border-active' as any]: c.borderActive,
|
||||
['--ss-bg-hover' as any]: c.bgHover,
|
||||
['--ss-bg-search' as any]: c.bgSearch,
|
||||
['--ss-input-bg' as any]: c.inputBg,
|
||||
['--ss-border' as any]: c.border,
|
||||
['--ss-danger' as any]: c.dangerText,
|
||||
['--ss-primary' as any]: c.primaryBtn ?? 'var(--color-brand)'
|
||||
} as any;
|
||||
|
||||
// 防抖搜索
|
||||
useEffect(() => {
|
||||
|
|
@ -165,16 +178,9 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
<List.Item
|
||||
key={s.id}
|
||||
onClick={() => (editing ? null : onChange(s.id))}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
padding: '8px 10px',
|
||||
background: isActive ? c.bgActive : c.bgTransparent,
|
||||
borderRadius: 6,
|
||||
border: isActive ? `1px solid ${c.borderActive}` : '1px solid transparent',
|
||||
marginBottom: 4
|
||||
}}
|
||||
className={`session-sidebar-item${isActive ? ' active' : ''}`}
|
||||
>
|
||||
<div style={{ flex: 1, minWidth: 0 }}>
|
||||
<div className="session-sidebar-item-main">
|
||||
{editing ? (
|
||||
<Input
|
||||
size="small"
|
||||
|
|
@ -186,35 +192,17 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
/>
|
||||
) : (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 13,
|
||||
fontWeight: isActive ? 600 : 500,
|
||||
color: isActive ? c.textActive : c.text,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap'
|
||||
}}
|
||||
>
|
||||
💬 {s.title}
|
||||
<div className={`session-sidebar-item-title${isActive ? ' active' : ''}`}>
|
||||
<MessageOutlined /> {s.title}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
fontSize: 11,
|
||||
color: c.textDim,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
marginTop: 2
|
||||
}}
|
||||
>
|
||||
<div className="session-sidebar-item-subtitle">
|
||||
{s.lastPreview || '无消息'} · {dayjs(s.lastAt || s.updatedAt).format('MM-DD HH:mm')}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{!editing && (
|
||||
<div style={{ display: 'flex', gap: 2, marginLeft: 6 }} onClick={(e) => e.stopPropagation()}>
|
||||
<div className="session-sidebar-item-actions" onClick={(e) => e.stopPropagation()}>
|
||||
<Tooltip title="重命名">
|
||||
<Button
|
||||
type="text"
|
||||
|
|
@ -266,10 +254,10 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
const inSearchMode = searchQ.trim().length > 0;
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||
<div className="session-sidebar" style={styleVars}>
|
||||
{showNewButton && (
|
||||
<Button type="primary" onClick={handleNew} style={{ marginBottom: 8, background: c.primaryBtn }} block>
|
||||
➕ 新对话
|
||||
<Button type="primary" onClick={handleNew} className="session-sidebar-new" block>
|
||||
新对话
|
||||
</Button>
|
||||
)}
|
||||
|
||||
|
|
@ -278,14 +266,13 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
allowClear
|
||||
value={searchQ}
|
||||
onChange={(e) => setSearchQ(e.target.value)}
|
||||
style={{ marginBottom: 8 }}
|
||||
styles={isDark ? { input: { background: c.inputBg, borderColor: c.border, color: c.text } } : undefined}
|
||||
className="session-sidebar-search"
|
||||
/>
|
||||
|
||||
{inSearchMode ? (
|
||||
<div style={{ flex: 1, overflow: 'auto' }}>
|
||||
<div className="session-sidebar-scroll">
|
||||
{searching ? (
|
||||
<div style={{ padding: 16, textAlign: 'center' }}>
|
||||
<div className="session-sidebar-loading">
|
||||
<Spin size="small" />
|
||||
</div>
|
||||
) : searchHits.length === 0 && searchSessionTitles.length === 0 ? (
|
||||
|
|
@ -293,25 +280,17 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
) : (
|
||||
<>
|
||||
{searchSessionTitles.length > 0 && (
|
||||
<div style={{ marginBottom: 8 }}>
|
||||
<div style={{ fontSize: 11, color: c.textDim, padding: '4px 8px' }}>
|
||||
<div className="session-sidebar-search-section">
|
||||
<div className="session-sidebar-search-section-title">
|
||||
📁 会话标题命中 ({searchSessionTitles.length})
|
||||
</div>
|
||||
{searchSessionTitles.map((s) => (
|
||||
<div
|
||||
key={s.id}
|
||||
onClick={() => onChange(s.id)}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
padding: '6px 10px',
|
||||
borderRadius: 6,
|
||||
marginBottom: 2,
|
||||
background: activeSessionId === s.id ? c.bgActive : c.bgSearch,
|
||||
fontSize: 12,
|
||||
color: c.text
|
||||
}}
|
||||
className={`session-sidebar-search-hit${activeSessionId === s.id ? ' active' : ''}`}
|
||||
>
|
||||
💬 {s.title}
|
||||
<MessageOutlined /> {s.title}
|
||||
{s.archived && <Tag style={{ marginLeft: 6 }}>归档</Tag>}
|
||||
</div>
|
||||
))}
|
||||
|
|
@ -319,7 +298,7 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
)}
|
||||
{searchHits.length > 0 && (
|
||||
<div>
|
||||
<div style={{ fontSize: 11, color: c.textDim, padding: '4px 8px' }}>
|
||||
<div className="session-sidebar-search-section-title">
|
||||
🔎 消息内容命中 ({searchHits.length})
|
||||
</div>
|
||||
{searchHits.map((h) => (
|
||||
|
|
@ -328,22 +307,15 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
onClick={() =>
|
||||
onChange(h.sessionId, { highlightMessageId: h.id })
|
||||
}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
padding: 8,
|
||||
borderRadius: 6,
|
||||
marginBottom: 4,
|
||||
background: c.bgSearch,
|
||||
borderLeft: `3px solid ${h.role === 'user' ? '#6366f1' : '#10b981'}`
|
||||
}}
|
||||
className={`session-sidebar-search-msg-hit ${h.role === 'user' ? 'role-user' : 'role-assistant'}`}
|
||||
>
|
||||
<div style={{ fontSize: 11, color: c.textDim, marginBottom: 2 }}>
|
||||
<div className="session-sidebar-search-msg-meta">
|
||||
{h.role === 'user' ? '我' : 'AI'} · {h.sessionTitle}
|
||||
{h.sessionArchived && <Tag style={{ marginLeft: 4 }}>归档</Tag>}
|
||||
<span style={{ marginLeft: 6 }}>{dayjs(h.createdAt).format('MM-DD HH:mm')}</span>
|
||||
</div>
|
||||
<div
|
||||
style={{ fontSize: 12, color: c.text, lineHeight: 1.4 }}
|
||||
className="session-sidebar-search-msg-snippet"
|
||||
dangerouslySetInnerHTML={{ __html: h.snippet }}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -364,7 +336,7 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
{
|
||||
value: 'active',
|
||||
label: (
|
||||
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
|
||||
<span className="session-sidebar-seg-label">
|
||||
<MessageOutlined /> 活跃 ({active.length})
|
||||
</span>
|
||||
)
|
||||
|
|
@ -372,13 +344,13 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
{
|
||||
value: 'archived',
|
||||
label: (
|
||||
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
|
||||
<span className="session-sidebar-seg-label">
|
||||
<InboxOutlined /> 归档 ({archived.length})
|
||||
</span>
|
||||
)
|
||||
}
|
||||
]}
|
||||
style={{ marginBottom: 8 }}
|
||||
className="session-sidebar-seg"
|
||||
/>
|
||||
{list.length === 0 ? (
|
||||
<Empty description={tab === 'active' ? '无活跃会话' : '无归档会话'} image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||
|
|
@ -386,22 +358,12 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
|
|||
<List
|
||||
size="small"
|
||||
dataSource={list}
|
||||
style={{ flex: 1, overflow: 'auto' }}
|
||||
className="session-sidebar-list"
|
||||
renderItem={renderSession}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* 顶部全局样式 mark 标签高亮 */}
|
||||
<style>{`
|
||||
mark {
|
||||
background: #fef3c7;
|
||||
color: #b45309;
|
||||
padding: 0 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ export default function ChatDrawers(props: {
|
|||
<Drawer
|
||||
title="聊天记录"
|
||||
placement="right"
|
||||
width={320}
|
||||
width={420}
|
||||
onClose={() => setHistoryDrawerOpen(false)}
|
||||
open={historyDrawerOpen}
|
||||
styles={{ body: { padding: 0 } }}
|
||||
|
|
|
|||
170
src/styles.css
170
src/styles.css
|
|
@ -870,6 +870,176 @@ body {
|
|||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.session-sidebar {
|
||||
width: 420px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.session-sidebar-new {
|
||||
margin-bottom: 8px;
|
||||
background: var(--ss-primary);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.session-sidebar-search {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.session-sidebar .ant-input-affix-wrapper,
|
||||
.session-sidebar .ant-input-affix-wrapper:hover,
|
||||
.session-sidebar .ant-input-affix-wrapper-focused {
|
||||
background: var(--ss-input-bg);
|
||||
border-color: var(--ss-border);
|
||||
}
|
||||
|
||||
.session-sidebar .ant-input {
|
||||
color: var(--ss-text);
|
||||
}
|
||||
|
||||
.session-sidebar-scroll {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.session-sidebar-loading {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.session-sidebar-search-section {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.session-sidebar-search-section-title {
|
||||
font-size: 11px;
|
||||
color: var(--ss-text-dim);
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.session-sidebar-search-hit {
|
||||
cursor: pointer;
|
||||
padding: 6px 10px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 2px;
|
||||
background: var(--ss-bg-search);
|
||||
font-size: 12px;
|
||||
color: var(--ss-text);
|
||||
}
|
||||
|
||||
.session-sidebar-search-hit.active {
|
||||
background: var(--ss-bg-active);
|
||||
}
|
||||
|
||||
.session-sidebar-search-msg-hit {
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 4px;
|
||||
background: var(--ss-bg-search);
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
|
||||
.session-sidebar-search-msg-hit.role-user {
|
||||
border-left-color: #6366f1;
|
||||
}
|
||||
|
||||
.session-sidebar-search-msg-hit.role-assistant {
|
||||
border-left-color: #10b981;
|
||||
}
|
||||
|
||||
.session-sidebar-search-msg-meta {
|
||||
font-size: 11px;
|
||||
color: var(--ss-text-dim);
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.session-sidebar-search-msg-snippet {
|
||||
font-size: 12px;
|
||||
color: var(--ss-text);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.session-sidebar-seg {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.session-sidebar-seg-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.session-sidebar-list {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.session-sidebar-item {
|
||||
cursor: pointer;
|
||||
padding: 8px 10px;
|
||||
background: transparent;
|
||||
border-radius: 6px;
|
||||
border: 1px solid transparent;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.session-sidebar-item:hover {
|
||||
background: var(--ss-bg-hover);
|
||||
}
|
||||
|
||||
.session-sidebar-item.active {
|
||||
background: var(--ss-bg-active);
|
||||
border-color: var(--ss-border-active);
|
||||
}
|
||||
|
||||
.session-sidebar-item-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.session-sidebar-item-title {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--ss-text);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.session-sidebar-item-title.active {
|
||||
font-weight: 600;
|
||||
color: var(--ss-text-active);
|
||||
}
|
||||
|
||||
.session-sidebar-item-subtitle {
|
||||
font-size: 11px;
|
||||
color: var(--ss-text-dim);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.session-sidebar-item-actions {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.session-sidebar mark {
|
||||
background: #fef3c7;
|
||||
color: #b45309;
|
||||
padding: 0 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.chat-disclaimer {
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
|
|
|
|||
Loading…
Reference in New Issue