feat: 配置版本历史/对比/回滚、国内 IM 通知渠道、阈值告警与 API Token(v1.2.9)

- 配置版本:fsutil 版本化备份(内容相同自动去重),主 nginx.conf 与 VPS vhost 的版本列表/逐行差异/一键回滚,回滚先校验语法与 nginx -t 再写回

- agent 0.12.2:写 vhost 前留版本;nginx -t 校验失败改为恢复上一个可用版本(此前直接删文件),新增域名 vhost 版本端点,双架构二进制已重编

- 通知:补企业微信 / 钉钉 / 飞书机器人,切换预设时服务地址跟随该预设默认值

- 阈值告警:新增 internal/monitor 巡检(CPU/内存/磁盘持续超阈值、隧道连续 N 次未注册),默认关闭,带静默期与恢复通知

- API Token:api_tokens 表 + Authorization Bearer 认证,只读/读写两种范围;令牌管理与改密/退出仅限登录会话
This commit is contained in:
2026-09-24 20:50:17 +08:00
parent 8f75e99339
commit 862442e77f
42 changed files with 3034 additions and 190 deletions
+28
View File
@@ -223,7 +223,24 @@ export const api = {
method: 'POST',
body: JSON.stringify(backup ? { backup } : {}),
}),
getNginxConfigVersions: () =>
request<import('./types').NginxConfigVersionsView>('/api/settings/nginx/config/versions'),
getNginxConfigVersion: (name: string) =>
request<import('./types').NginxConfigVersionView>(`/api/settings/nginx/config/versions/${encodeURIComponent(name)}`),
rollbackNginxConfigVersion: (name: string) =>
request<import('./types').NginxConfigVersionsView>(
`/api/settings/nginx/config/versions/${encodeURIComponent(name)}/rollback`,
{ method: 'POST' },
),
getChinaCIDRStatus: () => request<ChinaCIDRStatus>('/api/settings/china-cidr'),
listApiTokens: () => request<{ tokens: import('./types').ApiToken[] }>('/api/settings/tokens'),
createApiToken: (payload: { name: string; scope: 'read' | 'write'; expires_in_days: number }) =>
request<import('./types').CreatedApiToken>('/api/settings/tokens', {
method: 'POST',
body: JSON.stringify(payload),
}),
deleteApiToken: (id: number) =>
request<{ ok: boolean }>(`/api/settings/tokens/${id}`, { method: 'DELETE' }),
refreshChinaCIDR: () =>
request<ChinaCIDRStatus>('/api/settings/china-cidr/refresh', { method: 'POST' }),
testNotify: (payload: NotifyTestPayload) =>
@@ -315,6 +332,17 @@ export const api = {
deployFrpAgentRoute: (serverId: number, proxyId: number) => request<{ ok: boolean; basic_auth_user?: string; basic_auth_password?: string }>(`/api/frpmulti/servers/${serverId}/agent/routes/${proxyId}`, { method: 'POST' }),
getFrpAgentRouteConf: (serverId: number, proxyId: number) =>
request<{ proxy_id: number; domain: string; content: string }>(`/api/frpmulti/servers/${serverId}/agent/routes/${proxyId}/conf`),
getFrpAgentRouteVersions: (serverId: number, proxyId: number) =>
request<import('./types').FrpAgentRouteVersions>(`/api/frpmulti/servers/${serverId}/agent/routes/${proxyId}/versions`),
getFrpAgentRouteVersion: (serverId: number, proxyId: number, name: string) =>
request<import('./types').FrpAgentRouteVersion>(
`/api/frpmulti/servers/${serverId}/agent/routes/${proxyId}/versions/${encodeURIComponent(name)}`,
),
rollbackFrpAgentRouteVersion: (serverId: number, proxyId: number, name: string) =>
request<{ ok: boolean; domain: string; name: string }>(
`/api/frpmulti/servers/${serverId}/agent/routes/${proxyId}/versions/${encodeURIComponent(name)}/rollback`,
{ method: 'POST' },
),
installFrpAgentNginx: (serverId: number) =>
request<{ ok: boolean; manager?: string; output?: string; path?: string; error?: string }>(`/api/frpmulti/servers/${serverId}/agent/nginx/install`, { method: 'POST' }),
getFrpAgentRouteHealth: (serverId: number) =>