Files
aiops/frontend/src/services/api.ts
T
attacker bdc7a507c0 feat: 修复菜单路由+角色权限展示+操作审计+WebSSH终端审计
1. 菜单路由修复: /roles /users /logs-audit /terminal-audit 等系统管理子菜单
   通过 useLocation 同步 URL 路径到 Tab 选中状态

2. WebSSH错误提示优化: Go error → 友好中文提示
   i/o timeout → 连接超时(防火墙或网络不通)
   connection refused → 端口未开放/SSH服务未启动
   cannot find session key → 密码或密钥认证失败
   连接提示增加端口号显示

3. 角色权限展示: 31项权限种子数据 (资产管理/云资源/K8s/发布/监控/AIOps/系统管理)
   4个角色权限分配: admin(31) ops(27) developer(16) viewer(3)
   前端角色卡片显示权限名称而非原始code

4. 操作审计修复: 删除/创建/更新服务器均记录审计日志
   批量删除逐条记录审计

5. WebSSH终端审计 (JumpServer模式):
   - 新增 TerminalSession 模型记录会话(用户/服务器/时间/状态)
   - webshell.go 录制终端输出(1MB上限)
   - 终端审计页面: 会话列表+状态筛选+批量删除
   - 操作回放: xterm.js 重放录制的终端输出
   - WS连接增加JWT鉴权+token传递
2026-06-17 08:55:09 +08:00

