From d6b1f44119136417b0b3d008ef51a8d760ed7209 Mon Sep 17 00:00:00 2001 From: iven Date: Sun, 5 Apr 2026 01:40:38 +0800 Subject: [PATCH] feat(admin): add ConfigSync page + close ADMIN-01/02 (AUDIT_TRACKER) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- admin-v2/src/layouts/AdminLayout.tsx | 3 + admin-v2/src/pages/ConfigSync.tsx | 111 ++++++++++++++++++++ admin-v2/src/router/index.tsx | 1 + admin-v2/src/services/config-sync.ts | 7 ++ admin-v2/src/types/index.ts | 13 +++ crates/zclaw-saas/src/migration/handlers.rs | 2 +- docs/features/AUDIT_TRACKER.md | 6 +- 7 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 admin-v2/src/pages/ConfigSync.tsx create mode 100644 admin-v2/src/services/config-sync.ts diff --git a/admin-v2/src/layouts/AdminLayout.tsx b/admin-v2/src/layouts/AdminLayout.tsx index 097a524..56da9c8 100644 --- a/admin-v2/src/layouts/AdminLayout.tsx +++ b/admin-v2/src/layouts/AdminLayout.tsx @@ -20,6 +20,7 @@ import { CrownOutlined, SafetyOutlined, FieldTimeOutlined, + SyncOutlined, } from '@ant-design/icons' import { Avatar, Dropdown, Tooltip, Drawer } from 'antd' import { useAuthStore } from '@/stores/authStore' @@ -51,6 +52,7 @@ const navItems: NavItem[] = [ { path: '/knowledge', name: '知识库', icon: , permission: 'knowledge:read', group: '资源管理' }, { path: '/billing', name: '计费管理', icon: , permission: 'billing:read', group: '核心' }, { path: '/logs', name: '操作日志', icon: , permission: 'admin:full', group: '运维' }, + { path: '/config-sync', name: '同步日志', icon: , permission: 'config:read', group: '运维' }, { path: '/config', name: '系统配置', icon: , permission: 'config:read', group: '系统' }, { path: '/prompts', name: '提示词管理', icon: , permission: 'prompt:read', group: '系统' }, ] @@ -219,6 +221,7 @@ const breadcrumbMap: Record = { '/config': '系统配置', '/prompts': '提示词管理', '/logs': '操作日志', + '/config-sync': '同步日志', } // ============================================================ diff --git a/admin-v2/src/pages/ConfigSync.tsx b/admin-v2/src/pages/ConfigSync.tsx new file mode 100644 index 0000000..16d2eb8 --- /dev/null +++ b/admin-v2/src/pages/ConfigSync.tsx @@ -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 = { + push: '推送', + merge: '合并', + pull: '拉取', + diff: '差异', +} + +const actionColors: Record = { + 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[] = [ + { + title: '操作', + dataIndex: 'action', + width: 100, + render: (_, r) => ( + + {actionLabels[r.action] || r.action} + + ), + }, + { + title: '客户端指纹', + dataIndex: 'client_fingerprint', + width: 160, + render: (_, r) => {r.client_fingerprint.substring(0, 16)}..., + }, + { + 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 ( +
+
+ 配置同步日志 +
+ + + 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, + }} + /> +
+ ) +} diff --git a/admin-v2/src/router/index.tsx b/admin-v2/src/router/index.tsx index cc7bee9..9b9d10d 100644 --- a/admin-v2/src/router/index.tsx +++ b/admin-v2/src/router/index.tsx @@ -35,6 +35,7 @@ export const router = createBrowserRouter([ { path: 'config', lazy: () => import('@/pages/Config').then((m) => ({ Component: m.default })) }, { path: 'prompts', lazy: () => import('@/pages/Prompts').then((m) => ({ Component: m.default })) }, { path: 'logs', lazy: () => import('@/pages/Logs').then((m) => ({ Component: m.default })) }, + { path: 'config-sync', lazy: () => import('@/pages/ConfigSync').then((m) => ({ Component: m.default })) }, ], }, ]) diff --git a/admin-v2/src/services/config-sync.ts b/admin-v2/src/services/config-sync.ts new file mode 100644 index 0000000..9738771 --- /dev/null +++ b/admin-v2/src/services/config-sync.ts @@ -0,0 +1,7 @@ +import request, { withSignal } from './request' +import type { ConfigSyncLog, PaginatedResponse } from '@/types' + +export const configSyncService = { + list: (params?: Record, signal?: AbortSignal) => + request.get>('/config/sync-logs', withSignal({ params }, signal)).then((r) => r.data), +} diff --git a/admin-v2/src/types/index.ts b/admin-v2/src/types/index.ts index 6f6b1ac..f8dd89d 100644 --- a/admin-v2/src/types/index.ts +++ b/admin-v2/src/types/index.ts @@ -324,3 +324,16 @@ export interface CreateTemplateRequest { description?: string permissions?: string[] } + +/** 配置同步日志 */ +export interface ConfigSyncLog { + id: number + account_id: string + client_fingerprint: string + action: string + config_keys: string + client_values: string | null + saas_values: string | null + resolution: string | null + created_at: string +} diff --git a/crates/zclaw-saas/src/migration/handlers.rs b/crates/zclaw-saas/src/migration/handlers.rs index 7173cf0..3eda459 100644 --- a/crates/zclaw-saas/src/migration/handlers.rs +++ b/crates/zclaw-saas/src/migration/handlers.rs @@ -137,7 +137,7 @@ pub async fn config_diff( } /// GET /api/v1/config/sync-logs?page=1&page_size=20 -// @reserved - no frontend caller +/// @connected - admin-v2 ConfigSync page pub async fn list_sync_logs( State(state): State, Extension(ctx): Extension, diff --git a/docs/features/AUDIT_TRACKER.md b/docs/features/AUDIT_TRACKER.md index bb9c6dc..b0251cb 100644 --- a/docs/features/AUDIT_TRACKER.md +++ b/docs/features/AUDIT_TRACKER.md @@ -43,8 +43,8 @@ | SEC-V9-02 | relay 输入验证可加强 | **FALSE_POSITIVE** | relay/handlers.rs 已有完整验证(body size/model/role/content/temperature/max_tokens/queue/permission) | | AUDIT-01 | 前端 audit-logger 无消费者 | **FALSE_POSITIVE** | 文件已于先前清理中删除 | | DEAD-04 | director.rs 907 行孤立代码 | **FALSE_POSITIVE** | 与 V11-P3-05 相同,multi-agent feature gate 已正确隔离 | -| ADMIN-01 | config_sync_logs 无 Admin 页面 | OPEN | - | - | 添加页面 | -| ADMIN-02 | operation_logs 无 Admin 页面 | OPEN | - | - | 添加页面 | +| ADMIN-01 | config_sync_logs 无 Admin 页面 | **FIXED** | admin-v2 ConfigSync.tsx + config-sync service + route + nav | +| ADMIN-02 | operation_logs 无 Admin 页面 | **FALSE_POSITIVE** | admin-v2 已有 Logs.tsx + logs service 完整实现 | ## P4: 低优先级 @@ -274,6 +274,8 @@ | 2026-04-05 | V11-P2-05 | 部分关闭 → FIXED | 完整审计: 160 @connected + 16 @reserved + 1 未注册 = 177 总命令 | | 2026-04-05 | TYPE-01 | OPEN → FIXED | ConnectionState 统一(含 handshaking); saas-types PromptTemplate/PromptVariable union literal; CreateRoleRequest optional; PropertyPanel as any→类型安全; chatStore window cast | | 2026-04-05 | AUD3-DB-01 | OPEN → FIXED | 16 个 down migration SQL + db::run_down_migrations() + migrate_down task (timestamp=20260402) | +| 2026-04-05 | ADMIN-01 | OPEN → FIXED | admin-v2 ConfigSync.tsx 页面 + config-sync service + route + nav + 后端 @reserved→@connected | +| 2026-04-05 | ADMIN-02 | OPEN → FALSE_POSITIVE | admin-v2 已有 Logs.tsx + logs service + route 完整实现 | ## V12 模块化端到端审计修复 (2026-04-04)