10 KiB
云端服务与控制台开发说明
更新:2026-11-09。当前交付是第一阶段本地可运行版本。Vue 控制台通过真实 HTTP 调用 Go API,账号、授权、设备、任务和审计保存在 PostgreSQL;演示 VM 的电源操作由明确标记的演示计算适配执行。本文件主要描述演示开发环境;随后已接通独立真实环境,控制台端口 5182、设备 HTTPS 8443。
启动
Windows 本机开发
需要 Node.js 22.12+、Go 1.25+、Docker Desktop。仓库根目录执行:
.\tools\start-cloud-dev.ps1
已安装前端依赖时可加 -SkipInstall。脚本启动专用 PostgreSQL 容器,编译并启动本机 API,再启动 Vite。默认控制台地址 http://127.0.0.1:5180,API 地址 http://127.0.0.1:8088,数据库仅映射本机 55438。可用 -ApiPort 和 -ConsolePort 改开发端口。不会停止其他占用端口的程序。
演示账号 admin、operator、viewer,统一演示密码 Demo@2026。对应超级管理员、运维、只读角色,仅 VDI_MODE=demo 会创建这些账号。首次数据库初始化后,重新启动保留业务数据。
进程 PID 和日志在忽略提交的 .local/ 中。关闭本机开发进程时根据 .local/cloud-dev.json 确认 PID 和命令路径,只停止本次启动的 API 与 Vite。数据库可通过 docker compose -f deploy/compose.dev.yml stop postgres 停止;不删除卷即可保留数据。
全容器开发
与本机模式二选一,避免占用同一端口:
docker compose -f deploy/compose.dev.yml up --build -d
控制台仍是 http://127.0.0.1:5180。Nginx 代理同源 /api 到 Go 服务,PostgreSQL 使用命名卷。该 compose 是开发演示配置,不是客户生产部署包。
端口被其他开发进程占用时,可先设置 $env:VDI_CONSOLE_PORT='5181'、$env:VDI_API_PORT='8089' 再执行 compose。当前本机验收使用该端口组合,预览地址为 http://127.0.0.1:5181。
仅前端模拟
cd console
npm ci
$env:VITE_API_MODE='mock'
npm run dev
MSW 在浏览器层模拟 HTTP,只有开发构建允许启用,不需要 Go 或数据库。模拟操作不控制真实资源,刷新页面会重置模拟业务数据。正常的 api 模式不注册模拟 Worker。
当前可用范围
| 模块 | 当前实现 |
|---|---|
| 登录 | bcrypt 密码校验、JWT、服务端会话记录、退出撤销、刷新页面恢复、三角色服务端授权 |
| 总览 | 终端在线、VM 电源、实际画面就绪连接、异常任务;连接预约单独记录 |
| 计算资源 | 节点列表;配置 PVE 后每 30 秒同步节点/已纳管 VM,显示同步时间与过期标记 |
| 桌面 | 演示桌面;发现 PVE VM、纳管、查看详情、开机/正常关机/重启;PVE UPID 跟踪 |
| 终端 | 管理员登记、一次性激活、设备独立令牌、心跳、桌面授权列表、命令领取与回执 |
| 授权 | 创建最终使用者、每设备关联一位使用者、每使用者多个桌面、停用和撤销后阻止新连接 |
| 任务 | 持久化排队/执行/成功/失败/结果未确认、请求去重、同对象任务互斥、最终回执审计 |
| 连接契约 | 短期单次票据、终端隔离、消费时重新校验授权、同桌面活动占用检查 |
当前连接票据仅授权并返回 Moonlight 端点与参数;终端仍需既有 Sunshine 配对。消费票据登记连接预约,不证明串流已建立;现场 Qt 已上报实际画面就绪与进程结束事件,详情见真实接入说明。不要把 credentialMode=existing-pairing 当作免配对认证。
本轮将 API 入口与基础业务模块放在一个可运行的 Go 网关进程中,数据库和 Proxmox client 独立封装。原方案的七个服务职责继续作为后续拆分边界;当前尚未交付七个独立部署的服务。MQTT 总线、Rust Agent、VictoriaMetrics 指标接入、模板发放、桌面池、GPU 绑定、OTA、AD/LDAP 尚未完成;Qt 适配现已实际部署。控制台仅显示已接通的第一阶段功能。
真实 Proxmox 接入
使用新的独立数据库,按 platform/.env.example 注入配置。正式模式要求至少 32 字符的 JWT 密钥、管理员账号和至少 12 字符的初始密码。管理员环境变量仅在账号首次创建时生效,不会在每次启动时覆盖已有密码。数据库记录初始化模式,拒绝直接混用演示与正式数据库。
VDI_MODE=production
DATABASE_URL=postgres://.../vdi?sslmode=require
VDI_JWT_SECRET=...
VDI_ADMIN_USERNAME=...
VDI_ADMIN_PASSWORD=...
PVE_URL=https://pve.example.internal:8006
PVE_TOKEN_ID=vdi@pve!console
PVE_TOKEN_SECRET=...
PVE_CA_FILE=/run/secrets/pve-ca.pem
PVE 凭据由后端持有,前端和终端不会接收;证书校验始终开启。PVE_URL 只填 HTTPS origin,不附 /api2/json。由运维给 API Token 配置实际需要的节点/VM/存储查询和 VM 电源操作权限。本轮不自动修改 PVE 账号、ACL、VM 或主机配置。
启动后到“计算资源”手动同步;再到“桌面管理”选择“纳管已有 VM”。纳管仅登记已存在的 VM,不改 VM 配置。连接地址可在纳管表单填写。首次真实接入应使用专门测试 VM 核验 API 版本、证书、任务结果和关机行为,再对业务 VM 开放操作。
正式环境的 HTTPS 入口、运维凭据轮换、账号维护、登录限流、独立数据库迁移流程与备份恢复仍属于部署产品化工作;当前 compose 不作生产就绪声明。
设备接口联调
接口契约在 docs/openapi/platform.v1.json,API 根路径 /api/v1。控制台通过生成的类型和统一请求适配调用接口,页面不拼接 API 地址。
- 管理员在终端页登记 SN,取得仅显示一次的
activationSecret。 - 终端
POST /terminal/register提交 SN、activationSecret、agentVersion,取得设备令牌;激活密钥随即作废。 - 设备以独立
Authorization: Bearer <device-token>发送心跳、拉配置和获取授权桌面。 - 管理员创建用户并关联终端、勾选多个桌面;设备再次请求
/terminal/desktops即获得更新列表。 - 设备轮询
GET /terminal/commands领取命令,执行后POST /terminal/commands/{id}/ack报告 success/failed。没有回执的命令约两分钟后显示结果未确认;不会自动重放。 - 申请
/terminal/connect-ticket,再用/terminal/connect-ticket/consume单次消费;消费时再次检查授权与桌面占用。之后仍使用已有 Moonlight/Sunshine 配对。
tools/platform-terminal-simulator.py --sn <SN> 可在本机演示平台注册、发心跳和读取授权桌面。激活密钥通过交互输入或 VDI_DEVICE_ACTIVATION_SECRET 传入;模拟器对所有设备操作回失败,避免假装执行了重启或日志收集。它不是可部署的 Rust Agent。
当前 HTTPS 轮询是 MQTT 接入前的可验证通道;没有声称已提供消息总线。终端令牌的撤销/重新激活、配置热更新将继续扩展契约;Qt 串流事件、固定命令执行和诊断日志上传已在真实环境接通。
检查命令
cd console
npm run lint
npm run typecheck
npm run test
npm run build
npm run test:e2e
npm run api:generate
E2E 使用已经启动的本机平台,只允许对 /healthz 返回 demo 模式的服务运行;Windows 默认使用已安装的 Edge。其他环境使用 npx playwright install chromium 准备测试浏览器。VDI_E2E_URL 可覆盖测试地址。测试会创建演示用户和待激活终端、切换演示 VM 电源,不会操作真实 PVE。
cd platform
go test ./...
go vet ./...
数据库集成测试需要 VDI_TEST_DATABASE_URL 指向专用可清空测试数据库。测试会清空该数据库内平台表,不要指向开发业务库或生产库。
docker exec vdi-cloud-dev-postgres-1 psql -U vdi -d postgres -c 'CREATE DATABASE vdi_test'
$env:VDI_TEST_DATABASE_URL='postgres://vdi:vdi-local-demo@127.0.0.1:55438/vdi_test?sslmode=disable'
go test ./...
后端测试覆盖服务端 RBAC、JWT 退出失效、幂等任务、授权变更事务回滚、设备隔离、一次性票据、回执和超时;PVE client 使用本地测试服务器验证 TLS 和 UPID,不向现场 PVE 发送请求。
本轮验收记录(2026-11-09)
- Go 单元测试、专用 PostgreSQL 集成测试和
go vet通过;包含模式隔离、重启后撤权保留、PVE 明确失败与提交结果未确认的区分。 - 前端 ESLint、TypeScript、3 项登录状态单元测试和生产构建通过。
- 容器版
http://127.0.0.1:5181的 7 项 Playwright 用例全部通过:登录失败/恢复/退出、桌面命令最终结果、用户多桌面授权持久化、终端激活信息、两种权限角色、空列表/异常/401。 - 单独启动 MSW 模式,验证模拟登录和授权页导航;检查 1440px 桌面及 390px 窄屏。
- 页面截图:总览、桌面管理、窄屏。页面主题集中在
console/src/styles/tokens.css,可交给 UI 同事继续调整。 - Node 依赖完整审计为 0 项已知漏洞。Vitest 已更新;TypeScript ESLint 的 minimatch 子依赖定向覆盖至 11.0.1+,静态检查通过。
- Docker API/控制台镜像构建并启动,数据库保留卷内已有业务数据。未向现场 PVE 或盒子发送操作。
数据与执行边界
- 在线按最近 90 秒心跳计算;FPS/RTT 缺失为 null,不填 0。PVE 电源状态与 VM 内连接服务状态分开。
- 任务成功必须有计算适配结果或设备回执。提交后发生通信异常时保留“结果未确认”,由管理员核对实际状态,不自动重试。
- 桌面“重启”只用 PVE reboot;未将硬重启 reset 冒充“还原镜像”。
- 当前任务和审计列表展示最近 1000 条,完整记录仍存 PostgreSQL;长期检索和归档后续扩展。
- 凭据不写入审计;设备上报的自由文本不直接放入公开任务结果。