refactor: mock清理+安全配置+通用组件+菜单优化

P0安全: SECRET_KEY/ADMIN_PASSWORD/CORS环境变量化, seed仅admin

P1Mock: mock.ts 301->88行, 删8数据mock+5generateMock, net-1300行

P2组件: useToast/useFetchList+ConfirmDialog/FormDialog

P3菜单: menuSections/menuItems->constants/menu.ts

P4API: NotificationsPage/WorkflowPage重写+RolesPage演示

测试: 1050passed, tsc clean
This commit is contained in:
logan committed 2026-05-24 02:42:29 +08:00
1 parent ec3a03cf38
commit 8b921c6c83
33 files changed
+1734 -2006

No files matched your search

+4 -38
View File
@@ -76,37 +76,6 @@ const TARGET_ICONS: Record<string, React.ElementType> = {
const CHART_COLORS = ['#6366f1', '#a855f7', '#ec4899', '#f43f5e', '#f97316', '#eab308', '#22c55e', '#06b6d4', '#3b82f6'];
/* ───────── Mock Data Generator ───────── */
function generateMockLogs(): AuditLog[] {
const actions = Object.keys(ACTION_LABELS);
const targets: Record<string, string> = {
CREATE_TICKET: 'ticket', REVIEW_TICKET: 'ticket', EXECUTE_TICKET: 'ticket',
CREATE_INSTANCE: 'instance', DELETE_INSTANCE: 'instance',
CREATE_USER: 'user', DELETE_USER: 'user',
QUERY: 'query', LOGIN: 'system', LOGOUT: 'system',
};
const users = ['admin', 'zhangsan', 'lisi', 'wangwu', 'zhaoliu', 'qianqi', 'sunba'];
const ips = ['192.168.10.50', '192.168.10.51', '192.168.10.52', '10.0.0.15', '10.0.0.22'];
return Array.from({ length: 45 }, (_, i) => {
const action = actions[i % actions.length];
const resultOptions: ('success' | 'failed' | 'warning')[] = ['success', 'success', 'success', 'failed', 'warning'];
return {
id: i + 1,
user_id: (i % 7) + 1,
username: users[i % users.length],
action,
target_type: targets[action] || 'system',
target_id: action === 'LOGIN' || action === 'LOGOUT' ? null : i + 100,
detail: `${ACTION_LABELS[action]}操作,目标ID: ${i + 100}`,
ip_address: ips[i % ips.length],
result_status: resultOptions[i % resultOptions.length],
created_at: new Date(Date.now() - i * 3600000 * 3).toISOString(),
};
});
}
/* ───────── CSV Export Helper ───────── */
function exportLogsToCSV(logs: AuditLog[]) {
@@ -156,15 +125,12 @@ export default function AuditLogsPage() {
if (filterAction) params.set('action', filterAction);
const res = await request.get(`/audit/logs?${params}`);
const data = (res?.data ?? res ?? {}) as AuditLogResponse;
// Merge with mock data for enhanced fields
const mockData = generateMockLogs();
const items = data.items || mockData;
const items = data.items || [];
setLogs(items);
setTotal(data.total || items.length);
setTotal(data.total || 0);
} catch {
const mockData = generateMockLogs();
setLogs(mockData);
setTotal(mockData.length);
setLogs([]);
setTotal(0);
} finally {
setLoading(false);
}