# 3D 机房前后端接口对接文档 本文档依据 2026-07-31 工作区内 `assets`、`dc-control`、`alert` 的实际代码整理,供前端开发和联调使用。 ## 1. 对接范围 3D 机房由 `Assets` 服务提供统一场景接口,支持: - 加载单个机房或全部有权限的 3D 场景。 - 保存机房长、宽、高。 - 拖拽机柜并保存三维坐标。 - 将设备放入机柜并调整 U 位。 - 将智能空调、监控摄像头、智能插座等设备直接放置在机房内。 - 解除设备在机柜或机房内的位置。 - 查看设备运行状态、最新指标和活动告警。 - 将资产与 `dc-control` 监控资源绑定。 前端渲染和写入场景时主要访问 `Assets`。`Assets` 会在后台聚合 `dc-control` 和 `alert`,前端不直接调用运行状态及活动告警的内部批量接口。 ## 2. 通用约定 ### 2.1 基础地址和请求头 本文使用 `{API_BASE}` 表示网关地址,例如: ```text {API_BASE}/Assets/v1/three-d/rooms/1/scene ``` 所有本文列出的接口均需要 JWT: ```http Authorization: Bearer Content-Type: application/json ``` GET 请求不需要设置 `Content-Type`。DELETE 设备位置接口需要携带 JSON 请求体。 ### 2.2 统一响应结构 成功响应: ```json { "code": 0, "message": "", "details": {}, "timeseq": 1785465600000 } ``` 失败响应示例: ```json { "code": 500, "message": "布局版本已变化,当前版本为 5", "details": "", "timeseq": 1785465600000 } ``` 注意: - 业务成功以 `code === 0` 为准。 - 当前统一响应即使业务失败,HTTP 状态通常仍为 `200`,不能只判断 HTTP 状态。 - 失败时直接展示或记录 `message`;`details` 不承载错误详情。 - `timeseq` 是毫秒时间戳。 ### 2.3 数据权限 3D 接口从 JWT 扩展声明中读取数据范围: | JWT 扩展字段 | 示例 | 含义 | | --- | --- | --- | | `data_scope_all` | `"true"` | 可访问全部机房 | | `data_scope_datacenter_ids` | `"1,2"` | 可访问指定数据中心 | | `data_scope_room_ids` | `"10,11"` | 可访问指定机房 | 规则: - 仅配置数据中心范围时,该数据中心下的机房可访问。 - 仅配置机房范围时,指定机房可访问。 - 两种范围同时存在时,数据中心和机房必须同时匹配。 - 三个字段均未提供时,3D 接口返回“登录凭证缺少机房数据权限”。 - 前端不能通过自定义请求头或查询参数扩大数据范围。 ### 2.4 坐标和尺寸 坐标系约定: - `X`:机房长度方向。 - `Y`:高度方向。 - `Z`:机房宽度方向。 - 场景坐标、机房尺寸和独立设备尺寸单位均为米。 - `position_x/y/z` 表示物体底面中心点,不是包围盒中心点。 - 设备旋转角度单位为度,合法范围为 `[0, 360)`,旋转顺序为 X、Y、Z。 - 机柜只允许绕 Y 轴旋转。 - 传入的小数会四舍五入到两位后再校验和保存。 机柜尺寸: - `width_mm`、`depth_mm` 的单位是毫米。 - `height` 的单位是 U。 - 后端进行空间碰撞校验时,机柜高度按 `height × 0.04445` 米计算。 边界范围: ```text X: 0 ~ scene_length Y: 0 ~ scene_height Z: 0 ~ scene_width ``` 后端会对机柜和机房内独立设备做完整三维有向包围盒校验,包括越界、机柜与机柜、机柜与独立设备、独立设备与独立设备的重叠。物体边界接触允许,空间重叠不允许。 机柜内设备不参与场景包围盒碰撞,其位置由机柜和 U 位约束。 ### 2.5 布局版本和并发控制 每个机房包含 `layout_version`。以下写接口都必须提交当前版本: - 保存机房 3D 配置。 - 保存机柜布局。 - 保存设备位置。 - 解除设备位置。 每次成功写入后版本加一,响应会返回新的 `layout_version`。 前端处理规则: 1. 加载场景后保存 `room.layout_version`。 2. 同一个机房的写请求串行发送。 3. 写入成功后,用响应中的 `layout_version` 更新本地版本。 4. 收到“布局版本已变化”时,重新调用场景接口获取最新数据,不覆盖服务端的新布局。 ## 3. 接口总览 ### 3.1 3D 核心接口 | 方法 | 路径 | 用途 | | --- | --- | --- | | GET | `/Assets/v1/three-d/export` | 获取权限范围内全部 3D 场景 | | GET | `/Assets/v1/three-d/rooms/:room_id/scene` | 获取单个机房场景 | | PUT | `/Assets/v1/three-d/rooms/:room_id/config` | 保存机房尺寸及初始机柜位置 | | PUT | `/Assets/v1/three-d/rooms/:room_id/layout` | 批量保存机柜位置 | | PUT | `/Assets/v1/three-d/rooms/:room_id/devices/:asset_id/placement` | 保存设备的机柜或机房位置 | | DELETE | `/Assets/v1/three-d/rooms/:room_id/devices/:asset_id/placement` | 解除设备位置 | | GET | `/Assets/v1/three-d/rooms/:room_id/signals` | 获取机房设备状态和告警摘要 | | GET | `/Assets/v1/three-d/devices/:asset_id/observability` | 获取设备状态、指标和告警详情 | ### 3.2 资源绑定接口 | 方法 | 路径 | 用途 | | --- | --- | --- | | GET | `/DC-Control/v1/resources/options` | 查询可绑定监控资源选项 | | POST | `/Assets/v1/asset/resource/link` | 绑定资产与监控资源 | | GET | `/Assets/v1/asset/resource/:asset_id` | 查询资产资源绑定 | | DELETE | `/Assets/v1/asset/resource/:asset_id` | 解除资产资源绑定 | ## 4. 场景数据结构 ### 4.1 `RoomScene` ```json { "room": { "id": 1, "datacenter_id": 1, "floor_id": 2, "name": "一号机房", "code": "ROOM-001", "scene_length": 20, "scene_width": 12, "scene_height": 4, "layout_version": 4 }, "racks": [], "room_devices": [], "summary": { "rack_count": 0, "unit_count": 0, "rack_device_count": 0, "room_device_count": 0, "device_count": 0 } } ``` ### 4.2 `SceneRack` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | number | 机柜 ID | | `name` | string | 机柜名称 | | `code` | string | 机柜编码 | | `row` | number | 业务行号,不直接参与空间校验 | | `column` | number | 业务列号,不直接参与空间校验 | | `height` | number | 机柜高度,单位 U | | `width_mm` | number | 机柜宽度,毫米 | | `depth_mm` | number | 机柜深度,毫米 | | `status` | string | 机柜状态 | | `transform` | object | 三维位置和旋转 | | `utilization_rate` | number | U 位使用率百分比,占用和预留 U 位均计入 | | `units` | array | 全部 U 位,按 `unit_number` 升序 | | `devices` | array | 机柜中已上架设备,每台设备只出现一次 | 机柜 `transform` 固定包含全部轴,当前仅 `rotation_y` 可写: ```json { "position_x": 2, "position_y": 0, "position_z": 3, "rotation_x": 0, "rotation_y": 90, "rotation_z": 0 } ``` U 位结构: ```json { "id": 1001, "unit_number": 10, "status": "occupied", "asset_id": 201 } ``` `status` 可见值包括: - `available`:可用。 - `occupied`:已占用。 - `reserved`:已预留。 - `disabled`:已禁用。 U 位编号从 1 开始,自下向上递增。多 U 设备会在连续多个 `units` 项中使用相同 `asset_id`,但只在 `rack.devices` 中出现一次。 ### 4.3 `SceneDevice` | 字段 | 类型 | 说明 | | --- | --- | --- | | `asset_id` | number | 资产 ID | | `asset_code` | string | 资产编码 | | `asset_name` | string | 资产名称 | | `category_id` | number/null | 资产分类 ID | | `category_code` | string | 资产分类编码 | | `category_name` | string | 资产分类名称 | | `placement_type` | string | `rack` 或 `room` | | `rack_id` | number/null | 所属机柜,独立设备为 `null` | | `unit_start` | number/null | 起始 U 位 | | `unit_end` | number/null | 结束 U 位 | | `occupied_units` | number | 占用 U 位数;独立设备为 0 | | `power_consumption` | number | 机柜设备功耗,单位 W | | `transform` | object/省略 | 独立设备的三维位置,机柜设备不返回 | | `size` | object/省略 | 独立设备的尺寸,机柜设备不返回 | | `bindings` | array | 绑定的监控资源 | 独立设备尺寸结构: ```json { "width": 1.2, "height": 2, "depth": 0.8 } ``` 监控资源绑定结构: ```json { "resource_uid": "room_device:ac-01", "resource_category": "room_device", "service_identity": "ac-01", "display_name": "一号智能空调", "business_system_id": null } ``` ## 5. 获取单个机房场景 ```http GET /Assets/v1/three-d/rooms/{room_id}/scene ``` 路径参数: | 参数 | 类型 | 说明 | | --- | --- | --- | | `room_id` | 正整数 | 机房 ID | 成功响应的 `details`: ```json { "room": { "id": 1, "datacenter_id": 1, "floor_id": 2, "name": "一号机房", "code": "ROOM-001", "scene_length": 20, "scene_width": 12, "scene_height": 4, "layout_version": 4 }, "racks": [ { "id": 101, "name": "A01机柜", "code": "RACK-A01", "row": 1, "column": 1, "height": 42, "width_mm": 600, "depth_mm": 1000, "status": "in_use", "transform": { "position_x": 2, "position_y": 0, "position_z": 2, "rotation_x": 0, "rotation_y": 0, "rotation_z": 0 }, "utilization_rate": 4.761904761904762, "units": [ { "id": 1001, "unit_number": 1, "status": "available", "asset_id": null }, { "id": 1010, "unit_number": 10, "status": "occupied", "asset_id": 201 } ], "devices": [ { "asset_id": 201, "asset_code": "SRV-001", "asset_name": "应用服务器01", "category_id": 5, "category_code": "server", "category_name": "服务器", "placement_type": "rack", "rack_id": 101, "unit_start": 10, "unit_end": 11, "occupied_units": 2, "power_consumption": 850, "bindings": [ { "resource_uid": "server:srv-001", "resource_category": "server", "service_identity": "srv-001", "display_name": "应用服务器01", "business_system_id": null } ] } ] } ], "room_devices": [ { "asset_id": 301, "asset_code": "AC-001", "asset_name": "一号智能空调", "category_id": 12, "category_code": "air_conditioner", "category_name": "智能空调", "placement_type": "room", "rack_id": null, "unit_start": null, "unit_end": null, "occupied_units": 0, "power_consumption": 0, "transform": { "position_x": 8, "position_y": 0, "position_z": 2, "rotation_x": 0, "rotation_y": 90, "rotation_z": 0 }, "size": { "width": 1.2, "height": 2, "depth": 0.8 }, "bindings": [ { "resource_uid": "room_device:ac-01", "resource_category": "room_device", "service_identity": "ac-01", "display_name": "一号智能空调", "business_system_id": null } ] } ], "summary": { "rack_count": 1, "unit_count": 42, "rack_device_count": 1, "room_device_count": 1, "device_count": 2 } } ``` 说明: - 示例为便于阅读只展示了部分 U 位,实际响应返回机柜全部 U 位。 - 如果机房尚未完成 3D 配置,三个场景尺寸可能为 0。前端应进入初始化配置流程。 - 场景接口不包含实时运行状态和告警,加载完成后再调用机房信号接口叠加状态。 ## 6. 保存机房 3D 配置 ```http PUT /Assets/v1/three-d/rooms/{room_id}/config ``` 请求体: ```json { "expected_version": 1, "scene_length": 20, "scene_width": 12, "scene_height": 4, "racks": [ { "rack_id": 101, "row": 1, "column": 1, "position_x": 2, "position_y": 0, "position_z": 2, "rotation_y": 0 } ] } ``` 字段说明: | 字段 | 必填 | 说明 | | --- | --- | --- | | `expected_version` | 是 | 当前布局版本,必须大于 0 | | `scene_length` | 是 | 机房长度,米,必须大于 0 | | `scene_width` | 是 | 机房宽度,米,必须大于 0 | | `scene_height` | 是 | 机房高度,米,必须大于 0 | | `racks` | 条件必填 | 机柜位置列表 | 首次配置规则: - 如果机房已有机柜,必须一次提交该机房全部机柜的位置。 - 同一个 `rack_id` 不能重复。 - 所有机柜必须属于当前机房。 - 保存前会统一验证全部机柜是否越界或重叠。 已配置机房再次修改尺寸时,`racks` 可以为空或只包含需要同步调整的机柜,但后端仍会使用新尺寸验证全部已有机柜和独立设备。 成功响应的 `details`: ```json { "room_id": 1, "layout_version": 2 } ``` ## 7. 批量保存机柜布局 用于机柜拖拽结束后保存一个或多个机柜的位置。 ```http PUT /Assets/v1/three-d/rooms/{room_id}/layout ``` 请求体: ```json { "expected_version": 2, "racks": [ { "rack_id": 101, "row": 1, "column": 1, "position_x": 3.25, "position_y": 0, "position_z": 2.5, "rotation_y": 90 }, { "rack_id": 102, "row": 1, "column": 2, "position_x": 5, "position_y": 0, "position_z": 2.5, "rotation_y": 90 } ] } ``` 规则: - `racks` 不能为空,可以只提交本次变化的机柜。 - `position_x/y/z` 不能小于 0。 - `rotation_y` 范围为 `[0, 360)`。 - 后端将未提交机柜的原位置和本次候选位置一起进行全场景校验。 - 任一机柜失败时整批请求回滚,不会保存部分结果。 成功响应的 `details`: ```json { "room_id": 1, "layout_version": 3 } ``` ## 8. 保存设备位置 ```http PUT /Assets/v1/three-d/rooms/{room_id}/devices/{asset_id}/placement ``` 同一接口通过 `placement_type` 区分机柜设备和机房内独立设备。 ### 8.1 放入机柜或调整上架位置 请求体: ```json { "expected_version": 3, "placement_type": "rack", "rack_id": 101, "start_unit": 10, "occupied_units": 2, "power_consumption": 850 } ``` | 字段 | 必填 | 说明 | | --- | --- | --- | | `expected_version` | 是 | 当前布局版本 | | `placement_type` | 是 | 固定为 `rack` | | `rack_id` | 是 | 目标机柜 ID | | `start_unit` | 是 | 起始 U 位,从 1 开始 | | `occupied_units` | 是 | 连续占用 U 位数,必须大于 0 | | `power_consumption` | 是 | 设备功耗,单位 W,可为 0,不能为负数 | 校验规则: - 目标机柜必须属于路径中的机房。 - U 位范围必须完整、连续且可用。 - 调整同一设备的位置时,设备当前占用的 U 位可以作为本次目标位置的一部分。 - 机柜配置了 `power_capacity` 时,会校验调整后的剩余电力容量。机柜容量及已用电力单位为 kW,请求功耗单位为 W。 - 从一个机柜移动到另一个机柜时,原 U 位和原机柜功耗会在同一事务中释放。 ### 8.2 放置在机房内 智能空调、摄像头、智能插座等不在机柜中的设备使用 `room`: ```json { "expected_version": 3, "placement_type": "room", "position_x": 8, "position_y": 0, "position_z": 2, "rotation_x": 0, "rotation_y": 90, "rotation_z": 0, "scene_width": 1.2, "scene_height": 2, "scene_depth": 0.8 } ``` | 字段 | 必填 | 说明 | | --- | --- | --- | | `expected_version` | 是 | 当前布局版本 | | `placement_type` | 是 | 固定为 `room` | | `position_x/y/z` | 是 | 设备底面中心坐标,米,不能为负数 | | `rotation_x/y/z` | 是 | 三轴旋转角度,范围 `[0, 360)` | | `scene_width` | 是 | 设备本地 X 轴尺寸,米,必须大于 0 | | `scene_height` | 是 | 设备本地 Y 轴尺寸,米,必须大于 0 | | `scene_depth` | 是 | 设备本地 Z 轴尺寸,米,必须大于 0 | 保存时会校验设备是否越界,以及是否与机柜或其他独立设备重叠。从机柜移到机房内时,原 U 位和功耗会在同一事务中释放。 ### 8.3 跨机房限制 已经放置在其他机房的设备不能直接移动到当前机房。必须先调用原机房的解除位置接口,再使用当前机房的 `layout_version` 放置。 ### 8.4 成功响应 两种放置方式的成功响应结构相同: ```json { "room_id": 1, "asset_id": 201, "placement_type": "rack", "layout_version": 4 } ``` ## 9. 解除设备位置 ```http DELETE /Assets/v1/three-d/rooms/{room_id}/devices/{asset_id}/placement ``` 请求体: ```json { "expected_version": 4 } ``` 规则: - 设备必须已放置在路径指定的机房。 - 机柜设备会释放原 U 位和机柜功耗。 - 解除后资产的机房、机柜、U 位、三维坐标、旋转和尺寸均清空。 - 解除后的 `placement_type` 为 `unplaced`。 成功响应的 `details`: ```json { "room_id": 1, "asset_id": 201, "placement_type": "unplaced", "layout_version": 5 } ``` ## 10. 获取机房设备信号 该接口用于给整个 3D 场景批量叠加设备颜色、状态标识和告警角标。 ```http GET /Assets/v1/three-d/rooms/{room_id}/signals ``` 成功响应的 `details`: ```json { "room_id": 1, "signals": [ { "asset_id": 201, "status": "warning", "active_alert_count": 2, "highest_alert_severity": { "name": "严重", "code": "critical", "color": "#F5222D", "priority": 1 }, "resources": [ { "resource_uid": "server:srv-001", "resource_category": "server", "service_identity": "srv-001", "display_name": "应用服务器01", "status": "warning", "metrics": [] } ], "alerts": [ { "resource_uid": "server:srv-001", "active_count": 2, "highest_severity": { "name": "严重", "code": "critical", "color": "#F5222D", "priority": 1 }, "alerts": [ { "id": 9001, "alert_name": "CPU使用率过高", "summary": "CPU使用率持续超过阈值", "severity": { "name": "严重", "code": "critical", "color": "#F5222D", "priority": 1 }, "status": "firing", "starts_at": "2026-07-31T09:00:00+08:00", "last_seen_at": "2026-07-31T09:05:00+08:00", "updated_at": "2026-07-31T09:05:00+08:00" } ] } ] } ] } ``` 信号状态取值: | 状态 | 含义 | | --- | --- | | `unbound` | 资产没有绑定任何监控资源 | | `unknown` | 已绑定资源,但没有可用运行数据,或出现未识别状态 | | `healthy` | 所有可用资源状态正常 | | `warning` | 至少一个资源为警告或降级,且没有异常资源 | | `abnormal` | 至少一个资源为离线、错误或严重异常 | 后端状态映射: - 异常:`offline`、`down`、`error`、`critical`、`unhealthy`、`failed`。 - 警告:`warning`、`degraded`。 - 健康:`online`、`up`、`healthy`、`normal`、`running`、`success`。 告警规则: - `active_alert_count` 是该资产全部绑定资源的活动告警数量之和。 - `highest_alert_severity` 取 `priority` 数字最小的最高级别。 - 机房信号接口每个资源最多返回最近 3 条活动告警。 - 活动告警包括 `pending`、`firing`、`acked`、`silenced`、`suppressed`,已恢复告警不返回。 - 该接口不查询指标,因此资源的 `metrics` 为 `[]`。 当前 3D 接口没有 WebSocket 推送。前端需要刷新状态时,应轮询机房信号接口,不要为场景内每台设备并发调用设备详情接口。 ## 11. 获取设备可观测详情 用户在 3D 场景选中设备后调用: ```http GET /Assets/v1/three-d/devices/{asset_id}/observability ``` 成功响应的 `details`: ```json { "device": { "asset_id": 201, "asset_code": "SRV-001", "asset_name": "应用服务器01", "category_id": 5, "category_code": "server", "category_name": "服务器", "placement_type": "rack", "rack_id": 101, "unit_start": 10, "unit_end": 11, "occupied_units": 2, "power_consumption": 850, "bindings": [ { "resource_uid": "server:srv-001", "resource_category": "server", "service_identity": "srv-001", "display_name": "应用服务器01", "business_system_id": null } ] }, "resources": [ { "resource_uid": "server:srv-001", "resource_category": "server", "service_identity": "srv-001", "display_name": "应用服务器01", "status": "online", "metrics_at": "2026-07-31T09:05:00+08:00", "metrics": [ { "name": "cpu_usage", "value": 63.5, "unit": "%", "type": "gauge", "timestamp": "2026-07-31T09:05:00+08:00" } ] } ], "alerts": [ { "resource_uid": "server:srv-001", "active_count": 1, "highest_severity": { "name": "警告", "code": "warning", "color": "#FAAD14", "priority": 2 }, "alerts": [] } ] } ``` 说明: - `device` 使用与场景接口相同的 `SceneDevice` 结构。 - `resources` 返回每个绑定资源的当前状态和最近一批指标。 - 没有指标的资源返回 `metrics: []`,并省略 `metrics_at`。 - 每个资源最多返回最近 20 条活动告警。 - 资产未绑定监控资源时,`resources` 和 `alerts` 均为 `[]`。 ## 12. 导出全部 3D 场景 ```http GET /Assets/v1/three-d/export ``` 用于一次获取当前 JWT 数据范围内已启用的数据中心和机房场景。它不包含实时状态、指标和告警。 成功响应的 `details`: ```json { "datacenters": [ { "id": 1, "name": "北京数据中心", "code": "DC-BJ-01", "status": "running", "latitude": "39.9042", "longitude": "116.4074", "rooms": [] } ], "summary": { "datacenter_count": 1, "room_count": 2, "rack_count": 30, "unit_count": 1260, "device_count": 150 } } ``` `rooms` 中每一项都是完整的 `RoomScene`。 ## 13. 资产与监控资源绑定 设备只有绑定 `dc-control` 统一监控资源后,3D 页面才能展示该设备的实时状态、指标和活动告警。一个资产可以绑定多个资源,一个 `resource_uid` 在全局只能绑定一个资产。 ### 13.1 查询可绑定资源 ```http GET /DC-Control/v1/resources/options?resource_category=room_device ``` 查询参数: | 参数 | 必填 | 说明 | | --- | --- | --- | | `resource_category` | 否 | 按资源分类过滤;不传时返回全部分类,最多 500 条 | 成功响应的 `details`: ```json { "list": [ { "id": 501, "label": "一号智能空调", "value": "room_device:ac-01" } ], "count": 1 } ``` 其中 `value` 就是绑定接口需要的 `resource_uid`。 当前可查询运行状态的资源分类包括: - `host` - `server` - `pc` - `database` - `middleware` - `url` - `network` - `security` - `storage` - `room_device` 智能空调、监控摄像头、智能插座等机房设备统一使用 `room_device` 资源分类,具体设备类型由 `dc-control` 中的机房设备分类区分。 ### 13.2 绑定资源 ```http POST /Assets/v1/asset/resource/link ``` 请求体: ```json { "asset_id": 301, "resource_uid": "room_device:ac-01", "display_name": "一号智能空调", "business_system_id": null } ``` | 字段 | 必填 | 说明 | | --- | --- | --- | | `asset_id` | 是 | 资产 ID | | `resource_uid` | 是 | 格式为 `category:identity` | | `display_name` | 否 | 为空时使用 `dc-control` 中的资源名称 | | `business_system_id` | 否 | 关联业务系统 ID | 后端会实时调用 `dc-control` 验证资源存在。重复提交同一资产和资源会更新绑定;资源已绑定其他资产时返回错误。 成功响应的 `details` 包含绑定记录,例如: ```json { "id": 100, "created_at": "2026-07-31T09:00:00+08:00", "updated_at": "2026-07-31T09:00:00+08:00", "asset_id": 301, "resource_uid": "room_device:ac-01", "resource_category": "room_device", "service_identity": "ac-01", "display_name": "一号智能空调", "business_system_id": null, "health_status": "online", "alert_status": "none", "created_by": "admin", "updated_by": "admin" } ``` 实时页面不要使用绑定记录中的 `health_status` 或 `alert_status` 作为实时值,应使用机房信号或设备可观测接口。 ### 13.3 查询绑定 ```http GET /Assets/v1/asset/resource/{asset_id} ``` 成功响应的 `details` 是绑定记录数组: ```json [ { "id": 100, "asset_id": 301, "resource_uid": "room_device:ac-01", "resource_category": "room_device", "service_identity": "ac-01", "display_name": "一号智能空调", "business_system_id": null, "health_status": "online", "alert_status": "none", "created_by": "admin", "updated_by": "admin", "created_at": "2026-07-31T09:00:00+08:00", "updated_at": "2026-07-31T09:00:00+08:00" } ] ``` ### 13.4 解除绑定 ```http DELETE /Assets/v1/asset/resource/{asset_id}?resource_uid=room_device%3Aac-01 ``` `resource_uid` 必须放在查询参数中,并进行 URL 编码。 成功响应的 `details`: ```json "解除绑定成功" ``` ## 14. 待放置资产 当前没有单独的 3D 待放置资产接口。可使用现有资产下拉接口: ```http GET /Assets/v1/asset/all?keyword=空调 ``` 响应 `details` 是资产数组,前端可按以下条件筛选: ```text placement_type === "unplaced" ``` `placement_type` 取值: - `unplaced`:未放置。 - `rack`:已放入机柜。 - `room`:已放置在机房内。 前端筛选只用于交互,最终能否放置仍由设备位置接口的数据权限、版本、机房归属、U 位、边界和碰撞校验决定。 ## 15. 前端推荐调用流程 ### 15.1 打开机房 1. 调用 `GET /three-d/rooms/{room_id}/scene` 加载几何场景。 2. 保存 `room.layout_version`。 3. 如果机房尺寸为 0,进入初始化配置;否则渲染机房、机柜、机柜设备和独立设备。 4. 调用 `GET /three-d/rooms/{room_id}/signals` 叠加状态颜色和告警角标。 ### 15.2 拖拽机柜 1. 前端本地计算候选坐标并更新预览。 2. 拖拽结束后调用机柜布局接口,可批量提交本次变更。 3. 成功后更新本地 `layout_version`;失败则恢复或重新加载场景。 ### 15.3 设备上架或移动 1. 从待放置资产中选择设备,或选择场景内已有设备。 2. 放入机柜时提交 `rack` 请求和连续 U 位区间。 3. 放在机房内时提交 `room` 请求、完整坐标、旋转角度和物体尺寸。 4. 成功后更新 `layout_version`,再按需刷新场景和信号。 ### 15.4 查看设备状态 1. 场景批量状态使用机房信号接口。 2. 用户点击设备时调用设备可观测接口。 3. 设备没有绑定资源时显示“未绑定监控资源”,不要显示为离线。 ### 15.5 版本冲突 遇到以下任一消息时重新加载场景: ```text 布局版本已变化,当前版本为 N 布局版本已变化,请重新加载 ``` 不要用旧坐标自动覆盖新场景。需要保留用户拖拽意图时,应先获取新场景,再由用户确认重新应用。 ## 16. 常见失败场景 | `message` 特征 | 前端处理建议 | | --- | --- | | `登录凭证缺少机房数据权限` | 提示权限配置问题,不重试写请求 | | `无权访问该机房`、`无权移动该资产` | 提示无权限并退出编辑状态 | | `布局版本已变化` | 重新加载场景和版本 | | `机房三维长度、宽度和高度必须大于0` | 校验尺寸输入 | | `首次配置...必须同时提交...全部机柜的位置` | 补齐当前机房全部机柜 | | `超出机房三维边界` | 恢复物体到合法位置 | | `发生空间重叠` | 调整位置后重试 | | `目标U位...不可用` | 刷新场景或重新选择连续 U 位 | | `目标机柜剩余电力容量不足` | 调整机柜或功耗值 | | `资产属于其他机房` | 先在原机房解除位置 | | `环境变量 DC_CONTROL_BASE_URL 未配置` | 后端部署配置问题 | | `环境变量 ALERT_BASE_URL 未配置` | 后端部署配置问题 | | `查询 dc-control 设备状态失败` | 状态聚合依赖异常,保留场景并提示状态暂不可用 | | `查询 alert 活动告警失败` | 告警聚合依赖异常,保留场景并提示告警暂不可用 | 写请求是事务性的。任一校验或数据库操作失败时,不会只保存部分机柜、U 位或设备位置。 ## 17. 后端聚合依赖 以下接口由 `Assets` 后台调用,前端不直接调用: | 服务 | 内部接口 | 用途 | | --- | --- | --- | | `dc-control` | `POST /DC-Control/v1/resources/runtime` | 按资源 UID 批量读取状态和最新指标 | | `alert` | `POST /Alert/v1/record/active/by-resources` | 按资源 UID 批量读取活动告警 | `Assets` 会转发前端请求中的 `Authorization`。聚合请求按每批 500 个资源处理,单个下游请求超时为 8 秒。 部署 `Assets` 时需要配置: ```text DC_CONTROL_BASE_URL= ALERT_BASE_URL= ``` ## 18. 代码依据 本文档未读取项目既有文档,接口事实来自以下实际代码: - `assets/internal/routers/register.go` - `assets/internal/logic/three_d/types.go` - `assets/internal/logic/three_d/scene.go` - `assets/internal/logic/three_d/layout.go` - `assets/internal/logic/three_d/placement.go` - `assets/internal/logic/three_d/geometry.go` - `assets/internal/logic/three_d/integration.go` - `assets/internal/logic/three_d/scope.go` - `assets/internal/logic/asset/resource_binding.go` - `assets/internal/models/assets_asset.go` - `assets/internal/models/assets_asset_resource_binding.go` - `assets/internal/models/assets_rack.go` - `assets/internal/models/assets_room.go` - `dc-control/internal/routers/register.go` - `dc-control/internal/logic/controllers/resource_controller.go` - `dc-control/internal/logic/controllers/resource_runtime_controller.go` - `dc-control/internal/logic/resource_runtime/runtime.go` - `alert/internal/routers/register.go` - `alert/internal/logic/record/resource.go` - `bsm-sdk/core@v0.1.7/infra/response.go`