Appearance
模块:Services(服务层)
唯一职责:封装所有后端通信逻辑(HTTP REST + WebSocket),提供领域服务接口。不感知 Vue/Pinia 状态。
边界
属于本模块:
- HTTP 客户端(
ApiClient):统一 headers、响应信封解包、业务错误转换 - WebSocket 客户端(
WsClient):连接管理、心跳保活、自动重连、Command/Accept/Reject/Push 协议 - 领域服务:画布元数据、节点/连线 WS 命令、AI 生成、模型列表、工作空间管理、COS 文件上传
- 后端数据映射(Mapper):后端 VO → 前端数据结构转换
不属于本模块:
- 节点状态管理(idle → generating → done/error)
- 错误展示 UI
- 数据缓存(由各 Store 负责)
服务目录
services/
├── http/ # HTTP 客户端
├── ws/ # WebSocket 客户端
├── canvas/ # 画布元数据(HTTP)
├── flow/ # 节点/连线操作(WebSocket Command)
├── generate/ # AI 生成触发(HTTP)
├── models/ # 模型列表查询(HTTP)
├── workspace/ # 工作空间管理(HTTP)
├── storage/ # COS 文件上传
└── mappers/ # 共享映射工具(TYPE_MAP、STATUS_MAP、inferOrigin)HTTP 客户端
- 自动注入
App-Id、Platform、User-Id(从 localStorage 读取)headers - 响应信封自动解包:
code === 200→ 返回data,否则抛出ApiError baseURL来自NUXT_PUBLIC_API_BASE环境变量
WebSocket 协议
| 方向 | 类型 | 格式 |
|---|---|---|
| 发送 | Command | { requestId, action, data } |
| 接收 | Accept | { requestId, action, code: 200, msg, env, timestamp, data } |
| 接收 | Reject | { requestId, action, code: 4xx/5xx, msg } |
| 接收 | Push | { action, code: 0, env, timestamp, data } |
| 接收 | System | { action: 'connect', code: 0, data?, timestamp? } |
默认参数:心跳 30s、重连延迟 1s、最大重连 5 次、命令超时 15s。
API 端点
画布服务
| 方法 | Endpoint | 用途 |
|---|---|---|
| GET | /stormflow/flow/v1/canvases/{canvasId} | 获取画布元数据 |
| PUT | /stormflow/flow/v1/canvases/{canvasId} | 更新画布名称/视口 |
Flow 服务(WebSocket)
WS Action:add_node / update_node / remove_node / add_edge / update_edge / remove_edge / undo
Push 事件:node_added / node_updated / node_removed / edge_added / edge_updated / edge_removed
Generate 服务
| 方法 | Endpoint | 用途 |
|---|---|---|
| POST | /stormflow/flow/v1/canvases/{canvasId}/nodes/{nodeId}/action/generate | 触发 AI 生成 |
生成结果通过 WebSocket Push(node_updated)异步推送,不在 HTTP 响应中返回。
Models 服务
| 方法 | Endpoint | 用途 |
|---|---|---|
| GET | /stormflow/resource/v1/models | 获取所有可用模型 |
Workspace 服务
| 方法 | Endpoint | 用途 |
|---|---|---|
| GET | /stormflow/management/v1/workspaces | 获取工作空间 |
| PUT | /stormflow/management/v1/workspaces/{id} | 更新工作空间设置 |
| POST | /stormflow/flow/v1/canvases | 创建画布 |
| DELETE | /stormflow/management/v1/workspaces/{id}/items/{itemId} | 删除项目(回收站) |
| POST | /stormflow/management/v1/workspaces/{id}/items/{itemId}/action/restore | 恢复项目 |
Storage 服务
STS 凭证通过 POST /storage/object/v2/policies/action/generate 获取,文件直传腾讯 COS(cos-js-sdk-v5),返回 CDN URL。
不变量
- 所有 HTTP 请求通过
ApiClient发送,自动注入App-Id、Platform、User-Idheaders - 所有后端响应通过统一信封解包:
code === 200→ 返回data,否则抛出ApiError - WS 连接断开时自动重连(指数退避),达到上限后状态变为
disconnected - WS Command 必须携带
requestId,Accept/Reject 通过requestId匹配 - Services 层不持有、不修改任何 Vue / Pinia 状态,仅负责传输和数据映射
- COS 上传使用 STS 临时凭证,凭证过期前自动刷新
错误场景
| 场景 | 模块行为 | 调用方预期 |
|---|---|---|
NUXT_PUBLIC_API_BASE 未配置 | 首次请求时抛出 Error | 显示配置错误提示 |
| 后端返回非 200 code | 抛出 ApiError(code, msg, requestId) | catch 后更新状态为 error |
| 网络超时 / 断网(HTTP) | $fetch 抛出 FetchError | catch 后更新状态为 error |
| WS 连接失败 | 自动重连(指数退避),达到上限后状态变为 disconnected | 显示连接失败提示 |
| WS Command 超时 | 抛出 WsError,从 pending map 移除 | catch 后回滚乐观更新 |
| WS Command 被 Reject | 抛出 WsError(code, msg) | catch 后回滚乐观更新 |
| COS 上传失败 | uploadToCos Promise reject | 显示上传失败提示 |
实现位置
| 角色 | 文件路径 |
|---|---|
| HTTP 客户端 | services/http/ |
| WS 客户端 | services/ws/ |
| 画布服务 | services/canvas/ |
| Flow 服务 | services/flow/ |
| Generate 服务 | services/generate/ |
| Models 服务 | services/models/ |
| Workspace 服务 | services/workspace/ |
| COS 上传 | services/storage/ |
| 共享 Mapper | services/mappers/ |
| 测试 | test/unit/wsClient.test.ts, test/nuxt/apiClient.test.ts |