chat: add history/new session actions and fix icons

main
sp mac bookpro 2605 2026-06-06 13:45:07 +08:00
parent fb78c4e64a
commit 3f5b737fbb
4 changed files with 98 additions and 3 deletions

View File

@ -31,3 +31,46 @@ export function ProductCopyIcon(props: SVGProps<SVGSVGElement>) {
);
}
export function HistoryIcon(props: SVGProps<SVGSVGElement>) {
const { width = 20, height = 20, ...rest } = props;
return (
<svg
fill="none"
width={width}
height={height}
viewBox="0 0 16 16"
style={{ minWidth: 18, minHeight: 18, color: 'var(--theme-icon-primary)' }}
{...rest}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 2.625C5.03147 2.625 2.625 5.03147 2.625 8C2.625 10.9685 5.03147 13.375 8 13.375C10.9685 13.375 13.375 10.9685 13.375 8C13.375 5.03147 10.9685 2.625 8 2.625ZM1.375 8C1.375 4.34111 4.34111 1.375 8 1.375C11.6589 1.375 14.625 4.34111 14.625 8C14.625 11.6589 11.6589 14.625 8 14.625C4.34111 14.625 1.375 11.6589 1.375 8ZM8 3.775C8.34518 3.775 8.625 4.05482 8.625 4.4V7.61373L10.6795 8.64098C10.9882 8.79535 11.1134 9.17077 10.959 9.47951C10.8046 9.78825 10.4292 9.91339 10.1205 9.75902L7.72049 8.55902C7.50875 8.45315 7.375 8.23673 7.375 8V4.4C7.375 4.05482 7.65482 3.775 8 3.775Z"
fill="currentColor"
/>
</svg>
);
}
export function NewChatIcon(props: SVGProps<SVGSVGElement>) {
const { width = 20, height = 20, ...rest } = props;
return (
<svg
width={width}
height={height}
fill="none"
viewBox="0 0 256 256"
style={{ minWidth: 18, minHeight: 18 }}
{...rest}
>
<g>
<path
fillRule="evenodd"
clipRule="evenodd"
fill="var(--theme-icon-brand)"
d="M128 22C69.458 22 22 69.458 22 128v96c0 5.523 4.477 10 10 10h96c58.542 0 106-47.458 106-106S186.542 22 128 22Zm0 56c5.523 0 10 4.477 10 10v30h30c5.523 0 10 4.477 10 10s-4.477 10-10 10h-30v30c0 5.523-4.477 10-10 10s-10-4.477-10-10v-30H88c-5.523 0-10-4.477-10-10s4.477-10 10-10h30V88c0-5.523 4.477-10 10-10Z"
/>
</g>
</svg>
);
}

View File

@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from 'react';
import { App as AntApp, Empty } from 'antd';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import type { ModelOverrides } from '../../api';
import { SessionAPI } from '../../api';
import AgentSidebar from './components/AgentSidebar';
import ChatHeader from './components/ChatHeader';
import ChatBody from './components/ChatBody';
@ -146,6 +147,20 @@ export default function ChatPage() {
const selected = sender.modelOptions.find((m) => m.value === modelId);
setOverrides((o) => ({ ...o, model_id: String(modelId), model: selected?.label || String(modelId) }));
}}
onOpenHistory={() => setHistoryDrawerOpen(true)}
onNewSession={async () => {
if (!id) return;
abortRef.current?.abort();
try {
const created = await SessionAPI.create(id);
setHighlightId(null);
setMessages(() => []);
setBranches({});
setSessionId(created.id);
} catch (e: any) {
message.error('创建会话失败:' + (e?.message ?? e));
}
}}
/>
</>
)}

View File

@ -1,6 +1,7 @@
import { ArrowUpOutlined, BookOutlined, CloseOutlined, DownOutlined, PaperClipOutlined } from '@ant-design/icons';
import { Button, Image as AntImage, Input, Select, Tag, Upload } from 'antd';
import { Button, Image as AntImage, Input, Select, Tag, Tooltip, Upload } from 'antd';
import type { ChatAttachment } from '../../../api';
import { HistoryIcon, NewChatIcon } from '../../../components/icons';
export default function ChatInput(props: {
input: string;
@ -17,6 +18,8 @@ export default function ChatInput(props: {
modelOptions: Array<{ value: string; label: string }>;
activeModelValue: string;
onChangeModel: (modelId: string) => void;
onOpenHistory: () => void;
onNewSession: () => void;
}) {
const {
input,
@ -32,7 +35,9 @@ export default function ChatInput(props: {
onOpenTpl,
modelOptions,
activeModelValue,
onChangeModel
onChangeModel,
onOpenHistory,
onNewSession
} = props;
return (
@ -59,6 +64,18 @@ export default function ChatInput(props: {
</div>
<div className="chat-input-card">
<div className="chat-input-actions">
<Tooltip title="历史记录">
<Button size="small" type="text" className="chat-input-action-btn" icon={<HistoryIcon />} onClick={onOpenHistory}>
</Button>
</Tooltip>
<Tooltip title="新增会话">
<Button size="small" type="text" className="chat-input-action-btn" icon={<NewChatIcon />} onClick={onNewSession}>
</Button>
</Tooltip>
</div>
<div className="chat-input-stack">
<Input.TextArea
value={input}
@ -138,4 +155,3 @@ export default function ChatInput(props: {
</div>
);
}

View File

@ -749,6 +749,27 @@ body {
padding: 14px 16px 12px;
min-height: 110px;
box-shadow: var(--shadow-sm);
position: relative;
}
.chat-input-actions {
position: absolute;
top: 10px;
right: 12px;
display: flex;
gap: 4px;
z-index: 2;
}
.chat-input-action-btn {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--color-text-secondary);
}
.chat-input-action-btn:hover {
color: var(--color-text);
}
.chat-input-stack {