78 lines
2.4 KiB
TypeScript
78 lines
2.4 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { Card, Col, Row, Statistic, Table, Tag, Typography } from 'antd';
|
|
import { getStats } from '../../api';
|
|
|
|
export default function Stats() {
|
|
const [data, setData] = useState<Awaited<ReturnType<typeof getStats>> | null>(null);
|
|
|
|
useEffect(() => {
|
|
getStats().then(setData).catch(() => {});
|
|
}, []);
|
|
|
|
if (!data) return <Typography>加载中…</Typography>;
|
|
|
|
return (
|
|
<div>
|
|
<Row gutter={16} style={{ marginBottom: 24 }}>
|
|
<Col span={6}>
|
|
<Card>
|
|
<Statistic title="Token 总数" value={data.total} />
|
|
</Card>
|
|
</Col>
|
|
<Col span={6}>
|
|
<Card>
|
|
<Statistic title="活跃" value={data.active} valueStyle={{ color: '#3f8600' }} />
|
|
</Card>
|
|
</Col>
|
|
<Col span={6}>
|
|
<Card>
|
|
<Statistic title="已吊销" value={data.revoked} valueStyle={{ color: '#cf1322' }} />
|
|
</Card>
|
|
</Col>
|
|
<Col span={6}>
|
|
<Card>
|
|
<Statistic title="近 24h 调用" value={data.calls_24h} />
|
|
</Card>
|
|
</Col>
|
|
</Row>
|
|
|
|
<Card title="按服务范围分布" style={{ marginBottom: 24 }}>
|
|
<Row gutter={16}>
|
|
{Object.entries(data.by_scope).map(([scope, cnt]) => (
|
|
<Col key={scope} span={8}>
|
|
<Statistic title={scope} value={cnt} />
|
|
</Col>
|
|
))}
|
|
{Object.keys(data.by_scope).length === 0 && (
|
|
<Typography.Text type="secondary">暂无数据</Typography.Text>
|
|
)}
|
|
</Row>
|
|
</Card>
|
|
|
|
<Card title="最近调用">
|
|
<Table
|
|
dataSource={data.recent}
|
|
rowKey={(_, i) => String(i)}
|
|
pagination={{ pageSize: 10 }}
|
|
columns={[
|
|
{ title: 'Token', dataIndex: 'token_prefix', key: 'token_prefix' },
|
|
{ title: '客户端', dataIndex: 'client_id', key: 'client_id' },
|
|
{
|
|
title: '服务',
|
|
dataIndex: 'service',
|
|
key: 'service',
|
|
render: (s: string) => (s ? <Tag color="blue">{s}</Tag> : '-'),
|
|
},
|
|
{
|
|
title: '调用时间',
|
|
dataIndex: 'last_used_at',
|
|
key: 'last_used_at',
|
|
render: (t: string) => (t ? new Date(t).toLocaleString('zh-CN') : '-'),
|
|
},
|
|
]}
|
|
/>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|