chore: 更新智能体列表展示
parent
6f4f232e80
commit
85090899e6
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue