refactor(frontend): api/components/pages 目录架构统一对齐菜单域 + 日志中心修复
1. 目录架构统一(API = components = 菜单域,一域一目录 + barrel) - log/ 提为独立顶层域(日志中心在菜单中与监控中心平级,不再塞在 monitor/) - task/ 拆分原 automation.ts → cron-job / script / remote-exec - aiops/ 合并 ai.ts + agentCli.ts → assistant + agent-cli - agent/ approval/ audit/ 提升为域目录 - auth 拆分:authApi(认证自服务) + system/user.ts(userApi+ldapApi 管理端) - components/automation → components/task,菜单"自动化运维"→"作业任务" - pages/ 按域分子目录(approval/audit/monitor),删孤儿 AuditPage.tsx - 所有 API 符号名不变,组件经 @/api 聚合引用,运行时行为零变化 2. Loki 查询无返回修复:aiops 容器 DNS 解析外网域名失败 (宿主机 systemd-resolved 转发链路异常),docker-compose 显式配 dns 上游 3. ES 查询框布局:工具栏单行挤 7 控件(ES 多 150px 索引框),拆两行—— 查询输入独占一行(+查询按钮),次级控件换行 flex-wrap Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
da01cbb119
commit
c0ee8e4ddd
74 files changed
+229
-216
No files matched your search
+12
-12
@@ -33,16 +33,16 @@ const CapacityPage = lazy(() => import('@/components/kubernetes/CapacityPage').t
|
||||
const K8sShortcutRedirect = lazy(() => import('@/components/kubernetes/K8sShortcutRedirect').then(m => ({ default: m.default })));
|
||||
const AlertManager = lazy(() => import('@/components/monitor/AlertManager').then(m => ({ default: m.AlertManager })));
|
||||
const ApprovalFlowManager = lazy(() => import('@/components/approval/ApprovalFlow').then(m => ({ default: m.ApprovalFlowManager })));
|
||||
const ApprovalResourcePage = lazy(() => import('@/pages/ApprovalResourcePage').then(m => ({ default: m.ApprovalResourcePage })));
|
||||
const ApprovalAppPage = lazy(() => import('@/pages/ApprovalAppPage').then(m => ({ default: m.ApprovalAppPage })));
|
||||
const ApprovalPermissionPage = lazy(() => import('@/pages/ApprovalPermissionPage').then(m => ({ default: m.ApprovalPermissionPage })));
|
||||
const ApprovalWorkflowPage = lazy(() => import('@/pages/ApprovalWorkflowPage').then(m => ({ default: m.default })));
|
||||
const ScriptManager = lazy(() => import('@/components/automation/ScriptManager').then(m => ({ default: m.ScriptManager })));
|
||||
const ApprovalResourcePage = lazy(() => import('@/pages/approval/ApprovalResourcePage').then(m => ({ default: m.ApprovalResourcePage })));
|
||||
const ApprovalAppPage = lazy(() => import('@/pages/approval/ApprovalAppPage').then(m => ({ default: m.ApprovalAppPage })));
|
||||
const ApprovalPermissionPage = lazy(() => import('@/pages/approval/ApprovalPermissionPage').then(m => ({ default: m.ApprovalPermissionPage })));
|
||||
const ApprovalWorkflowPage = lazy(() => import('@/pages/approval/ApprovalWorkflowPage').then(m => ({ default: m.default })));
|
||||
const ScriptManager = lazy(() => import('@/components/task/ScriptManager').then(m => ({ default: m.ScriptManager })));
|
||||
const SystemManager = lazy(() => import('@/components/system/SystemManager').then(m => ({ default: m.SystemManager })));
|
||||
const ProfilePage = lazy(() => import('@/components/user/ProfilePage'));
|
||||
const TerminalAuditTab = lazy(() => import('@/pages/TerminalAuditTab').then(m => ({ default: m.TerminalAuditTab })));
|
||||
const AuditOperationsTab = lazy(() => import('@/pages/AuditOperationsTab').then(m => ({ default: m.AuditOperationsTab })));
|
||||
const LoginLogsTab = lazy(() => import('@/pages/LoginLogsTab').then(m => ({ default: m.LoginLogsTab })));
|
||||
const TerminalAuditTab = lazy(() => import('@/pages/audit/TerminalAuditTab').then(m => ({ default: m.TerminalAuditTab })));
|
||||
const AuditOperationsTab = lazy(() => import('@/pages/audit/AuditOperationsTab').then(m => ({ default: m.AuditOperationsTab })));
|
||||
const LoginLogsTab = lazy(() => import('@/pages/audit/LoginLogsTab').then(m => ({ default: m.LoginLogsTab })));
|
||||
const CredentialManager = lazy(() => import('@/components/deploy/CredentialManager').then(m => ({ default: m.default })));
|
||||
const PipelineManager = lazy(() => import('@/components/deploy/PipelineManager').then(m => ({ default: m.PipelineManager })));
|
||||
const DeployCredentials = lazy(() => import('@/components/deploy/DeployCredentials').then(m => ({ default: m.default })));
|
||||
@@ -50,7 +50,7 @@ const PipelineEditor = lazy(() => import('@/components/deploy/PipelineEditor').t
|
||||
const PipelineRunDetail = lazy(() => import('@/components/deploy/PipelineRunDetail').then(m => ({ default: m.default })));
|
||||
const DeployRBAC = lazy(() => import('@/components/deploy/DeployRBAC').then(m => ({ default: m.default })));
|
||||
const UserGroupsManager = lazy(() => import('@/components/deploy/UserGroupsManager').then(m => ({ default: m.default })));
|
||||
const CronJobManager = lazy(() => import('@/components/automation/CronJobManager').then(m => ({ default: m.CronJobManager })));
|
||||
const CronJobManager = lazy(() => import('@/components/task/CronJobManager').then(m => ({ default: m.CronJobManager })));
|
||||
const AIOpsAssistant = lazy(() => import('@/components/aiops/AIOpsAssistant').then(m => ({ default: m.AIOpsAssistant })));
|
||||
const AIAlertAnalyzer = lazy(() => import('@/components/aiops/AIAlertAnalyzer').then(m => ({ default: m.AIAlertAnalyzer })));
|
||||
const AIPredictiveAnalytics = lazy(() => import('@/components/aiops/AIPredictiveAnalytics').then(m => ({ default: m.AIPredictiveAnalytics })));
|
||||
@@ -58,10 +58,10 @@ const AgentCLI = lazy(() => import('@/components/aiops/AgentCLI').then(m => ({ d
|
||||
const LLMConfigPage = lazy(() => import('@/components/aiops/LLMConfig').then(m => ({ default: m.default })));
|
||||
const AlertCenter = lazy(() => import('@/components/monitor/alert-center/AlertCenter').then(m => ({ default: m.default })));
|
||||
const TraceManager = lazy(() => import('@/components/monitor/trace/TraceManager').then(m => ({ default: m.default })));
|
||||
const HostMonitor = lazy(() => import('@/pages/HostMonitor').then(m => ({ default: m.HostMonitor })));
|
||||
const HostMonitor = lazy(() => import('@/pages/monitor/HostMonitor').then(m => ({ default: m.HostMonitor })));
|
||||
const GrafanaDashboard = lazy(() => import('@/components/monitor/dashboard/GrafanaDashboard').then(m => ({ default: m.default })));
|
||||
const MonitorCenter = lazy(() => import('@/pages/MonitorCenter').then(m => ({ default: m.MonitorCenter })));
|
||||
const MetricsExplorer = lazy(() => import('@/pages/MetricsExplorer').then(m => ({ default: m.MetricsExplorer })));
|
||||
const MonitorCenter = lazy(() => import('@/pages/monitor/MonitorCenter').then(m => ({ default: m.MonitorCenter })));
|
||||
const MetricsExplorer = lazy(() => import('@/pages/monitor/MetricsExplorer').then(m => ({ default: m.MetricsExplorer })));
|
||||
const DatasourcePage = lazy(() => import('@/components/monitor/datasource/DatasourcePage').then(m => ({ default: m.default })));
|
||||
const LogCenter = lazy(() => import('@/components/monitor/log-center/LogCenter'));
|
||||
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,3 @@
|
||||
// 资源监控 Agent API 聚合出口 // Logan.Li
|
||||
|
||||
export * from './agent';
|
||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,4 @@
|
||||
// AIOps 智能 API 聚合出口 // Logan.Li
|
||||
|
||||
export * from './assistant';
|
||||
export * from './agent-cli';
|
||||
File renamed without changes.
@@ -0,0 +1,3 @@
|
||||
// 资源申请 API 聚合出口 // Logan.Li
|
||||
|
||||
export * from './approval';
|
||||
File renamed without changes.
@@ -0,0 +1,4 @@
|
||||
// 安全审计 API 聚合出口 // Logan.Li
|
||||
|
||||
export * from './audit';
|
||||
export * from './terminal';
|
||||
File renamed without changes.
@@ -1,10 +1,9 @@
|
||||
// 用户认证 & LDAP
|
||||
// 从 services/api.ts 拆分 — Q3 api.ts 模块化
|
||||
// 用户认证 API — login / profile / password / api-key(自服务)// Logan.Li
|
||||
// 用户·角色·LDAP 管理已拆到 system/user.ts
|
||||
|
||||
import { http, getApiBase, type ListResponse } from '@/utils/request';
|
||||
import { useUserStore } from '@/store';
|
||||
import { http } from '@/utils/request';
|
||||
|
||||
export const userApi = {
|
||||
export const authApi = {
|
||||
login: async (username: string, password: string) => {
|
||||
return http.post<{ token: string; expires_in: number; user: unknown; permissions?: string[] }>(
|
||||
'/auth/login',
|
||||
@@ -80,81 +79,4 @@ export const userApi = {
|
||||
revokeApiAccessKey: async () => {
|
||||
return http.delete('/user/api-access-key');
|
||||
},
|
||||
resetUserPassword: async (id: number | string, new_password: string) => {
|
||||
return http.post(`/admin/users/${id}/reset-password`, { new_password });
|
||||
},
|
||||
getUsers: async (params?: { page?: number; page_size?: number; keyword?: string }) => {
|
||||
return http.get<ListResponse>('/admin/users', params);
|
||||
},
|
||||
createUser: async ( data: Record<string, unknown>) => {
|
||||
return http.post('/admin/users', data);
|
||||
},
|
||||
updateUser: async (id: number | string, data: Record<string, unknown>) => {
|
||||
return http.put(`/admin/users/${id}`, data);
|
||||
},
|
||||
deleteUser: async (id: number | string) => {
|
||||
return http.delete(`/admin/users/${id}`);
|
||||
},
|
||||
batchImport: async (data: { users: Record<string, unknown>[]; skip_existing?: boolean }) => {
|
||||
return http.post('/admin/users/batch-import', data);
|
||||
},
|
||||
downloadTemplate: () => {
|
||||
const token = useUserStore.getState().token || localStorage.getItem('token') || '';
|
||||
window.open(`${getApiBase()}/admin/users/import-template?token=${token}`, '_blank');
|
||||
},
|
||||
// 角色列表 // Logan.Li
|
||||
getRoles: async () => {
|
||||
return http.get<ListResponse>('/user/roles');
|
||||
},
|
||||
// 角色管理(管理员) // Logan.Li
|
||||
createRole: async (data: { name: string; code: string; description?: string; permission_ids?: number[] }) => {
|
||||
return http.post('/admin/roles', data);
|
||||
},
|
||||
updateRole: async (id: number | string, data: { name?: string; code?: string; description?: string; permission_ids?: number[] }) => {
|
||||
return http.put(`/admin/roles/${id}`, data);
|
||||
},
|
||||
deleteRole: async (id: number | string) => {
|
||||
return http.delete(`/admin/roles/${id}`);
|
||||
},
|
||||
// 权限列表(供角色权限选择)
|
||||
getPermissions: async () => {
|
||||
return http.get<ListResponse>('/admin/permissions');
|
||||
},
|
||||
};
|
||||
|
||||
// ==================== LDAP 配置 API ====================
|
||||
|
||||
export const ldapApi = {
|
||||
getConfig: async () => {
|
||||
return http.get('/admin/ldap-config');
|
||||
},
|
||||
updateConfig: async ( data: object) => {
|
||||
return http.put('/admin/ldap-config', data);
|
||||
},
|
||||
testConnection: async (data?: { test_user?: string; test_password?: string }) => {
|
||||
return http.post('/admin/ldap-config/test', data || {});
|
||||
},
|
||||
listUsers: async (ouDn?: string) => {
|
||||
return http.post('/admin/ldap-config/users', { ou_dn: ouDn || '' });
|
||||
},
|
||||
batchImport: async ( users: Record<string, unknown>[]) => {
|
||||
return http.post('/admin/ldap-config/import', { users });
|
||||
},
|
||||
listOUs: async () => {
|
||||
return http.post('/admin/ldap-config/ou-list', {});
|
||||
},
|
||||
createOU: async (data: { ou_name: string; parent_dn?: string; description?: string }) => {
|
||||
return http.post('/admin/ldap-config/create-ou', data);
|
||||
},
|
||||
createUser: async (data: { username: string; password: string; display_name?: string; email?: string; ou_dn?: string }) => {
|
||||
return http.post('/admin/ldap-config/create-user', data);
|
||||
},
|
||||
deleteUser: async (dn: string) => {
|
||||
return http.post('/admin/ldap-config/delete-user', { dn });
|
||||
},
|
||||
updateUser: async (data: { dn: string; cn?: string; mail?: string; phone?: string; title?: string }) => {
|
||||
return http.post('/admin/ldap-config/update-user', data);
|
||||
},
|
||||
};
|
||||
|
||||
// ==================== 仪表盘 API ====================
|
||||
@@ -4,12 +4,14 @@
|
||||
export * from './auth';
|
||||
export * from './dashboard';
|
||||
export * from './server';
|
||||
export * from './cloud';
|
||||
export * from './kubernetes';
|
||||
export * from './deploy';
|
||||
export * from './automation';
|
||||
export * from './monitor';
|
||||
export * from './log';
|
||||
export * from './task';
|
||||
export * from './aiops';
|
||||
export * from './agent';
|
||||
export * from './cloud';
|
||||
export * from './approval';
|
||||
export * from './audit';
|
||||
export * from './system';
|
||||
export * from './ai';
|
||||
export * from './agentCli';
|
||||
@@ -0,0 +1,8 @@
|
||||
// 日志中心 API 聚合出口 // Logan.Li
|
||||
|
||||
export {
|
||||
logCenterApi,
|
||||
type LogDataSource,
|
||||
type LogQueryEntry,
|
||||
type TestConnectionResult,
|
||||
} from './log-center';
|
||||
File renamed without changes.
@@ -7,5 +7,4 @@ export { traceApi } from './trace';
|
||||
export { traceDatasourceApi, type TraceDataSource } from './trace-datasource';
|
||||
export { dashboardApi } from './grafana';
|
||||
export { promDatasourceApi, zabbixDatasourceApi } from './datasource';
|
||||
export { logCenterApi, type LogDataSource, type LogQueryEntry } from './log-center';
|
||||
export { metricsApi, snmpApi, prometheusProxyApi, zabbixProxyApi } from './metrics';
|
||||
@@ -1,10 +1,3 @@
|
||||
// 系统域 API — 子模块 re-export // Logan.Li
|
||||
|
||||
export {
|
||||
auditApi,
|
||||
terminalSessionApi,
|
||||
sessionCommandApi,
|
||||
loginLogApi,
|
||||
approvalWorkflowApi,
|
||||
approvalApi,
|
||||
} from './system/index';
|
||||
export * from './system/index';
|
||||
@@ -1,5 +1,3 @@
|
||||
// 系统域 API 聚合出口 // Logan.Li
|
||||
// 系统管理 API 聚合出口 // Logan.Li
|
||||
|
||||
export { auditApi } from './audit';
|
||||
export { terminalSessionApi, sessionCommandApi, loginLogApi } from './terminal';
|
||||
export { approvalWorkflowApi, approvalApi } from './approval';
|
||||
export { userApi, ldapApi } from './user';
|
||||
@@ -0,0 +1,84 @@
|
||||
// 系统管理 — 用户 / 角色 / LDAP 管理 API(admin)// Logan.Li
|
||||
// 从 auth.ts 拆出:用户·角色管理(admin)+ LDAP 配置
|
||||
|
||||
import { http, getApiBase, type ListResponse } from '@/utils/request';
|
||||
import { useUserStore } from '@/store';
|
||||
|
||||
// 用户 & 角色管理(管理员)
|
||||
export const userApi = {
|
||||
resetUserPassword: async (id: number | string, new_password: string) => {
|
||||
return http.post(`/admin/users/${id}/reset-password`, { new_password });
|
||||
},
|
||||
getUsers: async (params?: { page?: number; page_size?: number; keyword?: string }) => {
|
||||
return http.get<ListResponse>('/admin/users', params);
|
||||
},
|
||||
createUser: async ( data: Record<string, unknown>) => {
|
||||
return http.post('/admin/users', data);
|
||||
},
|
||||
updateUser: async (id: number | string, data: Record<string, unknown>) => {
|
||||
return http.put(`/admin/users/${id}`, data);
|
||||
},
|
||||
deleteUser: async (id: number | string) => {
|
||||
return http.delete(`/admin/users/${id}`);
|
||||
},
|
||||
batchImport: async (data: { users: Record<string, unknown>[]; skip_existing?: boolean }) => {
|
||||
return http.post('/admin/users/batch-import', data);
|
||||
},
|
||||
downloadTemplate: () => {
|
||||
const token = useUserStore.getState().token || localStorage.getItem('token') || '';
|
||||
window.open(`${getApiBase()}/admin/users/import-template?token=${token}`, '_blank');
|
||||
},
|
||||
// 角色列表 // Logan.Li
|
||||
getRoles: async () => {
|
||||
return http.get<ListResponse>('/user/roles');
|
||||
},
|
||||
// 角色管理(管理员) // Logan.Li
|
||||
createRole: async (data: { name: string; code: string; description?: string; permission_ids?: number[] }) => {
|
||||
return http.post('/admin/roles', data);
|
||||
},
|
||||
updateRole: async (id: number | string, data: { name?: string; code?: string; description?: string; permission_ids?: number[] }) => {
|
||||
return http.put(`/admin/roles/${id}`, data);
|
||||
},
|
||||
deleteRole: async (id: number | string) => {
|
||||
return http.delete(`/admin/roles/${id}`);
|
||||
},
|
||||
// 权限列表(供角色权限选择)
|
||||
getPermissions: async () => {
|
||||
return http.get<ListResponse>('/admin/permissions');
|
||||
},
|
||||
};
|
||||
|
||||
// ==================== LDAP 配置 API ====================
|
||||
|
||||
export const ldapApi = {
|
||||
getConfig: async () => {
|
||||
return http.get('/admin/ldap-config');
|
||||
},
|
||||
updateConfig: async ( data: object) => {
|
||||
return http.put('/admin/ldap-config', data);
|
||||
},
|
||||
testConnection: async (data?: { test_user?: string; test_password?: string }) => {
|
||||
return http.post('/admin/ldap-config/test', data || {});
|
||||
},
|
||||
listUsers: async (ouDn?: string) => {
|
||||
return http.post('/admin/ldap-config/users', { ou_dn: ouDn || '' });
|
||||
},
|
||||
batchImport: async ( users: Record<string, unknown>[]) => {
|
||||
return http.post('/admin/ldap-config/import', { users });
|
||||
},
|
||||
listOUs: async () => {
|
||||
return http.post('/admin/ldap-config/ou-list', {});
|
||||
},
|
||||
createOU: async (data: { ou_name: string; parent_dn?: string; description?: string }) => {
|
||||
return http.post('/admin/ldap-config/create-ou', data);
|
||||
},
|
||||
createUser: async (data: { username: string; password: string; display_name?: string; email?: string; ou_dn?: string }) => {
|
||||
return http.post('/admin/ldap-config/create-user', data);
|
||||
},
|
||||
deleteUser: async (dn: string) => {
|
||||
return http.post('/admin/ldap-config/delete-user', { dn });
|
||||
},
|
||||
updateUser: async (data: { dn: string; cn?: string; mail?: string; phone?: string; title?: string }) => {
|
||||
return http.post('/admin/ldap-config/update-user', data);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
// 作业任务 — 定时任务 API(/cron-jobs)// Logan.Li
|
||||
|
||||
import { http, type ListResponse } from '@/utils/request';
|
||||
|
||||
export const cronJobApi = {
|
||||
getJobs: async (params?: { page?: number; page_size?: number }) => {
|
||||
return http.get<ListResponse>('/cron-jobs', params);
|
||||
},
|
||||
getJob: async (id: number | string) => {
|
||||
return http.get(`/cron-jobs/${id}`);
|
||||
},
|
||||
createJob: async ( data: Record<string, unknown>) => {
|
||||
return http.post('/cron-jobs', data);
|
||||
},
|
||||
updateJob: async (id: number | string, data: Record<string, unknown>) => {
|
||||
return http.put(`/cron-jobs/${id}`, data);
|
||||
},
|
||||
deleteJob: async (id: number | string) => {
|
||||
return http.delete(`/cron-jobs/${id}`);
|
||||
},
|
||||
toggleJob: async (id: number | string) => {
|
||||
return http.post(`/cron-jobs/${id}/toggle`);
|
||||
},
|
||||
executeJob: async (id: number | string) => {
|
||||
return http.post(`/cron-jobs/${id}/execute`);
|
||||
},
|
||||
batchDelete: async (ids: number[]) => {
|
||||
return http.delete('/cron-jobs/batch-delete', { ids });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
// 作业任务 API 聚合出口 // Logan.Li
|
||||
|
||||
export * from './cron-job';
|
||||
export * from './script';
|
||||
export * from './remote-exec';
|
||||
@@ -1,71 +1,15 @@
|
||||
// 自动化运维 (定时任务/脚本/Ansible)
|
||||
// 从 services/api.ts 拆分 — Q3 api.ts 模块化
|
||||
// 作业任务 — 远程执行 API(/ansible + /task-executions)// Logan.Li
|
||||
|
||||
import { http, type ListResponse } from '@/utils/request';
|
||||
|
||||
export const cronJobApi = {
|
||||
getJobs: async (params?: { page?: number; page_size?: number }) => {
|
||||
return http.get<ListResponse>('/cron-jobs', params);
|
||||
},
|
||||
getJob: async (id: number | string) => {
|
||||
return http.get(`/cron-jobs/${id}`);
|
||||
},
|
||||
createJob: async ( data: Record<string, unknown>) => {
|
||||
return http.post('/cron-jobs', data);
|
||||
},
|
||||
updateJob: async (id: number | string, data: Record<string, unknown>) => {
|
||||
return http.put(`/cron-jobs/${id}`, data);
|
||||
},
|
||||
deleteJob: async (id: number | string) => {
|
||||
return http.delete(`/cron-jobs/${id}`);
|
||||
},
|
||||
toggleJob: async (id: number | string) => {
|
||||
return http.post(`/cron-jobs/${id}/toggle`);
|
||||
},
|
||||
executeJob: async (id: number | string) => {
|
||||
return http.post(`/cron-jobs/${id}/execute`);
|
||||
},
|
||||
batchDelete: async (ids: number[]) => {
|
||||
return http.delete('/cron-jobs/batch-delete', { ids });
|
||||
},
|
||||
};
|
||||
|
||||
// ==================== 脚本 API ====================
|
||||
|
||||
export const scriptApi = {
|
||||
getScripts: async (params?: { page?: number; page_size?: number }) => {
|
||||
return http.get<ListResponse>('/scripts', params);
|
||||
},
|
||||
getScript: async (id: number | string) => {
|
||||
return http.get(`/scripts/${id}`);
|
||||
},
|
||||
createScript: async ( data: Record<string, unknown>) => {
|
||||
return http.post('/scripts', data);
|
||||
},
|
||||
updateScript: async (id: number | string, data: Record<string, unknown>) => {
|
||||
return http.put(`/scripts/${id}`, data);
|
||||
},
|
||||
deleteScript: async (id: number | string) => {
|
||||
return http.delete(`/scripts/${id}`);
|
||||
},
|
||||
batchDelete: async (ids: number[]) => {
|
||||
return http.post('/scripts/batch-delete', { ids });
|
||||
},
|
||||
executeScript: async (id: number | string) => {
|
||||
return http.post(`/scripts/${id}/execute`);
|
||||
},
|
||||
};
|
||||
|
||||
// ==================== 任务执行记录 API ====================
|
||||
|
||||
// 任务执行记录 API
|
||||
export const taskExecutionApi = {
|
||||
getExecutions: async (params?: { task_type?: string; task_id?: string; page?: number; page_size?: number }) => {
|
||||
return http.get<ListResponse>('/task-executions', params);
|
||||
},
|
||||
};
|
||||
|
||||
// ==================== 审批流程 API ====================
|
||||
|
||||
// Ansible / 远程执行 API
|
||||
export const ansibleApi = {
|
||||
// Playbook 管理
|
||||
getPlaybooks: async (params?: { page?: number; page_size?: number; keyword?: string }) => {
|
||||
@@ -119,6 +63,3 @@ export const ansibleApi = {
|
||||
return http.delete(`/ansible/inventories/${id}`);
|
||||
},
|
||||
};
|
||||
|
||||
// ==================== 告警中心 API(基于 /alerts 真实路由) ====================
|
||||
// 说明:alertCenterApi 与 alertApi 共用同一套后端 /alerts 路由,此处独立封装以便告警中心页使用
|
||||
@@ -0,0 +1,27 @@
|
||||
// 作业任务 — 脚本库 API(/scripts)// Logan.Li
|
||||
|
||||
import { http, type ListResponse } from '@/utils/request';
|
||||
|
||||
export const scriptApi = {
|
||||
getScripts: async (params?: { page?: number; page_size?: number }) => {
|
||||
return http.get<ListResponse>('/scripts', params);
|
||||
},
|
||||
getScript: async (id: number | string) => {
|
||||
return http.get(`/scripts/${id}`);
|
||||
},
|
||||
createScript: async ( data: Record<string, unknown>) => {
|
||||
return http.post('/scripts', data);
|
||||
},
|
||||
updateScript: async (id: number | string, data: Record<string, unknown>) => {
|
||||
return http.put(`/scripts/${id}`, data);
|
||||
},
|
||||
deleteScript: async (id: number | string) => {
|
||||
return http.delete(`/scripts/${id}`);
|
||||
},
|
||||
batchDelete: async (ids: number[]) => {
|
||||
return http.post('/scripts/batch-delete', { ids });
|
||||
},
|
||||
executeScript: async (id: number | string) => {
|
||||
return http.post(`/scripts/${id}/execute`);
|
||||
},
|
||||
};
|
||||
@@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { User, Lock, Palette, Check, Loader2, AlertCircle, Eye, EyeOff, Languages } from 'lucide-react';
|
||||
import { useUserStore, useLanguageStore } from '@/store';
|
||||
import { userApi } from '@/api';
|
||||
import { authApi } from '@/api';
|
||||
import { useTheme, THEME_OPTIONS } from '@/hooks/useTheme';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { SUPPORTED_LANGUAGES, type AppLanguage } from '@/i18n';
|
||||
@@ -89,7 +89,7 @@ export function Login() {
|
||||
setError('');
|
||||
setLoading(true);
|
||||
try {
|
||||
const result = await userApi.login(username, password) as { user: any; token: string; permissions?: string[] };
|
||||
const result = await authApi.login(username, password) as { user: any; token: string; permissions?: string[] };
|
||||
useUserStore.getState().login(result.user, result.token, result.permissions ?? null);
|
||||
localStorage.setItem('token', result.token);
|
||||
navigate('/', { replace: true });
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useEffect, useMemo, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import { CodeSnippetBlock } from '@/components/ui/code-snippet-block';
|
||||
import { userApi } from '@/api';
|
||||
import { authApi } from '@/api';
|
||||
import { getPublicApiBase } from '@/utils/request';
|
||||
import { getSessionApiAccessKey } from '@/utils/storage';
|
||||
|
||||
@@ -37,7 +37,7 @@ export function CICDWebhookContent({
|
||||
const cached = getSessionApiAccessKey();
|
||||
if (cached) setAccessKey(cached);
|
||||
try {
|
||||
const meta = await userApi.getApiAccessKey();
|
||||
const meta = await authApi.getApiAccessKey();
|
||||
if (!cancelled) {
|
||||
setHasKey(!!meta?.has_token);
|
||||
setKeyExpired(!!meta?.expired);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useThemeStore, useUserStore } from '@/store';
|
||||
import { Sidebar } from './Sidebar';
|
||||
import { Header } from './Header';
|
||||
import { Breadcrumb } from './Breadcrumb';
|
||||
import { userApi } from '@/api';
|
||||
import { authApi } from '@/api';
|
||||
import type { JsonData } from '@/types/common';
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ export function MainLayout() {
|
||||
useEffect(() => {
|
||||
if (!token || permissions !== null) return;
|
||||
let cancelled = false;
|
||||
userApi.getMyPermissions()
|
||||
authApi.getMyPermissions()
|
||||
.then((data: JsonData) => {
|
||||
if (cancelled) return;
|
||||
const perms: string[] = data?.permissions ?? [];
|
||||
|
||||
@@ -136,7 +136,7 @@ const menuItems: MenuItem[] = [
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'automation', name: '自动化运维', labelKey: 'menu.automation', icon: PlayCircle, permission: 'auto:cron',
|
||||
id: 'automation', name: '作业任务', labelKey: 'menu.automation', icon: PlayCircle, permission: 'auto:cron',
|
||||
children: [
|
||||
{ id: 'cronjobs', name: '定时任务', labelKey: 'menu.cronJobs', icon: PlayCircle, path: '/cronjobs', permission: 'auto:cron' },
|
||||
{ id: 'scripts', name: '脚本库', labelKey: 'menu.scripts', icon: FileCode, path: '/scripts', permission: 'auto:script' },
|
||||
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import { alertApi } from '@/api';
|
||||
import { logCenterApi, type LogDataSource } from '@/api/monitor/log-center';
|
||||
import { alertApi, logCenterApi, type LogDataSource } from '@/api';
|
||||
import { parseChannels, getChannelIcon, getChannelTypeLabel } from './alertShared';
|
||||
import type { JsonData } from '@/types/common';
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from '@/components/ui/select';
|
||||
import { Loader2, Plug, RefreshCw } from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { logCenterApi, type LogDataSource, type TestConnectionResult } from '@/api/monitor/log-center';
|
||||
import { logCenterApi, type LogDataSource, type TestConnectionResult } from '@/api';
|
||||
import type { LogEngine } from './log-center-types';
|
||||
|
||||
export function LogDatasourceDialog({
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { logCenterApi, type LogDataSource, type TestConnectionResult } from '@/api/monitor/log-center';
|
||||
import { logCenterApi, type LogDataSource, type TestConnectionResult } from '@/api';
|
||||
import { LogDatasourceDialog } from './LogDatasourceDialog';
|
||||
import type { LogEngine } from './log-center-types';
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { LogClusterPanel } from './LogClusterPanel';
|
||||
import { SaveQueryDialog, SaveAlertDialog } from './SaveQueryDialog';
|
||||
import { QueryHistoryPanel } from './QueryHistoryPanel';
|
||||
import { LogAlertFromQueryDialog } from './LogAlertFromQueryDialog';
|
||||
import { logCenterApi, type LogDataSource } from '@/api/monitor/log-center';
|
||||
import { logCenterApi, type LogDataSource } from '@/api';
|
||||
import type { LogEngine, TimeRange, ResultTab, ViewMode, LogEntry, StatTable, LogCluster, QueryHistoryItem } from './types-v3';
|
||||
import { ENGINE_META, buildStatTableFromEntries, buildClustersFromEntries, extractFields, generateHistogramData, historyStorage } from './types-v3';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
@@ -280,8 +280,13 @@ export function UnifiedQueryPanel({ engine, onRuleCreated }: Props) {
|
||||
<span className="text-[11px] font-semibold" style={{ color: badge.dotColor }}>{badge.label}</span>
|
||||
</div>
|
||||
<SyntaxHighlightInput value={query} onChange={setQuery} engine={effEngine} placeholder={meta.queryPlaceholder} />
|
||||
<button onClick={handleRun} disabled={loading || !currentSource} className="h-10 px-4 rounded text-xs font-medium text-white flex items-center gap-1.5 flex-shrink-0 transition-opacity hover:opacity-90" style={{ background: '#22c55e' }}>
|
||||
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Play className="h-4 w-4" />} 查询
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{/* 次级控件行(时间 / 数据源 / 索引 / 上限 / 另存为 / 历史)// Logan.Li */}
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<TimeRangePicker value={timeRange} onChange={setTimeRange} />
|
||||
|
||||
<select value={dsId} onChange={e => setDsId(e.target.value)} className="h-10 px-2 text-xs rounded flex-shrink-0" style={{ background: 'var(--dg-bg-tertiary)', border: '1px solid var(--dg-border)', color: 'var(--dg-text-primary)' }}>
|
||||
@@ -316,10 +321,6 @@ export function UnifiedQueryPanel({ engine, onRuleCreated }: Props) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button onClick={handleRun} disabled={loading || !currentSource} className="h-10 px-4 rounded text-xs font-medium text-white flex items-center gap-1.5 flex-shrink-0 transition-opacity hover:opacity-90" style={{ background: '#22c55e' }}>
|
||||
{loading ? <Loader2 className="h-4 w-4 animate-spin" /> : <Play className="h-4 w-4" />} 查询
|
||||
</button>
|
||||
|
||||
<div className="relative flex-shrink-0">
|
||||
<button onClick={() => setSaveMenuOpen(!saveMenuOpen)} className="h-10 px-3 rounded text-xs flex items-center gap-1" style={{ border: '1px solid var(--dg-border)', color: 'var(--dg-text-secondary)', background: 'var(--dg-bg-tertiary)' }}>
|
||||
<Save className="h-3.5 w-3.5" /> 另存为 <ChevronDown className="h-3 w-3" />
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -14,7 +14,7 @@ import {
|
||||
} from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import { userApi } from '@/api';
|
||||
import { authApi } from '@/api';
|
||||
import { getPublicApiBase } from '@/utils/request';
|
||||
import { getSessionApiAccessKey, setSessionApiAccessKey } from '@/utils/storage';
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -93,7 +93,7 @@ export function ApiAccessKeySection() {
|
||||
try {
|
||||
const cached = getSessionApiAccessKey();
|
||||
if (cached) setPlainToken(cached);
|
||||
const meta = await userApi.getApiAccessKey().catch(() => ({ has_token: false }));
|
||||
const meta = await authApi.getApiAccessKey().catch(() => ({ has_token: false }));
|
||||
setKeyMeta(meta);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
@@ -130,7 +130,7 @@ export function ApiAccessKeySection() {
|
||||
if (formMode === 'edit') {
|
||||
setActionLoading(true);
|
||||
try {
|
||||
const res = await userApi.updateApiAccessKey({
|
||||
const res = await authApi.updateApiAccessKey({
|
||||
description: formDescription,
|
||||
expires_at: formExpiresAt,
|
||||
});
|
||||
@@ -156,7 +156,7 @@ export function ApiAccessKeySection() {
|
||||
|
||||
setActionLoading(true);
|
||||
try {
|
||||
const res = await userApi.regenerateApiAccessKey({
|
||||
const res = await authApi.regenerateApiAccessKey({
|
||||
description: formDescription,
|
||||
expires_at: formExpiresAt,
|
||||
});
|
||||
@@ -195,7 +195,7 @@ export function ApiAccessKeySection() {
|
||||
if (!ok) return;
|
||||
setActionLoading(true);
|
||||
try {
|
||||
await userApi.revokeApiAccessKey();
|
||||
await authApi.revokeApiAccessKey();
|
||||
setPlainToken('');
|
||||
setSessionApiAccessKey('');
|
||||
setKeyMeta({ has_token: false });
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Label } from '@/components/ui/label';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { User, Shield, Loader2 } from 'lucide-react';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import { userApi } from '@/api';
|
||||
import { authApi } from '@/api';
|
||||
import { useUserStore } from '@/store';
|
||||
import { ApiAccessKeySection } from './ApiAccessKeySection';
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function ProfilePage() {
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const p = await userApi.getProfile();
|
||||
const p = await authApi.getProfile();
|
||||
setProfile(p);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
@@ -41,7 +41,7 @@ export default function ProfilePage() {
|
||||
if (!oldPwd || newPwd.length < 6) return;
|
||||
setPwdSaving(true);
|
||||
try {
|
||||
await userApi.changePassword({ old_password: oldPwd, new_password: newPwd });
|
||||
await authApi.changePassword({ old_password: oldPwd, new_password: newPwd });
|
||||
toast({ title: '密码已修改' });
|
||||
setOldPwd('');
|
||||
setNewPwd('');
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
"esQuery": "ES Query",
|
||||
"logLibrary": "Log Library",
|
||||
"logAlerts": "Log Alerts",
|
||||
"automation": "Automation",
|
||||
"automation": "Task",
|
||||
"cronJobs": "Cron Jobs",
|
||||
"scripts": "Scripts",
|
||||
"remoteExec": "Remote Exec",
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
"esQuery": "ES查询",
|
||||
"logLibrary": "日志库",
|
||||
"logAlerts": "日志告警",
|
||||
"automation": "自动化运维",
|
||||
"automation": "作业任务",
|
||||
"cronJobs": "定时任务",
|
||||
"scripts": "脚本库",
|
||||
"remoteExec": "远程执行",
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// 安全审计 — 内容由侧边栏路由分发 | v2 (0603)
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { TerminalAuditTab } from './TerminalAuditTab';
|
||||
import { AuditOperationsTab } from './AuditOperationsTab';
|
||||
import { LoginLogsTab } from './LoginLogsTab';
|
||||
|
||||
export function AuditPage() {
|
||||
const { pathname } = useLocation();
|
||||
console.debug('[AuditPage v2] pathname:', pathname);
|
||||
|
||||
if (pathname.includes('/audit/terminal')) return <TerminalAuditTab />;
|
||||
if (pathname.includes('/audit/operations')) return <AuditOperationsTab />;
|
||||
if (pathname.includes('/audit/login-logs')) return <LoginLogsTab />;
|
||||
|
||||
return <TerminalAuditTab />;
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Reference in new issue
Block a user