first commit

This commit is contained in:
liu
2026-07-13 15:23:29 +08:00
commit 50885a98c8
473 changed files with 33772 additions and 0 deletions
+118
View File
@@ -0,0 +1,118 @@
import {
App,
Button,
Empty,
Space,
Switch,
Tag,
Typography,
theme, Spin, Avatar, Card, Tooltip,
} from 'antd';
import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router';
import { getAgentList, updateAgent } from '@/api/ai/agent.ts';
import type { IAgent } from '@/domain/iAgents.ts';
const { Title, Text, Paragraph } = Typography;
export default function AgentPage() {
const { t } = useTranslation();
const { token } = theme.useToken();
const { message } = App.useApp();
const navigate = useNavigate();
const [agents, setAgents] = useState<IAgent[]>([]);
const [loading, setLoading] = useState(false);
const loadAgents = useCallback(async () => {
setLoading(true);
try {
const res = await getAgentList();
setAgents(res.data.data ?? []);
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
loadAgents();
}, [loadAgents]);
const handleToggleEnabled = async (id: number, enabled: boolean) => {
try {
await updateAgent(id, { enabled });
setAgents((prev) =>
prev.map((a) => (a.id === id ? { ...a, enabled } : a)),
);
message.success(t('ai.agent.update.success'));
} catch {
message.error(t('ai.agent.update.failed'));
}
};
return (
<>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: token.marginLG }}>
<div>
<Title level={3} style={{ marginBottom: token.marginXS }}>
{t('ai.agent.page.title')}
</Title>
<Text type="secondary">{t('ai.agent.page.description')}</Text>
</div>
</div>
<Spin spinning={loading}>
{agents.length > 0 ? (
<div className={'flex flex-wrap gap-6'}>
{agents.map((agent) => (
<Tooltip title={agent.description}>
<Card hoverable variant={'borderless'} styles={{ body: { width: 300, padding: 20, overflow: "hidden" }}}>
<div className={'flex justify-between items-center mb-2.5'}>
<Space align={'center'}>
<Avatar src={agent.icon} size={32} />
<span style={{fontWeight: 700, fontSize: 18}}>{agent.name}</span>
</Space>
<Switch
checked={agent.enabled}
size="small"
onChange={(checked) =>
handleToggleEnabled(agent.id!, checked)
}
/>
</div>
<Paragraph
type="secondary"
ellipsis={{ rows: 2 }}
style={{ marginBottom: token.marginSM }}
>
{agent.description}
</Paragraph>
<Space size={[4, 4]} wrap>
{agent.tags?.map((tag) => (
<Tag key={tag} color="blue">
{tag}
</Tag>
))}
</Space>
<div style={{ marginTop: token.marginSM }}>
<Button
type="primary"
size="small"
block
onClick={() => navigate(`/ai/chat?agent_id=${agent.id}`)}
>
{t('ai.agent.goChat')}
</Button>
</div>
</Card>
</Tooltip>
))}
</div>
) : (
<Empty description={t('ai.agent.empty')} />
)}
</Spin>
</>
);
}