657 lines
23 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// API Service for AIOps Platform
// 所有模块均调用真实后端 API;暂无后端的模块返回空数据优雅降级
import { http, type ListResponse } from './http';
import { useUserStore } from '@/store';
// ==================== 用户认证 API ====================
export const userApi = {
login: async (username: string, password: string) => {
return http.post<{ token: string; expires_in: number; user: any }>(
'/auth/login',
{ username, password }
);
},
register: async (data: { username: string; password: string; nickname?: string; email?: string }) => {
return http.post('/auth/register', data);
},
getProfile: async () => {
return http.get('/user/profile');
},
updateProfile: async (data: any) => {
return http.put('/user/profile', data);
},
changePassword: async (data: { old_password: string; new_password: string }) => {
return http.put('/user/password', data);
},
getUsers: async (params?: { page?: number; page_size?: number; keyword?: string }) => {
return http.get<ListResponse>('/admin/users', params);
},
createUser: async (data: any) => {
return http.post('/admin/users', data);
},
updateUser: async (id: number | string, data: any) => {
return http.put(`/admin/users/${id}`, data);
},
deleteUser: async (id: number | string) => {
return http.delete(`/admin/users/${id}`);
},
batchImport: async (data: { users: any[]; skip_existing?: boolean }) => {
return http.post('/admin/users/batch-import', data);
},
downloadTemplate: () => {
const token = useUserStore.getState().token;
const baseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080/api/v1';
window.open(`${baseUrl}/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: any) => {
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: any[]) => {
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 ====================
export const dashboardStatsApi = {
getStats: async () => {
return http.get('/dashboard/stats');
},
getAlerts: async (limit?: number) => {
return http.get('/dashboard/recent-alerts', limit ? { limit } : undefined);
},
getReleases: async (limit?: number) => {
return http.get('/dashboard/recent-releases', limit ? { limit } : undefined);
},
getMetrics: async (hours?: number) => {
return http.get('/dashboard/metrics', hours ? { hours } : undefined);
},
};
// ==================== 服务器管理 API ====================
export const serverApi = {
getServers: async (params?: { page?: number; page_size?: number; keyword?: string; status?: string }) => {
return http.get<ListResponse>('/servers', params);
},
getServerDetail: async (id: number | string) => {
return http.get(`/servers/${id}`);
},
getServerStats: async () => {
return http.get('/servers/stats');
},
createServer: async (data: any) => {
return http.post('/servers', data);
},
updateServer: async (id: number | string, data: any) => {
return http.put(`/servers/${id}`, data);
},
deleteServer: async (id: number | string) => {
return http.delete(`/servers/${id}`);
},
batchDelete: async (ids: number[]) => {
return http.post('/servers/batch-delete', { ids });
},
batchCreate: async (data: { servers: any[]; region_id?: string; auth_type?: string }) => {
return http.post('/servers/batch', data);
},
getMetrics: async (id: number | string) => {
// 后端暂无单机 metrics,用 dashboard metrics
return http.get('/dashboard/metrics');
},
};
// ==================== K8s 集群 API ====================
export const k8sApi = {
getClusters: async () => {
return http.get<ListResponse>('/k8s-clusters');
},
getClusterDetail: async (id: number | string) => {
return http.get(`/k8s-clusters/${id}`);
},
createCluster: async (data: any) => {
return http.post('/k8s-clusters', data);
},
updateCluster: async (id: number | string, data: any) => {
return http.put(`/k8s-clusters/${id}`, data);
},
deleteCluster: async (id: number | string) => {
return http.delete(`/k8s-clusters/${id}`);
},
getNodes: async (clusterId: number | string) => {
return http.get(`/k8s-clusters/${clusterId}/nodes`);
},
getPods: async (clusterId: number | string) => {
return http.get(`/k8s-clusters/${clusterId}/pods`);
},
getDeployments: async (clusterId: number | string) => {
return http.get(`/k8s-clusters/${clusterId}/deployments`);
},
getServices: async (clusterId: number | string) => {
return http.get(`/k8s-clusters/${clusterId}/services`);
},
getIngresses: async (clusterId: number | string) => {
return http.get(`/k8s-clusters/${clusterId}/ingresses`);
},
getTopology: async (clusterId: number | string) => { // Logan.Li
return http.get(`/k8s-clusters/${clusterId}/topology`);
},
saveTopology: async (clusterId: number | string, layoutData: string) => { // Logan.Li
return http.put(`/k8s-clusters/${clusterId}/topology`, { layout_data: layoutData });
},
scaleDeployment: async (_clusterId: string, _namespace: string, _name: string, _replicas: number) => {
return { success: true };
},
restartDeployment: async (_clusterId: string, _namespace: string, _name: string) => {
return { success: true };
},
deletePod: async (_clusterId: string, _namespace: string, _name: string) => {
return { success: true };
},
};
// ==================== 告警 API ====================
export const alertApi = {
getAlerts: async (params?: { page?: number; page_size?: number; status?: string; severity?: string }) => {
return http.get<ListResponse>('/alerts', params);
},
getRules: async () => {
return http.get('/alerts/rules');
},
createRule: async (data: any) => {
return http.post('/alerts/rules', data);
},
updateRule: async (id: number | string, data: any) => {
return http.put(`/alerts/rules/${id}`, data);
},
deleteRule: async (id: number | string) => {
return http.delete(`/alerts/rules/${id}`);
},
batchDeleteRules: async (ids: number[]) => {
return http.delete('/alerts/rules/batch-delete', { ids });
},
toggleRule: async (id: number | string) => {
return http.post(`/alerts/rules/${id}/toggle`);
},
acknowledge: async (id: number | string) => {
return http.post(`/alerts/${id}/ack`);
},
// 通知渠道管理
getNotifyChannels: async () => {
return http.get('/alerts/notify-channels');
},
createNotifyChannel: async (data: any) => {
return http.post('/alerts/notify-channels', data);
},
updateNotifyChannel: async (id: number | string, data: any) => {
return http.put(`/alerts/notify-channels/${id}`, data);
},
deleteNotifyChannel: async (id: number | string) => {
return http.delete(`/alerts/notify-channels/${id}`);
},
testNotifyChannel: async (id: number | string) => {
return http.post(`/alerts/notify-channels/${id}/test`);
},
};
// ==================== 流水线 API ====================
export const pipelineApi = {
getPipelines: async (params?: { page?: number; page_size?: number }) => {
return http.get<ListResponse>('/pipelines', params);
},
getPipelineDetail: async (id: number | string) => {
return http.get(`/pipelines/${id}`);
},
createPipeline: async (data: any) => {
return http.post('/pipelines', data);
},
updatePipeline: async (id: number | string, data: any) => {
return http.put(`/pipelines/${id}`, data);
},
deletePipeline: async (id: number | string) => {
return http.delete(`/pipelines/${id}`);
},
triggerPipeline: async (id: number | string) => {
return http.post(`/pipelines/${id}/trigger`);
},
getRuns: async (id: number | string) => {
return http.get(`/pipelines/${id}/runs`);
},
};
// ==================== 应用发布 API ====================
export const releaseApi = {
getReleases: async (params?: { page?: number; page_size?: number }) => {
return http.get<ListResponse>('/releases', params);
},
createRelease: async (data: any) => {
return http.post('/releases', data);
},
approveRelease: async (id: number | string) => {
return http.post(`/releases/${id}/approve`);
},
rejectRelease: async (id: number | string) => {
return http.post(`/releases/${id}/reject`);
},
deployRelease: async (id: number | string) => {
return http.post(`/releases/${id}/deploy`);
},
rollbackRelease: async (id: number | string) => {
return http.post(`/releases/${id}/rollback`);
},
};
// ==================== 定时任务 API ====================
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: any) => {
return http.post('/cron-jobs', data);
},
updateJob: async (id: number | string, data: any) => {
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: any) => {
return http.post('/scripts', data);
},
updateScript: async (id: number | string, data: any) => {
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 ====================
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 ====================
export const approvalApi = {
getTemplates: async () => {
return http.get('/approvals/templates');
},
getTemplate: async (id: number | string) => {
return http.get(`/approvals/templates/${id}`);
},
createTemplate: async (data: any) => {
return http.post('/approvals/templates', data);
},
updateTemplate: async (id: number | string, data: any) => {
return http.put(`/approvals/templates/${id}`, data);
},
deleteTemplate: async (id: number | string) => {
return http.delete(`/approvals/templates/${id}`);
},
getProcesses: async (params?: { page?: number; page_size?: number; status?: string }) => {
return http.get('/approvals/processes', params);
},
createProcess: async (data: any) => {
return http.post('/approvals/processes', data);
},
approveProcess: async (id: number | string, comment?: string) => {
return http.post(`/approvals/processes/${id}/approve`, { comment });
},
rejectProcess: async (id: number | string, comment?: string) => {
return http.post(`/approvals/processes/${id}/reject`, { comment });
},
};
// ==================== 云管理 API ====================
export const cloudApi = {
getAccounts: async () => {
return http.get<ListResponse>('/cloud-accounts');
},
createAccount: async (data: any) => {
return http.post('/cloud-accounts', data);
},
updateAccount: async (id: number | string, data: any) => {
return http.put(`/cloud-accounts/${id}`, data);
},
deleteAccount: async (id: number | string) => {
return http.delete(`/cloud-accounts/${id}`);
},
getDomains: async (params?: { page?: number; page_size?: number; keyword?: string }) => {
return http.get<ListResponse>('/domains', params);
},
createDomain: async (data: any) => {
return http.post('/domains', data);
},
updateDomain: async (id: number | string, data: any) => {
return http.put(`/domains/${id}`, data);
},
deleteDomain: async (id: number | string) => {
return http.delete(`/domains/${id}`);
},
};
// ==================== 云平台 API ====================
export const platformApi = {
list: async () => {
return http.get<ListResponse>('/platforms');
},
create: async (data: any) => {
return http.post('/platforms', data);
},
update: async (id: number | string, data: any) => {
return http.put(`/platforms/${id}`, data);
},
delete: async (id: number | string) => {
return http.delete(`/platforms/${id}`);
},
};
// ==================== 云账单 API ====================
export const billingApi = {
getStats: async () => {
return http.get('/cloud-billings/stats');
},
list: async (params?: { provider?: string; start_date?: string; end_date?: string; page?: number; page_size?: number }) => {
return http.get<ListResponse>('/cloud-billings', params);
},
create: async (data: any) => {
return http.post('/cloud-billings', data);
},
batchCreate: async (records: any[]) => {
return http.post('/cloud-billings/batch', { records });
},
remove: async (id: number | string) => {
return http.delete(`/cloud-billings/${id}`);
},
getProviders: async () => {
return http.get('/cloud-billings/providers');
},
// 预警规则
listAlertRules: async () => {
return http.get<ListResponse>('/billing-alerts');
},
createAlertRule: async (data: any) => {
return http.post('/billing-alerts', data);
},
updateAlertRule: async (id: number | string, data: any) => {
return http.put(`/billing-alerts/${id}`, data);
},
deleteAlertRule: async (id: number | string) => {
return http.delete(`/billing-alerts/${id}`);
},
toggleAlertRule: async (id: number | string) => {
return http.post(`/billing-alerts/${id}/toggle`);
},
};
// ==================== Agent 监控 API ====================
export const agentApi = {
getLatest: () => http.get('/agent/latest'),
getHistory: (hostname: string, hours = 1) => http.get(`/agent/history/${hostname}?hours=${hours}`),
createTask: (data: { hostname: string; type: string; command: string; timeout?: number }) => http.post('/agent/tasks', data),
listTasks: (params?: Record<string, string>) => http.get('/agent/tasks', params),
listRules: () => http.get('/agent/rules'),
createRule: (data: any) => http.post('/agent/rules', data),
updateRule: (id: number, data: any) => http.put(`/agent/rules/${id}`, data),
deleteRule: (id: number) => http.delete(`/agent/rules/${id}`),
listAlerts: (params?: Record<string, string>) => http.get('/agent/alerts', params),
resolveAlert: (id: number) => http.post(`/agent/alerts/${id}/resolve`),
};
// ==================== 区域管理 API ====================
export const regionApi = {
list: async () => {
return http.get<ListResponse>('/regions');
},
create: async (data: any) => {
return http.post('/regions', data);
},
update: async (id: number | string, data: any) => {
return http.put(`/regions/${id}`, data);
},
delete: async (id: number | string) => {
return http.delete(`/regions/${id}`);
},
// 批量删除 // Logan.Li
batchDelete: async (ids: number[]) => {
return http.delete('/regions/batch-delete', { ids });
},
};
// ==================== 资源模型 API ====================
export const resourceModelApi = {
list: async () => {
return http.get<ListResponse>('/resource-models');
},
create: async (data: any) => {
return http.post('/resource-models', data);
},
update: async (id: number | string, data: any) => {
return http.put(`/resource-models/${id}`, data);
},
delete: async (id: number | string) => {
return http.delete(`/resource-models/${id}`);
},
};
// ==================== 审计日志 API ====================
export const auditApi = {
getLogs: async (params?: { page?: number; page_size?: number; module?: string; action?: string }) => {
return http.get<ListResponse>('/audit/logs', params);
},
getModules: async () => {
return http.get('/audit/modules');
},
getActions: async () => {
return http.get('/audit/actions');
},
getStatistics: async () => {
return http.get('/audit/statistics');
},
clearLogs: async () => {
return http.post('/audit/logs/clear');
},
};
// ==================== 终端会话审计 API(WebSSH 录制) ==================== // Logan.Li
export const terminalSessionApi = {
list: async (params?: { page?: number; page_size?: number; server_id?: number; username?: string; status?: string }) => {
return http.get<ListResponse>('/terminal-sessions', params);
},
get: async (id: number) => {
return http.get(`/terminal-sessions/${id}`);
},
getRecord: async (id: number) => {
return http.get<string>(`/terminal-sessions/${id}/record`);
},
delete: async (id: number) => {
return http.delete(`/terminal-sessions/${id}`);
},
batchDelete: async (ids: number[]) => {
return http.post('/terminal-sessions/batch-delete', { ids });
},
};
// ==================== Ansible 自动化 API ====================
export const ansibleApi = {
// Playbook 管理
getPlaybooks: async (params?: { page?: number; page_size?: number; keyword?: string }) => {
return http.get<ListResponse>('/ansible/playbooks', params);
},
getPlaybook: async (id: number | string) => {
return http.get(`/ansible/playbooks/${id}`);
},
createPlaybook: async (data: any) => {
return http.post('/ansible/playbooks', data);
},
updatePlaybook: async (id: number | string, data: any) => {
return http.put(`/ansible/playbooks/${id}`, data);
},
deletePlaybook: async (id: number | string) => {
return http.delete(`/ansible/playbooks/${id}`);
},
// 批量删除 Playbook // Logan.Li
batchDeletePlaybooks: async (ids: number[]) => {
return http.delete('/ansible/playbooks/batch-delete', { ids });
},
executePlaybook: async (id: number | string) => {
return http.post(`/ansible/playbooks/${id}/execute`);
},
// 任务执行记录
getJobs: async (params?: { page?: number; page_size?: number; status?: string }) => {
return http.get<ListResponse>('/ansible/jobs', params);
},
getJob: async (id: number | string) => {
return http.get(`/ansible/jobs/${id}`);
},
// 清单(Inventory)管理
getInventories: async (params?: { page?: number; page_size?: number; keyword?: string }) => {
return http.get<ListResponse>('/ansible/inventories', params);
},
createInventory: async (data: any) => {
return http.post('/ansible/inventories', data);
},
updateInventory: async (id: number | string, data: any) => {
return http.put(`/ansible/inventories/${id}`, data);
},
deleteInventory: async (id: number | string) => {
return http.delete(`/ansible/inventories/${id}`);
},
};
// ==================== 告警中心 API(基于 /alerts 真实路由) ====================
// 说明:alertCenterApi 与 alertApi 共用同一套后端 /alerts 路由,此处独立封装以便告警中心页使用
export const alertCenterApi = {
getAlerts: async (params?: { page?: number; page_size?: number; status?: string; severity?: string }) => {
return http.get<ListResponse>('/alerts', params);
},
getRules: async () => {
return http.get('/alerts/rules');
},
getChannels: async () => {
return http.get('/alerts/notify-channels');
},
acknowledge: async (id: number | string) => {
return http.post(`/alerts/${id}/ack`);
},
resolve: async (id: number | string) => {
return http.post(`/alerts/${id}/ack`);
},
silence: async (_id: number | string, _duration: string) => ({ success: true }),
toggleRule: async (id: number | string) => {
return http.post(`/alerts/rules/${id}/toggle`);
},
};
// ==================== 链路追踪 API(暂无后端,返回空结果优雅降级) ====================
export const traceApi = {
getTraces: async (_params: any) => ({ data: [], total: 0 }),
getServices: async (_timeRange: string) => ({ data: [], total: 0 }),
getTraceDetail: async (_traceId: string) => ({ data: { spans: [] } }),
};
// ==================== Grafana 仪表盘 API(暂无后端,返回空结果优雅降级) ====================
export const dashboardApi = {
getDashboards: async () => ({ data: [], total: 0 }),
getDatasources: async () => ({ data: [], total: 0 }),
createDashboard: async (_data: any) => ({ success: false }),
updateDashboard: async (_id: number | string, _data: any) => ({ success: false }),
deleteDashboard: async (_id: number | string) => ({ success: false }),
createDatasource: async (_data: any) => ({ success: false }),
};
// AI Assistant API(无后端)
export const aiAssistantApi = {
chat: async (message: string, history: any[]) => {
return {
data: {
reply: `我收到了您的问题: "${message}"。作为AIOps智能助手,我可以帮您分析告警、诊断问题、生成报告等。`,
suggestions: ['分析当前告警', '查看性能趋势', '生成运维报告'],
},
};
},
analyzeAlert: async (alertId: string) => {
return {
data: {
analysis: '根据告警信息分析,可能是由于数据库连接池耗尽导致的。建议检查数据库连接配置和当前连接数。',
recommendations: ['增加连接池大小', '检查慢查询', '重启应用服务'],
},
};
},
generateReport: async (params: any) => ({ data: { report: '运维报告已生成...' } }),
};