chore: 更新智能体列表展示

main
sp mac bookpro 2605 2026-06-08 15:12:13 +08:00
parent 6f4f232e80
commit 85090899e6
1 changed files with 76 additions and 79 deletions

View File

@ -8,39 +8,39 @@ import {
RobotOutlined RobotOutlined
} from '@ant-design/icons'; } from '@ant-design/icons';
import { Button, Col, Row, Empty, Popconfirm, App as AntApp, Tag, Space } from 'antd'; import { Button, Col, Row, Empty, Popconfirm, App as AntApp, Tag, Space } from 'antd';
import { Link, useNavigate } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { Agent, AgentAPI } from '../api'; import { Agent, AgentAPI } from '../api';
export default function AgentList() { export default function AgentList() {
const [list, setList] = useState<Agent[]>([]); const [list, setList] = useState<Agent[]>([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const navigate = useNavigate(); const navigate = useNavigate();
const { message } = AntApp.useApp(); const { message } = AntApp.useApp();
const load = async () => { const load = async () => {
setLoading(true); setLoading(true);
try { try {
setList(await AgentAPI.list()); setList(await AgentAPI.list());
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
useEffect(() => { useEffect(() => {
load(); load();
}, []); }, []);
const handleDelete = async (id: string) => { const handleDelete = async (id: string) => {
await AgentAPI.remove(id); await AgentAPI.remove(id);
message.success('已删除'); message.success('已删除');
load(); load();
}; };
const isImageUrl = (url: string) => url?.startsWith('http') || url?.startsWith('/'); const isImageUrl = (url: string) => url?.startsWith('http') || url?.startsWith('/');
const publicCount = useMemo(() => list.filter((a) => a.visibility === 'public').length, [list]); const publicCount = useMemo(() => list.filter((a) => a.visibility === 'public').length, [list]);
const teamCount = useMemo(() => list.filter((a) => a.visibility === 'team').length, [list]); const teamCount = useMemo(() => list.filter((a) => a.visibility === 'team').length, [list]);
return ( return (
<div className="page-container"> <div className="page-container">
<div <div
style={{ style={{
@ -89,7 +89,7 @@ export default function AgentList() {
<div className="page-subtitle" style={{ marginTop: 0, fontSize: 15, lineHeight: 1.75 }}> <div className="page-subtitle" style={{ marginTop: 0, fontSize: 15, lineHeight: 1.75 }}>
AI 广 AI 广
</div> </div>
</div> </div>
<Button <Button
type="primary" type="primary"
size="large" size="large"
@ -99,7 +99,7 @@ export default function AgentList() {
> >
广 广
</Button> </Button>
</div> </div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 14 }}> <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 14 }}>
{[ {[
@ -135,20 +135,20 @@ export default function AgentList() {
</div> </div>
))} ))}
</div> </div>
</div> </div>
{!loading && list.length === 0 ? ( {!loading && list.length === 0 ? (
<div className="empty-state"> <div className="empty-state">
<Empty description="你还没有任何智能体"> <Empty description="你还没有任何智能体">
<Button type="primary" onClick={() => navigate('/marketplace')} style={{ borderRadius: 10 }}> <Button type="primary" onClick={() => navigate('/marketplace')} style={{ borderRadius: 10 }}>
广 广
</Button> </Button>
</Empty> </Empty>
</div> </div>
) : ( ) : (
<Row gutter={[18, 18]}> <Row gutter={[18, 18]}>
{list.map((a) => ( {list.map((a) => (
<Col xs={24} sm={12} md={8} lg={6} key={a.id}> <Col xs={24} sm={12} md={8} lg={6} key={a.id}>
<div <div
className="agent-card" className="agent-card"
style={{ style={{
@ -164,19 +164,19 @@ export default function AgentList() {
className="avatar" className="avatar"
style={{ background: a.avatar || 'var(--gradient-brand)', borderRadius: '50%', overflow: 'hidden', width: 54, height: 54 }} style={{ background: a.avatar || 'var(--gradient-brand)', borderRadius: '50%', overflow: 'hidden', width: 54, height: 54 }}
> >
{isImageUrl(a.avatar) ? ( {isImageUrl(a.avatar) ? (
<img src={a.avatar} className="w-full h-full object-cover" alt="avatar" /> <img src={a.avatar} className="w-full h-full object-cover" alt="avatar" />
) : ( ) : (
(a.name?.charAt(0) || '?').toUpperCase() (a.name?.charAt(0) || '?').toUpperCase()
)} )}
</div> </div>
<div style={{ flex: 1, minWidth: 0 }}> <div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontWeight: 700, fontSize: 17, color: 'var(--color-text)', marginBottom: 4 }}>{a.name}</div> <div style={{ fontWeight: 700, fontSize: 17, color: 'var(--color-text)', marginBottom: 4 }}>{a.name}</div>
<div style={{ fontSize: 12.5, color: 'var(--color-text-tertiary)' }}> <div style={{ fontSize: 12.5, color: 'var(--color-text-tertiary)' }}>
{dayjs(a.updated_at).format('YYYY-MM-DD')} {dayjs(a.updated_at).format('YYYY-MM-DD')}
</div> </div>
</div> </div>
</div> </div>
<div <div
style={{ style={{
@ -215,42 +215,39 @@ export default function AgentList() {
</span> </span>
</Tag> </Tag>
)} )}
<Tag bordered={false} style={{ background: 'var(--color-surface-2)', color: 'var(--color-text-secondary)', borderRadius: 999, margin: 0 }}>
T={a.temperature}
</Tag>
{(a.fork_count ?? 0) > 0 && ( {(a.fork_count ?? 0) > 0 && (
<Tag bordered={false} style={{ background: 'var(--color-surface-2)', color: 'var(--color-text-secondary)', borderRadius: 999, margin: 0 }}> <Tag bordered={false} style={{ background: 'var(--color-surface-2)', color: 'var(--color-text-secondary)', borderRadius: 999, margin: 0 }}>
Fork {a.fork_count} Fork {a.fork_count}
</Tag> </Tag>
)} )}
</Space> </Space>
<div style={{ display: 'flex', gap: 8, marginTop: 'auto', paddingTop: 16, borderTop: '1px solid var(--color-border)' }}> <div style={{ display: 'flex', gap: 8, marginTop: 'auto', paddingTop: 16, borderTop: '1px solid var(--color-border)' }}>
<Link to={`/chat/${a.id}`} style={{ flex: 1 }}> <Link to={`/chat/${a.id}`} style={{ flex: 1 }}>
<Button type="primary" block icon={<MessageOutlined />} style={{ borderRadius: 12, height: 40, fontWeight: 600 }}> <Button type="primary" block icon={<MessageOutlined />} style={{ borderRadius: 12, height: 40, fontWeight: 600 }}>
</Button> </Button>
</Link> </Link>
<Link to={`/agents/${a.id}`} style={{ flex: 1 }}> <Link to={`/agents/${a.id}`} style={{ flex: 1 }}>
<Button block icon={<EditOutlined />} style={{ borderRadius: 12, height: 40 }}> <Button block icon={<EditOutlined />} style={{ borderRadius: 12, height: 40 }}>
</Button> </Button>
</Link> </Link>
<Popconfirm <Popconfirm
title="确定删除该智能体?" title="确定删除该智能体?"
description="将删除其知识库与对话记录" description="将删除其知识库与对话记录"
onConfirm={() => handleDelete(a.id)} onConfirm={() => handleDelete(a.id)}
okText="删除" okText="删除"
cancelText="取消" cancelText="取消"
> >
<Button danger icon={<DeleteOutlined />} style={{ borderRadius: 12, width: 40, height: 40 }} /> <Button danger icon={<DeleteOutlined />} style={{ borderRadius: 12, width: 40, height: 40 }} />
</Popconfirm> </Popconfirm>
</div> </div>
</div> </div>
</Col> </Col>
))} ))}
</Row> </Row>
)} )}
{list.length > 0 && ( {list.length > 0 && (
<div <div
@ -280,6 +277,6 @@ export default function AgentList() {
</Button> </Button>
</div> </div>
)} )}
</div> </div>
); );
} }