+
+
内容安全
+
+ } type="primary" onClick={() => { setNewWord(''); setAddOpen(true) }}>新增敏感词
+ } onClick={() => qc.invalidateQueries({ queryKey: ['safety'] })}>刷新
+
+
+
+
},
+ { key: 'checks', label: '审核记录', children:
},
+ ]} />
+
+
setAddOpen(false)} okText="添加">
+ setNewWord(e.target.value)} style={{ marginBottom: 12 }} />
+
+
+
+
+ )
+}
+
+export default CSPage
diff --git a/src/pages/Metrics.tsx b/src/pages/Metrics.tsx
new file mode 100644
index 0000000..02f3ef2
--- /dev/null
+++ b/src/pages/Metrics.tsx
@@ -0,0 +1,57 @@
+import { useQuery, useQueryClient } from '@tanstack/react-query'
+import { Table, Card, Row, Col, Statistic, Button, Typography, App } from 'antd'
+import { ReloadOutlined, DashboardOutlined } from '@ant-design/icons'
+import { api } from '@/services/http-client'
+import dayjs from 'dayjs'
+
+const { Title } = Typography
+
+function MetricsPage() {
+ const qc = useQueryClient()
+
+ const { data: overview } = useQuery({ queryKey: ['metrics', 'overview'], queryFn: () => api.get('/admin-api/metrics/overview'), staleTime: 10_000 })
+ const { data: top } = useQuery({ queryKey: ['metrics', 'top'], queryFn: () => api.get('/admin-api/metrics/top?limit=15'), staleTime: 10_000 })
+ const { data: recent } = useQuery({ queryKey: ['metrics', 'recent'], queryFn: () => api.get('/admin-api/metrics/recent?limit=30'), staleTime: 5_000 })
+
+ const topCols = [
+ { title: '接口', dataIndex: 'path', width: 300, ellipsis: true },
+ { title: '方法', dataIndex: 'method', width: 70 },
+ { title: '调用', dataIndex: 'calls', width: 70, align: 'center' as const },
+ { title: '平均耗时', dataIndex: 'avgDuration', width: 100, align: 'center' as const, render: (v: number) =>