feat(admin): add ConfigSync page + close ADMIN-01/02 (AUDIT_TRACKER)
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

- ADMIN-01 FIXED: ConfigSync.tsx page with ProTable + pagination
  - config-sync service calling GET /config/sync-logs
  - route + nav item + breadcrumb
  - backend @reserved → @connected
- ADMIN-02 FALSE_POSITIVE: Logs.tsx + logs service already exist
This commit is contained in:
iven
2026-04-05 01:40:38 +08:00
parent 745c2fd754
commit d6b1f44119
7 changed files with 140 additions and 3 deletions

View File

@@ -0,0 +1,111 @@
// ============================================================
// 配置同步日志
// ============================================================
import { useState } from 'react'
import { useQuery } from '@tanstack/react-query'
import { Tag, Typography } from 'antd'
import type { ProColumns } from '@ant-design/pro-components'
import { ProTable } from '@ant-design/pro-components'
import { configSyncService } from '@/services/config-sync'
import type { ConfigSyncLog } from '@/types'
const { Title } = Typography
const actionLabels: Record<string, string> = {
push: '推送',
merge: '合并',
pull: '拉取',
diff: '差异',
}
const actionColors: Record<string, string> = {
push: 'blue',
merge: 'green',
pull: 'cyan',
diff: 'orange',
}
export default function ConfigSync() {
const [page, setPage] = useState(1)
const { data, isLoading } = useQuery({
queryKey: ['config-sync', page],
queryFn: ({ signal }) => configSyncService.list({ page, page_size: 20 }, signal),
})
const columns: ProColumns<ConfigSyncLog>[] = [
{
title: '操作',
dataIndex: 'action',
width: 100,
render: (_, r) => (
<Tag color={actionColors[r.action] || 'default'}>
{actionLabels[r.action] || r.action}
</Tag>
),
},
{
title: '客户端指纹',
dataIndex: 'client_fingerprint',
width: 160,
render: (_, r) => <code>{r.client_fingerprint.substring(0, 16)}...</code>,
},
{
title: '配置键',
dataIndex: 'config_keys',
width: 200,
ellipsis: true,
},
{
title: '客户端值',
dataIndex: 'client_values',
width: 150,
ellipsis: true,
render: (_, r) => r.client_values || '-',
},
{
title: '服务端值',
dataIndex: 'saas_values',
width: 150,
ellipsis: true,
render: (_, r) => r.saas_values || '-',
},
{
title: '解决方式',
dataIndex: 'resolution',
width: 120,
render: (_, r) => r.resolution || '-',
},
{
title: '时间',
dataIndex: 'created_at',
width: 180,
render: (_, r) => new Date(r.created_at).toLocaleString('zh-CN'),
},
]
return (
<div>
<div style={{ marginBottom: 24 }}>
<Title level={4} style={{ margin: 0 }}></Title>
</div>
<ProTable<ConfigSyncLog>
columns={columns}
dataSource={data?.items ?? []}
loading={isLoading}
rowKey="id"
search={false}
toolBarRender={false}
pagination={{
total: data?.total ?? 0,
pageSize: 20,
current: page,
onChange: setPage,
showSizeChanger: false,
}}
/>
</div>
)
}