这次我完成了一个面向运维场景的前端控制台项目,实现目标是根据接口文档和后端工程语义,构建一套可扩展、可联调、结构清晰的 Web 前端。项目围绕告警接入、会话跟踪、审批闭环、配置查看和 Webhook 联调等核心能力展开,整体技术栈采用 Vue 3 + Vite + Pinia + Vue Router + Element Plus + ECharts。

从结果上看,这次工作不仅完成了页面开发,也建立了统一的路由体系、状态管理、请求封装和业务模块划分,使前端具备了比较完整的控制台形态。

一、项目目标与业务背景


OpsPilot 面向的是运维自动化和告警处置场景,因此前端并不是普通的信息展示页面,而是一个围绕“告警 -> 分析 -> 审批 -> 处置”流程展开的工作台。结合接口文档,前端需要覆盖以下几类核心能力:

Dashboard 总览:展示调度器状态、会话状态、告警数量、待审批项
告警中心:查看告警列表和告警详情
会话中心:查看分析会话、事件时间线、审批状态与处理动作
审批台:对危险操作进行批准或拒绝
分析详情:展示报告、工具调用、审批轨迹
项目与工具管理:查看项目配置、工具注册表、通知渠道
Webhook 测试:直接向后端接口推送模拟告警
配置中心与系统设置:支持配置查看、热重载与本地偏好管理
这意味着前端不仅要把页面做出来,还要构建清晰的业务边界和统一的数据访问方式。

二、技术栈与工程入口


项目使用 Vite 构建前端工程,在入口中完成了 Vue 应用、路由、Pinia、Element Plus、图标系统和 ECharts 的初始化。

入口文件如下:

import { createApp } from 'vue'
import App from './App.vue'
import router, { setupRouterGuard } from './router'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import ECharts from 'vue-echarts'
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { LineChart, BarChart, PieChart } from 'echarts/charts'
import { GridComponent, TooltipComponent, LegendComponent, TitleComponent } from 'echarts/components'

use([CanvasRenderer, LineChart, BarChart, PieChart, GridComponent, TooltipComponent, LegendComponent, TitleComponent])

const app = createApp(App)
const pinia = createPinia()

app.use(router)
app.use(pinia)
setupRouterGuard(pinia)

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

app.use(ElementPlus)
app.component('v-chart', ECharts)

app.mount('#app')

这里我额外注册了 PieChart,因为 Dashboard 中需要展示会话状态分布图。通过这种方式,整个图表系统保持按需注册,兼顾功能完整性和前端打包控制。

三、前端目录结构设计


为了让页面结构与业务结构保持一致,我将前端划分为几个清晰的模块层:

src/pages/:页面级组件
src/api/:接口访问模块
src/layouts/:布局组件
src/router/:路由与守卫
src/stores/:全局状态管理
src/utils/:格式化与通用辅助逻辑
页面目录按照业务对象拆分,例如:

pages/alerts/
pages/sessions/
pages/approvals/
pages/analyses/
pages/projects/
pages/tools/
pages/notify/
pages/config/
pages/errors/
这种设计的优势在于,页面与业务域天然对应,后续无论是新增功能还是排查问题,都可以直接定位到具体业务目录,而不是在一个平铺的大型 views 目录中查找。

四、请求层设计与 API 模块化


为了保证接口调用清晰可维护,我将请求层拆成了统一客户端和业务分域 API 两层。

1. 统一请求客户端


在 src/api/client.js 中,我封装了 Axios 实例,负责:

动态解析 API Base URL
自动注入 X-Operator
统一处理接口错误提示
兼容环境变量和本地运行时配置
其中,API 地址解析逻辑如下:

function resolveBaseUrl() {
  const raw = (
    localStorage.getItem('opspilot_api_base_url') ||
    import.meta.env.VITE_API_BASE_URL ||
    '/api'
  ).trim()

  if (!raw) return '/api'
  if (raw === '/api' || raw.endsWith('/api')) return raw
  return `${raw.replace(/\/$/, '')}/api`
}

这个设计让前端既支持开发环境配置,也支持运行时通过设置页覆盖后端地址,在联调阶段非常实用。

2. 按业务域拆分 API


我将接口模块拆分为:

alerts.js
sessions.js
approvals.js
analyses.js
stats.js
projects.js
tools.js
config.js
webhook.js
例如会话相关接口包括:

获取会话列表
获取活跃会话
获取会话详情
获取事件流
获取会话关联分析
批准/拒绝/取消/注入消息
这样页面在引用接口时只依赖当前业务域,避免了大而全的聚合模块带来的维护复杂度。

五、登录态与本地操作员标识


由于当前后端更偏向运行态系统,没有完整的用户体系,因此前端实现了一个轻量的本地操作员标识方案。通过 Pinia 中的 auth store 管理操作员名称,并统一写入 localStorage。

