288 lines
9.9 KiB
Markdown
288 lines
9.9 KiB
Markdown
# VDI Web 管理控制台 MVP 实施方案
|
||
|
||
> 版本:v0.1(功能先行,UI 稿待项目经理提供)
|
||
> 日期:2026-10-28
|
||
> 依据:`VDI云桌面软件开发方案(1).docx` 第 2、4、5 节及 `VDI云桌面完整方案-云管端.docx` 管理平台模块表。
|
||
|
||
## 1. 先明确两个“登录”
|
||
|
||
本项目有两个不同的界面,必须分开:
|
||
|
||
| 界面 | 使用者 | 运行位置 | 职责 |
|
||
|---|---|---|---|
|
||
| 终端 kiosk-shell | 云桌面最终用户 | RK3528 盒子本地全屏 | 首配、设备绑定、用户登录、选择/进入被授权桌面、会话状态 |
|
||
| Web 管理控制台 console | 超级管理员、运维、只读人员 | PC 浏览器 | 终端、桌面池、用户绑定、GPU、监控、OTA、审计管理 |
|
||
|
||
正式文档中的 `console/` 指第二项。它不应运行在盒子上,也不应直接发起 RDP/Moonlight;它通过平台 API 管理资源和下发策略。
|
||
|
||
“盒子开机直连 Moonlight”只能作为当前串流技术验证,不是最终产品登录流程。最终终端流程应恢复为:
|
||
|
||
```text
|
||
盒子开机
|
||
-> kiosk-shell 全屏终端登录/首配页
|
||
-> vdt-agent 注册并获取终端身份
|
||
-> 用户登录或终端绑定校验
|
||
-> 平台返回该用户可用的桌面列表及短期连接信息
|
||
-> 用户选择桌面
|
||
-> kiosk-shell 按 protocol=rdp|moonlight 启动会话
|
||
-> 断开后回桌面列表/登录页
|
||
```
|
||
|
||
## 2. Web 控制台 MVP 目标
|
||
|
||
第一版目标不是做漂亮的大屏,而是跑通一个可演示、可替换 UI、可接真实后端的后台系统:
|
||
|
||
1. 用户能登录和退出;
|
||
2. 根据角色控制菜单和按钮;
|
||
3. 管理员能查看终端、桌面、用户及绑定关系;
|
||
4. 能对终端下发命令、对桌面执行开关机/重置;
|
||
5. 能查看基础状态、操作结果和审计记录;
|
||
6. 后端未完成时使用 Mock API,后端接口上线后不改页面业务逻辑即可切换。
|
||
|
||
## 3. 技术栈与工程结构
|
||
|
||
按定版文档执行:Vue 3 + Vite + TypeScript 严格模式 + Element Plus。
|
||
|
||
建议补充:Pinia(状态)、Vue Router、Axios、Vitest、Playwright、MSW(Mock API)。
|
||
|
||
```text
|
||
console/
|
||
├─ src/
|
||
│ ├─ api/ # OpenAPI 生成 SDK 的薄封装
|
||
│ ├─ assets/
|
||
│ ├─ components/ # 领域无关组件
|
||
│ ├─ layouts/ # 登录布局、控制台布局
|
||
│ ├─ mocks/ # MSW handlers 与演示数据
|
||
│ ├─ router/ # 路由、鉴权守卫、RBAC meta
|
||
│ ├─ stores/ # auth、app、notification
|
||
│ ├─ types/ # 页面 ViewModel;API 类型由生成器管理
|
||
│ ├─ views/
|
||
│ │ ├─ login/
|
||
│ │ ├─ dashboard/
|
||
│ │ ├─ terminals/
|
||
│ │ ├─ desktops/
|
||
│ │ ├─ users/
|
||
│ │ ├─ gpu/
|
||
│ │ ├─ monitoring/
|
||
│ │ ├─ ota/
|
||
│ │ └─ audit/
|
||
│ ├─ App.vue
|
||
│ └─ main.ts
|
||
├─ e2e/
|
||
├─ public/
|
||
├─ .env.development
|
||
├─ .env.mock
|
||
├─ package.json
|
||
└─ vite.config.ts
|
||
```
|
||
|
||
约束:页面不能直接拼 URL 或写 Axios;所有网络调用只经过 `api/`。这样 Mock 与真实后端可无感切换。
|
||
|
||
## 4. 页面与优先级
|
||
|
||
### M0:登录与应用框架
|
||
|
||
- 登录页:用户名、密码、登录按钮、错误状态、加载状态;
|
||
- 控制台壳:侧边导航、顶部栏、面包屑、当前账号、退出;
|
||
- 401 自动清理会话并回登录;
|
||
- 403 权限提示;
|
||
- 路由级 RBAC:`super_admin`、`operator`、`viewer`;
|
||
- 开发环境使用 Mock 登录,生产环境只调用真实 API。
|
||
|
||
### M1:核心演示闭环
|
||
|
||
1. 仪表盘:在线终端、活动会话、运行桌面、告警数量;
|
||
2. 终端管理:列表、搜索、状态筛选、详情、重启、重置会话;
|
||
3. 桌面管理:列表、状态筛选、开机、关机、重启、重置;
|
||
4. 用户与绑定:用户列表、用户详情、终端/桌面绑定与解绑;
|
||
5. 审计日志:操作者、动作、目标、结果、时间、请求 ID。
|
||
|
||
M1 完成后已经可以给项目经理演示完整业务流程。
|
||
|
||
### M2:完整文档范围
|
||
|
||
- 桌面池:模板、容量、回收策略;
|
||
- GPU 池:节点/PCI 地址/型号/状态/绑定桌面;
|
||
- 监控:会话在线数、FPS、RTT、节点水位、告警;
|
||
- OTA 中心:版本、批次、灰度比例、进度、失败终端;
|
||
- CSV 用户/绑定批量导入向导;
|
||
- 配置模板与配置版本下发。
|
||
|
||
## 5. 登录与权限方案
|
||
|
||
### 登录接口
|
||
|
||
```http
|
||
POST /api/v1/auth/login
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"username": "admin",
|
||
"password": "******"
|
||
}
|
||
```
|
||
|
||
建议响应:
|
||
|
||
```json
|
||
{
|
||
"accessToken": "jwt",
|
||
"expiresIn": 3600,
|
||
"user": {
|
||
"id": "usr_001",
|
||
"username": "admin",
|
||
"displayName": "系统管理员",
|
||
"role": "super_admin"
|
||
}
|
||
}
|
||
```
|
||
|
||
建议第一版 access token 仅存内存;刷新 token 使用 `HttpOnly + Secure + SameSite` Cookie。若后端尚未支持 refresh,MVP 可暂存 `sessionStorage`,但不要长期使用 `localStorage` 保存高权限令牌。
|
||
|
||
### 权限矩阵
|
||
|
||
| 能力 | super_admin | operator | viewer |
|
||
|---|---:|---:|---:|
|
||
| 查看所有页面 | 是 | 是 | 是 |
|
||
| 终端远程命令 | 是 | 是 | 否 |
|
||
| 桌面生命周期操作 | 是 | 是 | 否 |
|
||
| 用户/绑定修改 | 是 | 否 | 否 |
|
||
| GPU 绑定 | 是 | 否 | 否 |
|
||
| OTA 发布/灰度 | 是 | 是 | 否 |
|
||
| 只读监控/审计 | 是 | 是 | 是 |
|
||
|
||
前端 RBAC 只是交互约束,真正授权必须由 `api-gateway` 再验证,不能只隐藏按钮。
|
||
|
||
## 6. 第一版 API 契约
|
||
|
||
文档已明确的接口优先沿用:
|
||
|
||
```text
|
||
POST /api/v1/auth/login
|
||
GET /api/v1/users
|
||
POST /api/v1/desktop/assign
|
||
POST /api/v1/pool/{id}/action
|
||
GET /api/v1/gpu/cards
|
||
POST /api/v1/gpu/bind
|
||
GET /api/v1/monitor/query
|
||
```
|
||
|
||
为控制台 MVP 补齐建议接口(需后端确认并写入 OpenAPI):
|
||
|
||
```text
|
||
GET /api/v1/auth/me
|
||
POST /api/v1/auth/logout
|
||
GET /api/v1/terminals
|
||
GET /api/v1/terminals/{id}
|
||
POST /api/v1/terminals/{id}/commands
|
||
GET /api/v1/desktops
|
||
GET /api/v1/desktops/{id}
|
||
POST /api/v1/desktops/{id}/actions
|
||
GET /api/v1/bindings
|
||
DELETE /api/v1/bindings/{id}
|
||
GET /api/v1/audit-logs
|
||
```
|
||
|
||
所有列表统一查询参数:`page`、`pageSize`、`keyword`、`status`、`sort`;统一响应:
|
||
|
||
```json
|
||
{
|
||
"items": [],
|
||
"page": 1,
|
||
"pageSize": 20,
|
||
"total": 0,
|
||
"requestId": "req_xxx"
|
||
}
|
||
```
|
||
|
||
所有命令型接口必须返回 `commandId`,页面展示“已提交”,再轮询或通过 WebSocket/MQTT 网关显示最终结果,不能把 HTTP 200 当作设备已经执行成功。
|
||
|
||
## 7. Mock 先行策略
|
||
|
||
后端还没完成时,前端不应硬编码页面数据。使用 MSW 模拟真实 HTTP:
|
||
|
||
- 固定 3 个测试账号,对应三角色;
|
||
- 终端包含在线/离线/会话中/升级中;
|
||
- 桌面包含运行/停止/错误/任务中;
|
||
- 所有命令先进入 `pending`,1–3 秒后变成 `success` 或 `failed`;
|
||
- 登录失败、401、403、网络超时、空列表都要有测试场景;
|
||
- `VITE_API_MODE=mock|real` 切换数据源。
|
||
|
||
项目经理 UI 稿到后,Mock 数据仍然可用于逐页视觉验收。
|
||
|
||
## 8. 与终端登录流程的接口边界
|
||
|
||
管理员 Web 控制台不直接把 VM 密码写进终端,也不让终端调用 Proxmox API。
|
||
|
||
建议终端用户登录流程由 `auth-svc` 单独提供:
|
||
|
||
```text
|
||
POST /api/v1/terminal/session/login
|
||
GET /api/v1/terminal/session/desktops
|
||
POST /api/v1/terminal/session/connect-ticket
|
||
```
|
||
|
||
`connect-ticket` 返回短期、一次性连接信息:
|
||
|
||
```json
|
||
{
|
||
"desktopId": "desk_001",
|
||
"protocol": "moonlight",
|
||
"endpoint": "192.168.1.70",
|
||
"app": "Desktop",
|
||
"display": { "width": 1920, "height": 1080, "fps": 60 },
|
||
"ticket": "short-lived-token",
|
||
"expiresAt": "2026-10-28T16:30:00+08:00"
|
||
}
|
||
```
|
||
|
||
这部分不是 `console/` 页面,但必须和 Web 控制台的“用户/终端/桌面绑定”共享同一套后端数据。
|
||
|
||
## 9. UI 稿到来前的页面设计原则
|
||
|
||
第一版只做稳定工作台,不做营销式页面:
|
||
|
||
- 左侧导航 + 顶部工具栏 + 主内容区;
|
||
- 列表优先,详情使用独立页或抽屉;
|
||
- 状态使用图标/标签,不依赖单一颜色;
|
||
- 危险操作二次确认;
|
||
- 所有异步操作显示提交、执行中、成功、失败四态;
|
||
- 页面级空态、错误态、无权限态必须完整;
|
||
- 颜色、字号、间距集中为设计 token,避免 UI 稿到后逐页改 CSS;
|
||
- 表格列、筛选区、表单字段以配置驱动,减少视觉改版成本。
|
||
|
||
## 10. 验收标准
|
||
|
||
M1 应达到:
|
||
|
||
1. 三种角色都能登录,菜单/按钮权限正确;
|
||
2. 刷新页面仍能恢复会话,令牌过期自动回登录;
|
||
3. 终端、桌面、用户/绑定、审计五条流程可演示;
|
||
4. 命令有执行中与最终结果,不出现“点击无反馈”;
|
||
5. API 全走统一 SDK/适配层,无页面直连 Axios;
|
||
6. Vitest 覆盖 auth store、路由守卫、权限判断;
|
||
7. Playwright 覆盖登录、终端命令、桌面操作、用户绑定四条主路径;
|
||
8. `npm run lint`、`npm run typecheck`、`npm run test`、`npm run build` 全通过。
|
||
|
||
## 11. 推荐实施顺序
|
||
|
||
```text
|
||
第 1 步:初始化 console 工程、路由、布局、设计 token
|
||
第 2 步:OpenAPI 初稿 + API SDK 生成 + MSW Mock
|
||
第 3 步:登录、会话恢复、RBAC、错误处理
|
||
第 4 步:终端管理 + 桌面管理
|
||
第 5 步:用户与绑定 + 审计日志
|
||
第 6 步:仪表盘聚合数据
|
||
第 7 步:Playwright E2E 与生产构建
|
||
第 8 步:项目经理 UI 稿到后替换视觉层
|
||
第 9 步:接真实 Go API,关闭 Mock
|
||
```
|
||
|
||
## 12. 当前决策建议
|
||
|
||
- 现在先开发 `console/` 的 M0 + M1,不等 UI 稿;
|
||
- 同时为 `terminal/kiosk-shell` 恢复“登录/桌面列表后连接”的产品流程,不再把开机直连 Moonlight 当最终形态;
|
||
- Web 控制台第一版只接 Mock,API 契约先和后端负责人确认;
|
||
- Moonlight/RDP 统一抽象成终端连接票据的 `protocol` 字段,Web 控制台只管理策略,不直接操控串流客户端;
|
||
- UI 稿到后只调整布局组件与 design tokens,业务路由、权限、API、测试保留。
|