ui: replace session sidebar emoji icons with antd icons

main
sp mac bookpro 2605 2026-06-06 14:35:55 +08:00
parent 3d60016d87
commit b333600245
1 changed files with 37 additions and 26 deletions

View File

@ -1,5 +1,6 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Button, List, Popconfirm, Input, App as AntApp, Tooltip, Empty, Segmented, Tag, Spin, Dropdown, Modal } from 'antd'; import { Button, List, Popconfirm, Input, App as AntApp, Tooltip, Empty, Segmented, Tag, Spin, Dropdown, Modal } from 'antd';
import { DeleteOutlined, DownloadOutlined, InboxOutlined, EditOutlined, MessageOutlined, RollbackOutlined, ShareAltOutlined } from '@ant-design/icons';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { ChatSession, SearchHit, SessionAPI } from '../api'; import { ChatSession, SearchHit, SessionAPI } from '../api';
@ -9,10 +10,10 @@ interface Props {
onChange: (sessionId: string, options?: { highlightMessageId?: string }) => void; onChange: (sessionId: string, options?: { highlightMessageId?: string }) => void;
refreshTick?: number; refreshTick?: number;
theme?: 'light' | 'dark'; theme?: 'light' | 'dark';
showNewButton?: boolean; showNewButton?: boolean;
} }
export default function SessionSidebar({ agentId, activeSessionId, onChange, refreshTick, theme = 'light', showNewButton = true }: Props) { export default function SessionSidebar({ agentId, activeSessionId, onChange, refreshTick, theme = 'light', showNewButton = true }: Props) {
const { message } = AntApp.useApp(); const { message } = AntApp.useApp();
const [tab, setTab] = useState<'active' | 'archived'>('active'); const [tab, setTab] = useState<'active' | 'archived'>('active');
const [active, setActive] = useState<ChatSession[]>([]); const [active, setActive] = useState<ChatSession[]>([]);
@ -218,25 +219,27 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
<Button <Button
type="text" type="text"
size="small" size="small"
icon={<EditOutlined />}
onClick={() => { onClick={() => {
setEditingId(s.id); setEditingId(s.id);
setEditingTitle(s.title); setEditingTitle(s.title);
}} }}
> />
</Button>
</Tooltip> </Tooltip>
<Tooltip title={tab === 'active' ? '归档' : '恢复'}> <Tooltip title={tab === 'active' ? '归档' : '恢复'}>
<Button type="text" size="small" onClick={() => handleArchive(s, tab === 'active')}> <Button
{tab === 'active' ? '📦' : '↩️'} type="text"
</Button> size="small"
icon={tab === 'active' ? <InboxOutlined /> : <RollbackOutlined />}
onClick={() => handleArchive(s, tab === 'active')}
/>
</Tooltip> </Tooltip>
<Dropdown <Dropdown
trigger={['click']} trigger={['click']}
menu={{ menu={{
items: [ items: [
{ key: 'md', label: '⬇️ Markdown (.md)' }, { key: 'md', label: 'Markdown (.md)' },
{ key: 'json', label: '⬇️ JSON (.json)' } { key: 'json', label: 'JSON (.json)' }
], ],
onClick: ({ key }) => { onClick: ({ key }) => {
SessionAPI.exportSession(agentId, s.id, key as 'md' | 'json'); SessionAPI.exportSession(agentId, s.id, key as 'md' | 'json');
@ -245,20 +248,14 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
}} }}
> >
<Tooltip title="导出会话"> <Tooltip title="导出会话">
<Button type="text" size="small"> <Button type="text" size="small" icon={<DownloadOutlined />} />
</Button>
</Tooltip> </Tooltip>
</Dropdown> </Dropdown>
<Tooltip title="分享公开链接(任何人都可只读访问)"> <Tooltip title="分享公开链接(任何人都可只读访问)">
<Button type="text" size="small" onClick={() => handleShare(s)}> <Button type="text" size="small" icon={<ShareAltOutlined />} onClick={() => handleShare(s)} />
🔗
</Button>
</Tooltip> </Tooltip>
<Popconfirm title="删除此会话(不可恢复)?" onConfirm={() => handleDelete(s.id)} okText="删除" cancelText="取消"> <Popconfirm title="删除此会话(不可恢复)?" onConfirm={() => handleDelete(s.id)} okText="删除" cancelText="取消">
<Button type="text" size="small" danger> <Button type="text" size="small" danger icon={<DeleteOutlined />} />
🗑
</Button>
</Popconfirm> </Popconfirm>
</div> </div>
)} )}
@ -270,11 +267,11 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
return ( return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}> <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
{showNewButton && ( {showNewButton && (
<Button type="primary" onClick={handleNew} style={{ marginBottom: 8, background: c.primaryBtn }} block> <Button type="primary" onClick={handleNew} style={{ marginBottom: 8, background: c.primaryBtn }} block>
</Button> </Button>
)} )}
<Input.Search <Input.Search
placeholder="搜索会话与消息…" placeholder="搜索会话与消息…"
@ -364,8 +361,22 @@ export default function SessionSidebar({ agentId, activeSessionId, onChange, ref
value={tab} value={tab}
onChange={(v) => setTab(v as any)} onChange={(v) => setTab(v as any)}
options={[ options={[
{ value: 'active', label: `💬 活跃 (${active.length})` }, {
{ value: 'archived', label: `📦 归档 (${archived.length})` } value: 'active',
label: (
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
<MessageOutlined /> ({active.length})
</span>
)
},
{
value: 'archived',
label: (
<span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
<InboxOutlined /> ({archived.length})
</span>
)
}
]} ]}
style={{ marginBottom: 8 }} style={{ marginBottom: 8 }}
/> />