核心状态包括:

operatorName
isLoggedIn
并提供:

setOperatorName
logout
这个设计有两个作用:

配合路由守卫控制访问逻辑
在请求头中携带 X-Operator,使审批和人工介入类操作带有最基本的操作者标识
对于当前阶段的运维控制台来说,这是一个足够轻量、又具备实际意义的前端状态方案。

六、路由与页面实现


项目采用 Vue Router 管理页面导航,并通过统一的守卫逻辑控制受保护页面访问。

目前已经实现的核心页面包括:

/login
/dashboard
/alerts
/alerts/:id
/sessions
/sessions/:id
/approvals
/analyses/:id
/projects
/projects/:name
/tools
/tools/webhook-tester
/notify/channels
/config
/settings
/403
/404
/error


1. Dashboard 总览页


Dashboard 页面聚合了多个统计接口,主要展示:

调度器运行状态
会话状态统计
告警数量
待审批项
最新告警列表
同时通过 ECharts 绘制会话状态分布图,使运维人员能够快速把握系统整体运行态势。

2. 告警与会话页面


告警列表页支持分页、过滤和详情跳转。告警详情页展示:

基础字段
标签与注解
关联会话
分析历史
原始 Payload
会话详情页则更加偏向运行态,展示:

会话基本信息
当前状态
结果摘要
事件时间线
关联分析
合并进入会话的相关告警
此外,会话详情页还具备几个关键操作入口:

批准
拒绝
取消会话
注入消息
这些能力使前端真正具备了从查看到处理的闭环能力。

3. 审批台与分析详情页


审批台聚焦待决策项目,支持查看审批状态并执行批准或拒绝。分析详情页则用于展示:

分析元数据
报告内容
工具调用记录
审批轨迹
上下文快照
这两个页面一起构成了自动分析与人工决策之间的桥梁。

4. 项目、工具与配置页


除了主流程页面,项目中还实现了若干平台辅助页面:

项目列表与项目详情
工具注册表
通知渠道
配置中心
系统设置
其中配置中心支持:

查看当前配置
查看版本号
触发配置重载
提交增量 patch
这让前端不仅可以消费运行态数据,也具备一定的平台运维能力。

七、Webhook 联调页面实现


/tools/webhook-tester 是一个非常实用的功能页面。它允许前端直接构造模拟告警,并调用后端的 POST /api/webhook/{project} 接口。

我在这个页面中预置了三类模板:

generic
prometheus
grafana
并支持填写:

project
source
webhook secret
payload JSON
这样一来,联调时不需要依赖外部监控系统,前端页面本身就可以完成告警推送模拟,大幅提高了开发和验证效率。

八、格式化与兼容层设计


由于后端返回的数据结构既包含结构化对象,也包含 JSON 字符串字段,因此在 src/utils/format.js 中实现了统一的兼容与格式化逻辑,包括:

safeJsonParse
prettyJson
formatDate
formatRelativeTime
formatDuration
normalizeCollection
normalizeAlert
normalizeSession
normalizeApproval
normalizeAnalysis
这一层非常重要。它把页面组件从“直接处理后端原始结构”的负担中解耦出来,让页面只关注展示逻辑,而不关心某个字段究竟是对象、字符串还是数组。

例如 normalizeSession 会统一兼容:

session_id
events
events_json
related_alerts
result
这样的设计显著提升了页面稳定性,也降低了后续接口演进对 UI 的直接冲击。

九、开发环境与联调方式


为了让开发更顺畅,我配置了 Vite 开发服务器代理:

server: {
  host: '0.0.0.0',
  port: 5173,
  proxy: {
    '/api': {
      target: 'http://127.0.0.1:8000',
      changeOrigin: true
    }
  }
}

同时,环境变量中也支持直接指定 API 地址:

VITE_API_BASE_URL=http://localhost:8000

这使得前端可以在两种模式下工作:

使用代理方式访问 /api
直接访问指定的后端地址
对于联调阶段来说,这种设计很灵活,既适合本地开发,也便于后续部署到不同环境。

十、构建验证与当前状态


在完成页面、路由、请求层和业务模块实现后,我对项目进行了构建验证,执行:

npm run build

构建成功,说明当前工程已经具备以下条件:

页面组件可正常编译
路由引用完整
API 模块依赖正确
全局状态、布局和图表注册无语法问题
工程可以产出可部署的前端构建包
从工程角度来说,这已经是一个结构完整的运维控制台前端项目。

结语


这次工作让我比较系统地完成了一次运维场景前端的落地实践。从技术上看,它涉及的不只是 Vue 页面开发,还包括:

工程结构设计
路由与权限控制
状态管理
请求层封装
图表集成
数据兼容与格式化
联调辅助能力建设
最终形成的不是单一页面,而是一套围绕告警、会话、审批、配置和联调能力展开的前端系统。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