From eb11e7ed1f2888bd1ea38bfd62659776d5ee6338 Mon Sep 17 00:00:00 2001 From: 16337 <1633794139@qq.com> Date: Mon, 9 Feb 2026 10:25:03 +0800 Subject: [PATCH] =?UTF-8?q?refactor(aiot-device):=20=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E6=95=B4=E7=90=86=E8=AE=BE=E5=A4=87=20API=20=E5=B1=82=E5=92=8C?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 按功能分区:摄像头管理、ROI 区域、算法管理、算法绑定、配置推送 - Camera 接口扩展完整字段(streamKey、createTime 等) - 新增 PageResult、MediaServer 类型定义 - getSnapUrl 改为 async,通过 query param 传递 access-token 支持认证截图 - 所有 API 函数添加精确的泛型返回类型 Co-Authored-By: Claude Opus 4.6 --- apps/web-antd/src/api/aiot/device/index.ts | 183 +++++++++++++-------- 1 file changed, 117 insertions(+), 66 deletions(-) diff --git a/apps/web-antd/src/api/aiot/device/index.ts b/apps/web-antd/src/api/aiot/device/index.ts index f82f868ea..db4d240e3 100644 --- a/apps/web-antd/src/api/aiot/device/index.ts +++ b/apps/web-antd/src/api/aiot/device/index.ts @@ -1,10 +1,49 @@ +/** + * AIoT 设备管理 API + * + * 所有请求通过 wvpRequestClient 发送到 WVP 视频平台后端, + * 由 Vite 代理按路径分发并 rewrite: + * /aiot/device/proxy/* → WVP /api/proxy/* + * /aiot/device/user/* → WVP /api/user/* + * /aiot/device/server/* → WVP /api/server/media_server/* + * /aiot/device/* → WVP /api/ai/* + */ import { useAppConfig } from '@vben/hooks'; -import { wvpRequestClient } from '#/api/aiot/request'; +import { getWvpToken, wvpRequestClient } from '#/api/aiot/request'; const { apiURL } = useAppConfig(import.meta.env, import.meta.env.PROD); +// ==================== 类型定义 ==================== + export namespace AiotDeviceApi { + /** 分页响应结构 */ + export interface PageResult { + list: T[]; + total: number; + } + + /** 摄像头(拉流代理) */ + export interface Camera { + id?: number; + type?: string; // 'default' | 'ffmpeg' + app?: string; + stream?: string; + srcUrl?: string; + timeout?: number; + rtspType?: string; // '0'=TCP, '1'=UDP, '2'=Multicast + enable?: boolean; + enableAudio?: boolean; + enableMp4?: boolean; + enableDisableNoneReader?: boolean; + relatesMediaServerId?: string; + ffmpegCmdKey?: string; + pulling?: boolean; + mediaServerId?: string; + streamKey?: string; + createTime?: string; + } + /** ROI 区域 */ export interface Roi { id?: number; @@ -12,7 +51,7 @@ export namespace AiotDeviceApi { cameraId?: string; deviceId?: string; name?: string; - roiType?: string; // rectangle | polygon + roiType?: string; // 'rectangle' | 'polygon' coordinates?: string; color?: string; priority?: number; @@ -21,7 +60,7 @@ export namespace AiotDeviceApi { algorithms?: RoiAlgoBinding[]; } - /** ROI 算法绑定(详情里的嵌套结构) */ + /** ROI 算法绑定(详情嵌套结构) */ export interface RoiAlgoBinding { bind: AlgoBind; algorithm?: Algorithm; @@ -32,11 +71,11 @@ export namespace AiotDeviceApi { bindId?: string; roiId?: string; algoCode?: string; - enabled?: number; + enabled?: number; // 0 | 1 params?: string; } - /** 算法 */ + /** 算法定义 */ export interface Algorithm { id?: number; algoCode?: string; @@ -46,36 +85,38 @@ export namespace AiotDeviceApi { paramSchema?: string; } - /** 摄像头(拉流代理) */ - export interface Camera { - id?: number; - type?: string; // default | ffmpeg - app?: string; - stream?: string; - srcUrl?: string; - timeout?: number; - rtspType?: string; // 0=TCP, 1=UDP, 2=Multicast - enable?: boolean; - enableAudio?: boolean; - enableMp4?: boolean; - enableDisableNoneReader?: boolean; - relatesMediaServerId?: string; - ffmpegCmdKey?: string; - pulling?: boolean; - mediaServerId?: string; + /** 媒体服务器 */ + export interface MediaServer { + id: string; + ip: string; } } -// ==================== 摄像头管理 API ==================== +// ==================== 摄像头管理 ==================== -/** 获取摄像头列表 */ +/** 摄像头列表(分页) */ export function getCameraList(params: { page: number; count: number; query?: string; pulling?: boolean; }) { - return wvpRequestClient.get('/aiot/device/proxy/list', { params }); + return wvpRequestClient.get>( + '/aiot/device/proxy/list', + { params }, + ); +} + +/** 保存摄像头(新增/编辑,有 id 为编辑) */ +export function saveCamera(data: Partial) { + return wvpRequestClient.post('/aiot/device/proxy/save', data); +} + +/** 删除摄像头 */ +export function deleteCamera(id: number) { + return wvpRequestClient.delete('/aiot/device/proxy/delete', { + params: { id }, + }); } /** 开始拉流 */ @@ -88,26 +129,16 @@ export function stopCamera(id: number) { return wvpRequestClient.get('/aiot/device/proxy/stop', { params: { id } }); } -/** 保存摄像头(新增/编辑) */ -export function saveCamera(data: Partial) { - return wvpRequestClient.post('/aiot/device/proxy/save', data); -} - -/** 删除摄像头 */ -export function deleteCamera(id: number) { - return wvpRequestClient.delete('/aiot/device/proxy/delete', { - params: { id }, - }); -} - -/** 获取在线媒体服务器列表 */ +/** 在线媒体服务器列表 */ export function getMediaServerList() { - return wvpRequestClient.get('/aiot/device/server/online/list'); + return wvpRequestClient.get( + '/aiot/device/server/online/list', + ); } -// ==================== ROI 区域管理 API ==================== +// ==================== ROI 区域管理 ==================== -/** 获取 ROI 列表(分页) */ +/** ROI 列表(分页) */ export function getRoiList(params: { page: number; count: number; @@ -115,22 +146,26 @@ export function getRoiList(params: { deviceId?: string; query?: string; }) { - return wvpRequestClient.get('/aiot/device/roi/list', { params }); + return wvpRequestClient.get>( + '/aiot/device/roi/list', + { params }, + ); } -/** 获取 ROI 详情 */ +/** ROI 详情(含算法绑定) */ export function getRoiDetail(id: number) { - return wvpRequestClient.get(`/aiot/device/roi/${id}`); + return wvpRequestClient.get(`/aiot/device/roi/${id}`); } -/** 获取某摄像头的所有 ROI */ +/** 某摄像头的所有 ROI */ export function getRoiByCameraId(cameraId: string) { - return wvpRequestClient.get('/aiot/device/roi/channel', { - params: { cameraId }, - }); + return wvpRequestClient.get( + '/aiot/device/roi/channel', + { params: { cameraId } }, + ); } -/** 保存 ROI */ +/** 保存 ROI(新增/编辑) */ export function saveRoi(data: Partial) { return wvpRequestClient.post('/aiot/device/roi/save', data); } @@ -140,12 +175,34 @@ export function deleteRoi(roiId: string) { return wvpRequestClient.delete(`/aiot/device/roi/delete/${roiId}`); } -/** 获取截图 URL */ -export function getSnapUrl(app: string, stream: string) { - return `${apiURL}/aiot/device/roi/snap?app=${encodeURIComponent(app)}&stream=${encodeURIComponent(stream)}&t=${Date.now()}`; +/** + * 获取摄像头截图 URL + * 截图接口需要认证,通过 query param 传递 access-token + */ +export async function getSnapUrl( + app: string, + stream: string, +): Promise { + const token = await getWvpToken(); + return ( + `${apiURL}/aiot/device/roi/snap` + + `?app=${encodeURIComponent(app)}` + + `&stream=${encodeURIComponent(stream)}` + + `&access-token=${encodeURIComponent(token)}` + + `&t=${Date.now()}` + ); } -// ==================== 算法绑定 API ==================== +// ==================== 算法管理 ==================== + +/** 算法列表 */ +export function getAlgorithmList() { + return wvpRequestClient.get( + '/aiot/device/algorithm/list', + ); +} + +// ==================== 算法绑定 ==================== /** 绑定算法到 ROI */ export function bindAlgo(data: { roiId: string; algoCode: string }) { @@ -159,7 +216,7 @@ export function unbindAlgo(bindId: string) { }); } -/** 更新算法参数 */ +/** 更新算法绑定参数 */ export function updateAlgoParams(data: { bindId: string; params?: string; @@ -168,14 +225,7 @@ export function updateAlgoParams(data: { return wvpRequestClient.post('/aiot/device/roi/updateAlgoParams', data); } -// ==================== 算法管理 API ==================== - -/** 获取算法列表 */ -export function getAlgorithmList() { - return wvpRequestClient.get('/aiot/device/algorithm/list'); -} - -// ==================== 配置推送 API ==================== +// ==================== 配置推送 ==================== /** 推送配置到边缘端 */ export function pushConfig(cameraId: string) { @@ -184,9 +234,10 @@ export function pushConfig(cameraId: string) { }); } -/** 导出配置 */ +/** 导出摄像头配置 JSON */ export function exportConfig(cameraId: string) { - return wvpRequestClient.get('/aiot/device/config/export', { - params: { cameraId }, - }); + return wvpRequestClient.get>( + '/aiot/device/config/export', + { params: { cameraId } }, + ); }