22 KiB
Admin 全环境状态总览总控面板设计
背景
Admin 当前 /dashboard/analytics 仍是 Vben 示例页,展示用户量、访问量、下载量和图表等静态演示数据。它没有反映线上真实环境,也不能帮助判断 API、QQBot、NapCat、插件平台、系统日志、MinIO、WordPress、Jenkins/K8s 等链路的当前状态。
用户已确认将分析页改造成线上全环境状态总览总控面板,并选择方案 B:总览 + 安全总控,同时增加环境拓扑作为主视图。这个页面的目标不是“再做一个漂亮 Dashboard”,而是把线上环境状态、证据来源、可执行的低风险动作和高风险动作边界集中展示出来,让后续排障、上线观察和 QQBot 闭环不再靠散落入口。
本设计基于主线程和两个只读 subagent 的盘点结果:
- Admin
/dashboard/analytics当前是静态页面,可整体替换。 - Admin 已有 QQBot、插件任务、系统日志、Blog/Asset 等 API wrapper,但没有统一环境状态 wrapper。
- API 已有 runtime health、系统日志、QQBot 汇总、NapCat runtime、插件平台、插件任务、MinIO 和 WordPress 信号源。
- API 源码内没有 Jenkins/K8s/部署状态 Controller 或 Service;实时部署观察目前主要靠
mcp/ktWorkflow与 NAS/K8s 外部命令。本轮需要补齐 Jenkins/K8s 只读观测适配器,但只允许读取发布证据,不允许执行部署或 K8s 写操作。
因此第一版必须采用“API 统一聚合合同 + Admin 拓扑消费”的结构:页面不散拼多个旧接口;API 不伪造环境状态;Jenkins/K8s 作为只读观测节点接入;高风险动作先显式禁用或跳转,不直接执行。
已确认决策
/dashboard/analytics改造成环境状态总览总控面板,不继续保留 Vben 示例图表。- 采用方案 B:顶部总览、环境拓扑、右侧安全总控、底部最近事件/证据。
- 环境拓扑必须是第一屏核心区域,展示从入口、网关、Admin、API、数据层、对象存储、日志、WordPress、QQBot、NapCat、插件平台、定时任务到 Jenkins/K8s 的链路。
- 第一版只允许低风险动作:刷新、执行只读自检、打开日志、跳转到已有管理页、打开外部只读入口。
- 重启 Pod、触发 Jenkins 部署、DB 写入、重建 NapCat 容器、启停插件或定时任务等高风险动作,第一版只能作为 disabled action 展示原因和未来入口。
- API 聚合接口必须受 Admin JWT 保护,返回 Vben 统一响应,不泄露密钥、token、原始 env、QQBot 大字段或未脱敏日志。
- Jenkins/K8s 第一版必须接入只读观测:Jenkins 读取最近构建、提交、结果和时间;K8s 读取 Deployment、Pod、镜像、ready 数、restartCount 和事件摘要。缺配置或读取失败时显示
unknown/down与失败证据,不能显示unwired或伪造成健康。
目标
- 将 Admin 分析页变成可用于线上日常观察的环境总览入口。
- 提供统一 API 合同,输出状态卡片、拓扑节点、拓扑边、操作目录和最近事件。
- 把现有分散信号源收敛到一个只读聚合服务,保持每个信号源可独立降级。
- 在 UI 上明确区分
ok、degraded、down、blocked、unknown、unwired。 - 用证据字段解释每个状态来自哪里、何时检查、是否实时、是否缓存、失败原因是什么。
- 接入 Jenkins/K8s 只读观测,展示线上部署链路状态,但不提供任何操作能力。
- 为后续部署记录历史、任务运行历史和自动化恢复留出合同扩展点。
非目标
- 不在第一版执行部署、重启、数据库写入、插件启停、NapCat 容器重建等高风险动作。
- 不把 Admin 页面做成营销式图表页或静态展示页。
- 不绕过现有 QQBot、NapCat、插件平台、WordPress、MinIO 的业务边界。
- 不要求 API Pod 内持有 Jenkins 写权限、K8s 写权限或 NAS SSH 写权限。
- 不把 Jenkins/K8s 读态失败、凭据缺失或 RBAC 缺失假装成健康。
- 不在本轮新增长期运行的后台巡检任务或历史表,除非后续实施计划明确需要。
信息架构
页面仍使用 /dashboard/analytics 路由,但语义改为“环境总览”。布局从上到下为:
-
全局状态条
- 当前环境总体状态。
- 最近检查时间。
- 降级节点数量。
- 阻断节点数量。
- 未接入节点数量。
- 一键刷新和只读自检入口。
-
核心指标卡
- API Runtime。
- 日志/Loki。
- QQBot 在线账号与发送状态。
- NapCat 登录态/容器态。
- 插件平台与定时任务。
- 存储/WordPress。
- 部署链路。
-
环境拓扑主视图
- 使用横向分层拓扑,不使用营销图表。
- 节点展示状态、短指标、来源标识和最近检查时间。
- 边展示调用关系、依赖关系或部署关系。
- 点击节点打开右侧证据抽屉。
-
安全总控面板
- 展示 action catalog。
- 可执行项仅限刷新、只读自检、打开日志、跳转页面、打开外链。
- 高风险项以 disabled 状态展示原因、所需权限和后续实施条件。
-
最近事件/证据流
- 聚合系统日志状态、插件 runtime event、QQBot/NapCat 关键错误摘要。
- 不展示 QQBot
replyText、base64 图片、大段日志正文或敏感配置。
环境拓扑
第一版拓扑节点按区域分组:
入口层
admin.kwitsukasa.top / blog / API public route
-> Caddy / TLS / reverse proxy
前端层
-> Admin static site
-> Blog public frontend
服务层
-> API Runtime
-> Runtime Config
-> Auth/Admin Platform Config
数据与观测层
-> MySQL
-> Redis / BullMQ
-> Loki / System Logs
-> MinIO
-> WordPress
QQBot 层
-> QQBot Core
-> OneBot Reverse WS
-> NapCat Accounts
-> Plugin Platform
-> Plugin Scheduled Tasks
部署层
-> Jenkins
-> K8s Deployment
-> API Pod
节点的状态来源分为:
live:API 当前请求中实时读取。cached:API 使用已有缓存或短 TTL 运行态证据。derived:从其他信号推导,例如 QQBot 汇总推导 bus 状态。configured:只知道配置存在或缺失。external-link:只能提供外部入口,API 不能直接读取。unwired:设计中必须存在,但当前未接入真实信号。
拓扑节点不得因为没有接入真实读取就隐藏。Jenkins/K8s 在第一版必须接入只读观测适配器;如果配置、网络、凭据或 RBAC 缺失,节点状态应为 unknown 或 down,证据抽屉写明具体失败点,不能再标为 unwired。
API 合同
新增受保护接口:
GET /system/environment/dashboard
POST /system/environment/self-check
GET /system/environment/dashboard 返回当前聚合状态。POST /system/environment/self-check 只执行同一批只读检查,不执行写入、重启、部署或容器重建;它可以返回新的检查结果和本次 checkRunId,但第一版不要求落库。
建议目录:
src/modules/admin/platform-config/environment-dashboard/
contract/
environment-dashboard.controller.ts
dto/
environment-dashboard.dto.ts
application/
environment-dashboard.service.ts
environment-dashboard-status.mapper.ts
environment-dashboard-action.catalog.ts
domain/
environment-dashboard.types.ts
infrastructure/
environment-dashboard-signal.collector.ts
该模块属于 Admin Platform Config,因为它面向后台环境观测和安全总控,不属于 QQBot、Blog、Asset 任一业务域。
DTO
type EnvironmentHealthStatus =
| 'ok'
| 'degraded'
| 'down'
| 'blocked'
| 'unknown'
| 'unwired';
interface EnvironmentDashboardDto {
checkedAt: string;
checkRunId: string;
overallStatus: EnvironmentHealthStatus;
summaryCards: EnvironmentSummaryCardDto[];
topology: EnvironmentTopologyDto;
actions: EnvironmentActionDto[];
recentEvents: EnvironmentEventDto[];
}
interface EnvironmentSummaryCardDto {
key: string;
title: string;
status: EnvironmentHealthStatus;
primaryMetric: string;
secondaryMetric?: string;
source: EnvironmentSignalSourceDto;
route?: string;
}
interface EnvironmentTopologyDto {
nodes: EnvironmentNodeDto[];
edges: EnvironmentEdgeDto[];
}
interface EnvironmentNodeDto {
id: string;
label: string;
group: 'entry' | 'frontend' | 'service' | 'data' | 'observability' | 'qqbot' | 'deploy';
status: EnvironmentHealthStatus;
sourceKind: 'live' | 'cached' | 'derived' | 'configured' | 'external-link' | 'unwired';
metrics: EnvironmentMetricDto[];
evidence: EnvironmentEvidenceDto[];
links: EnvironmentNodeLinkDto[];
lastCheckedAt?: string;
}
interface EnvironmentEdgeDto {
id: string;
source: string;
target: string;
relation: 'routes-to' | 'depends-on' | 'observes' | 'deploys' | 'connects';
status: EnvironmentHealthStatus;
}
interface EnvironmentActionDto {
key: string;
label: string;
description: string;
kind: 'refresh' | 'self-check' | 'open-route' | 'open-url' | 'disabled-future';
riskLevel: 'safe' | 'medium' | 'high';
enabled: boolean;
targetRoute?: string;
targetUrl?: string;
disabledReason?: string;
requiredPermission?: string;
}
interface EnvironmentEventDto {
id: string;
source: string;
level: 'info' | 'warn' | 'error' | 'fatal';
title: string;
message: string;
happenedAt: string;
route?: string;
}
实现时应使用项目现有 class DTO 风格,不需要逐字照搬 interface;上述结构是合同语义。
状态归一规则
ok:信号源明确可用,关键指标正常。degraded:信号源可读,但存在局部异常,例如少量账号离线、日志查询降级、插件部分失败。down:信号源明确不可用,例如 MinIO 检查失败、WordPress auth check 失败。blocked:存在会阻断业务闭环的问题,例如 API runtime 配置缺失、QQBot worker 阻塞。unknown:检查失败、超时或没有足够证据判断。unwired:设计上存在该节点,但当前版本尚未接入读取能力。
总体状态按严重度聚合:
blocked > down > degraded > unknown/unwired > ok
unknown 和 unwired 不应覆盖真实 down 或 blocked,但必须在 UI 上单独计数,避免被误认为健康。
信号源映射
Runtime/API
来源:
RuntimeHealthService.getRuntimeHealth()RuntimeConfigService配置检查结果
节点:
- API Runtime
- Runtime Config
- MySQL
- Loki configured
- MinIO configured
- WordPress configured
- QQBot/NapCat configured
注意:
/health/runtime是无鉴权 plain JSON,新的 Admin 聚合接口不能直接 HTTP 调自己,应直接调用 service。- 返回给 Admin 的证据必须脱敏,保留 configured/missing 语义即可。
系统日志/Loki
来源:
SystemLogService/system/logs/status/system/logs/summary
节点:
- Loki / System Logs
事件:
- 最近错误等级摘要。
- 日志查询状态。
注意:
- 不返回大段原始日志。
- 页面跳转到现有系统日志页面时可附带 level/source filter。
QQBot Core / NapCat
来源:
QqbotDashboardService.summary()QqbotAccountService或账号列表已有 runtime append 结果QqbotNapcatAccountRuntimeService- NapCat runtime detail 现有摘要
节点:
- QQBot Core
- OneBot Reverse WS
- NapCat Accounts
指标:
- 账号总数。
- 在线账号数。
- 启用账号数。
- 发送成功/失败。
- bus/runtime 状态。
- NapCat 容器/WebUI/QQ 登录态分布。
注意:
- 账号列表可能触发 runtime TTL 检查,聚合服务需要短超时和并发限制。
- OneBot reverse WS 心跳不能被当作 QQ 登录成功,拓扑证据必须区分容器、OneBot、WebUI、QQ 登录态。
插件平台与定时任务
来源:
- Plugin Platform installations/capabilities/operations/runtime events。
- Plugin Task page/status service。
节点:
- Plugin Platform
- Plugin Operations
- Plugin Scheduled Tasks
指标:
- 已安装插件数量。
- enabled 插件数量。
- operation 数量。
- worker/runtime event 最近异常。
- 定时任务总数、启用数、最近失败数。
注意:
- 第一版面板不执行插件 enable/disable、task run、cron 修改。
- 相关操作只跳转到插件管理或插件任务页。
MinIO / Asset
来源:
MinioClientService.checkConnection(bucketName?)/minio/check现有能力对应的 service。
节点:
- MinIO
指标:
- bucket 名称。
- bucket 是否存在。
- 连接检查状态。
注意:
- 不在 Dashboard 创建 bucket。
createAssetBucket、上传、删除都不是第一版安全动作。
WordPress / Blog
来源:
WordpressService.checkAuth()- WordPress theme/blog theme config 读取能力。
节点:
- WordPress
- Blog Frontend
指标:
- WordPress auth check。
- theme config 读取状态。
- public blog route 可用性如果 API 内有 service 可读,则作为 live;否则第一版仅展示 configured/external-link。
注意:
- 不执行 WordPress import、sync 或写入。
Jenkins / K8s / NAS
来源:
- Jenkins 只读 API:读取指定 job 的最近 build number、result、building、timestamp、duration、commit/hash、branch 和构建 URL。
- K8s 只读 API:读取指定 namespace/deployment 的 generation、observedGeneration、replicas、updatedReplicas、readyReplicas、availableReplicas、镜像、Pod phase、restartCount 和最近 warning event 摘要。
- Deploy observation evidence:如果已有
mcp/ktWorkflow deploy-observation产物或等价线上证据文件,可作为cached证据补充 Jenkins/K8s live 读取。 - 外部链接:Jenkins/K8s Dashboard 链接只作为跳转,不替代只读状态读取。
节点:
- Jenkins
- K8s Deployment
- API Pod
- NAS Runtime
第一版行为:
- 拓扑上显示节点。
- Jenkins/K8s/NAS 节点必须有只读观测证据或明确的读取失败证据。
- 只允许
GET/ list/watch 等只读能力;K8s RBAC 必须限制为 deployment、pod、event、replicaset 等观测资源的get/list/watch。 - Jenkins 凭据必须是只读账号或只读 token,不允许 job build、replay、configure、credential 相关权限。
- 高风险动作如“触发部署”“重启 Pod”“查看敏感 Secret”全部 disabled。
读取字段:
- Jenkins:jobPath、buildNumber、result、building、branch、commitSha、commitMessageSummary、startedAt、durationMs、url。
- K8s Deployment:namespace、name、generation、observedGeneration、replicas、updatedReplicas、readyReplicas、availableReplicas、currentImage、desiredImage。
- K8s Pod:podName、phase、ready、restartCount、image、nodeName 可选、startedAt、lastWarningReason。
- NAS Runtime:第一版只展示
external-link或 cached deploy-observation 证据,不执行 SSH;如果没有可读证据,状态为unknown且写明未配置只读 NAS 证据源。
失败语义:
- Jenkins token 缺失或 403:
unknown,evidence 写明jenkins-readonly-auth-missing或jenkins-readonly-forbidden。 - Jenkins 最近 build failed:
down或degraded,按是否影响当前线上镜像判断。 - K8s RBAC 403:
unknown,evidence 写明k8s-readonly-rbac-forbidden。 - Deployment 未就绪:
down。 - Pod restartCount 增长或 warning event:
degraded。 - 只读证据必须脱敏,不暴露 kubeconfig、token、Secret、完整 Jenkins console log。
安全总控 Action Catalog
第一版 enabled actions:
refresh-dashboard:重新请求 dashboard。run-readonly-self-check:调用POST /system/environment/self-check,只执行只读检查。open-system-logs:跳转系统日志页。open-qqbot-dashboard:跳转 QQBot Dashboard。open-napcat-runtime:跳转 NapCat runtime/账号详情相关页面。open-plugin-platform:跳转插件平台页。open-plugin-tasks:跳转插件任务页。open-asset-page:跳转资产/MinIO 相关页面。open-wordpress-page:跳转 Blog/WordPress 管理页。open-jenkins:如果配置外链则打开 Jenkins。open-k8s-dashboard:如果配置外链则打开 K8s Dashboard。
第一版 disabled actions:
restart-api-podtrigger-jenkins-deployrun-db-migrationrecreate-napcat-containerplugin-enable-disableplugin-task-run-onceminio-create-bucketwordpress-import
每个 disabled action 必须返回:
riskLevel: 'high'enabled: falsedisabledReasonrequiredPermission- 后续所需安全条件,例如二次确认、审计日志、回滚路径、只读预检。
前端设计
改造位置:
apps/web-antdv-next/src/views/dashboard/analytics/index.vue
apps/web-antdv-next/src/views/dashboard/analytics/components/
apps/web-antdv-next/src/api/system/environment.ts
路由:
- 保留
/dashboard/analytics,避免菜单和固定 tab 入口失效。 - 菜单文案可改为“环境总览”或“环境状态”。
- 如果后台菜单组件选择依赖
componentKeys,需要补齐/dashboard/组件扫描。
页面结构:
- 使用
Page autoContentHeight。 - 使用 Ant Design Vue Next 的
Card、Statistic、Tag、Button、Tooltip、Drawer、Timeline、Alert、Descriptions。 - 拓扑可使用 DOM + CSS grid/SVG edge overlay 实现,不引入重量图表库。
- 每个拓扑节点使用固定尺寸,避免状态文字变化导致布局跳动。
- 节点点击打开证据抽屉,抽屉展示 metrics、evidence、links、lastCheckedAt。
- 安全总控按钮必须用图标 + tooltip;高风险 disabled action 不隐藏。
- 页面禁止使用旧示例中的营销图表和静态数据。
视觉原则:
- 运维工具风格,信息密度高、层级清晰、颜色克制。
- 不做 hero,不做装饰渐变,不做大面积单色主题。
ok/degraded/down/blocked/unknown/unwired使用一致的状态色和文字。- 拓扑主视图必须在桌面第一屏可见;移动端可纵向分组堆叠。
后端实现约束
- Controller 使用
JwtAuthGuard。 - 返回
vbenSuccess(data)。 - Aggregator 通过 service 直接调用现有能力,不通过 HTTP 请求本 API。
- 每个信号源独立 timeout、独立
Promise.allSettled,单点失败不能拖垮整个 dashboard。 - 信号源失败必须变成节点 evidence,而不是抛出 500。
- 只有认证、参数、系统级不可恢复错误才让接口失败。
- 新增或触碰函数、方法、handler、job 必须补 JSDoc,参数说明要写来源和用途。
- 不泄露 secrets、token、password、raw env、kubeconfig、SSH 信息、QQBot 大字段。
- QQBot 摘要不得返回
replyText、base64 图片或过长日志。 - Jenkins/K8s 必须接入只读观测;读取失败时返回
unknown/down和失败证据,不得退回unwired或伪造健康。 - Jenkins/K8s 适配器必须在代码和权限上只读:不得调用 Jenkins build/configure/replay,不得调用 K8s create/update/patch/delete/exec/log secret 等写入或敏感接口。
缓存与成本
建议第一版采用短 TTL 聚合缓存:
- 默认 dashboard TTL:10-30 秒。
self-check可绕过 dashboard TTL,但仍给单个信号源设置 timeout。- NapCat/account runtime 读取复用现有 TTL,不强制刷新所有账号。
- WordPress/MinIO 外部探测设置独立短超时。
- Loki summary 查询失败时只降级日志节点。
- Jenkins/K8s 只读探测设置独立短超时,读取失败只降级部署层节点。
缓存返回需要在 evidence 中标注:
checkedAtsourceKindttlMsisStale
验收标准
设计验收
- 用户确认本 spec 后,进入 Superpowers writing-plans。
- 实施计划必须拆 API 合同、API 聚合、Admin 页面、测试/线上闭环四部分。
API 验收
GET /system/environment/dashboard本地真实请求返回 Vben 包装。- 响应中包含 summaryCards、topology.nodes、topology.edges、actions、recentEvents。
- Jenkins/K8s 节点由只读适配器提供 build/deployment/pod 证据;缺配置、403 或超时时显示
unknown/down与原因,不导致接口失败。 - Jenkins/K8s 适配器没有任何部署、重启、patch、delete、exec 或 secret 读取路径。
- 任一可模拟信号源失败时接口仍 200,并将对应节点标为
unknown/degraded/down。 - 不返回敏感字段或 QQBot 大字段。
Admin 验收
/dashboard/analytics不再展示 Vben 示例静态图表。- 第一屏展示总体状态、拓扑和安全总控。
- 节点点击能打开证据抽屉。
- enabled action 可执行刷新、只读自检或跳转。
- disabled high-risk action 可见且说明禁用原因。
- 页面切换无 Vue
non-element root node/ transition 空白问题。
线上验收
- API/Admin 推送部署后,Jenkins/K8s 发布状态需按现有 deploy observation 流程验证。
- 线上 Admin 页面可打开。
- 线上 dashboard 接口 200。
- 线上页面至少展示 API Runtime、System Logs、QQBot、NapCat、Plugin Platform、MinIO、WordPress、Jenkins/K8s 节点。
- 线上页面的 Jenkins/K8s 节点展示真实只读观测证据:Jenkins 最近 build、commit、result;K8s Deployment ready/updated、Pod image、restartCount。
- Jenkins/K8s 操作项只展示 disabled,不允许触发部署、重启 Pod、修改资源或读取 Secret。
测试计划方向
实施计划阶段应覆盖:
- API service 单测:状态严重度聚合、partial failure、unwired 节点、action catalog、Jenkins/K8s read-only failure mapping。
- API Jenkins/K8s adapter 单测:只允许只读路径,覆盖 200、403、timeout、failed build、deployment not ready、pod restart warning。
- API controller contract spec:鉴权路由、Vben response shape、self-check 只读行为。
- Admin API wrapper Vitest:请求路径和响应类型。
- Admin 页面组件测试:拓扑节点、证据抽屉、disabled actions。
- 本地真实接口请求:启动或复用 API 服务调用 dashboard 接口。
- 本地浏览器 smoke:打开
/dashboard/analytics,检查 console、首屏、抽屉和动作。 - 线上 smoke:部署后调用线上接口和页面。
后续扩展
后续可以在不破坏第一版合同的基础上增加:
- deploy observation evidence 入库或文件读取。
- 安全动作审计表。
- 二次确认和权限码控制的高风险动作。
- 环境变更历史趋势。
- 定时自检和告警推送。
这些扩展必须继续遵守:读态优先、动作分级、证据脱敏、失败局部降级、高风险动作有审计与回滚路径。