admin-projects/src/pages/CacheAdmin.tsx
WangDL cf1ea873e0
Some checks failed
Deploy Admin Frontend / build-and-deploy (push) Failing after 7s
refactor: replace any with proper types in admin page api calls
- Add CacheStats, NotificationTemplate, NotificationLog, ReviewCardItem to types/api.ts
- Use PaginatedResult<T> for ReviewAdmin pagination
- All queryFn now declare explicit Promise<T> return type

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 16:22:47 +08:00

103 lines
3.3 KiB
TypeScript

import { Card, Button, Statistic, Row, Col, Space, Typography, message } from 'antd'
import { ClearOutlined, ReloadOutlined, DeleteOutlined } from '@ant-design/icons'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { api } from '@/services/http-client'
import type { CacheStats } from '@/types/api'
const { Title } = Typography
export default function CacheAdmin() {
const qc = useQueryClient()
const { data: stats, isLoading } = useQuery({
queryKey: ['admin', 'cache-stats'],
queryFn: (): Promise<CacheStats> => api.get('/admin-api/cache/stats'),
refetchInterval: 10_000,
})
const flushModule = useMutation({
mutationFn: (module: string) => api.post(`/admin-api/cache/flush/${module}`),
onSuccess: (_, mod) => {
message.success(`已清除 ${mod} 模块缓存`)
qc.invalidateQueries({ queryKey: ['admin', 'cache-stats'] })
},
})
const flushAll = useMutation({
mutationFn: () => api.post('/admin-api/cache/flush-all'),
onSuccess: () => {
message.success('已清除所有缓存')
qc.invalidateQueries({ queryKey: ['admin', 'cache-stats'] })
},
})
const resetStats = useMutation({
mutationFn: () => api.post('/admin-api/cache/reset-stats'),
onSuccess: () => qc.invalidateQueries({ queryKey: ['admin', 'cache-stats'] }),
})
const modules = [
{ key: 'config', label: '配置缓存' },
{ key: 'workspace', label: '工作台缓存' },
{ key: 'admin', label: 'Admin 缓存' },
{ key: 'ai', label: 'AI 路由缓存' },
{ key: 'safety', label: '安全词库缓存' },
{ key: 'user', label: '用户信息缓存' },
{ key: 'kb', label: '知识库缓存' },
]
return (
<div>
<Title level={4}></Title>
<Row gutter={16} style={{ marginBottom: 24 }}>
<Col span={6}>
<Card><Statistic title="命中次数" value={stats?.hits ?? 0} loading={isLoading} /></Card>
</Col>
<Col span={6}>
<Card><Statistic title="未命中次数" value={stats?.misses ?? 0} loading={isLoading} /></Card>
</Col>
<Col span={6}>
<Card><Statistic title="命中率" value={stats?.hitRate ?? 0} suffix="%" precision={1} loading={isLoading} /></Card>
</Col>
<Col span={6}>
<Card><Statistic title="Redis 状态" value={stats?.available ? '在线' : '离线'} valueStyle={{ color: stats?.available ? '#52c41a' : '#f5222d' }} loading={isLoading} /></Card>
</Col>
</Row>
<Card title="按模块清除缓存" style={{ marginBottom: 24 }}>
<Space wrap>
{modules.map(m => (
<Button
key={m.key}
icon={<ClearOutlined />}
onClick={() => flushModule.mutate(m.key)}
loading={flushModule.isPending}
>
{m.label}
</Button>
))}
</Space>
</Card>
<Space>
<Button
danger
icon={<DeleteOutlined />}
onClick={() => flushAll.mutate()}
loading={flushAll.isPending}
>
</Button>
<Button
icon={<ReloadOutlined />}
onClick={() => resetStats.mutate()}
loading={resetStats.isPending}
>
</Button>
</Space>
</div>
)
}