fix(aiot): 回退告警 API 到 Service 后端,修复截图 URL 端点

告警问题:
- 告警数据存储在 FastAPI Service 的 alert_platform.db 中
- 之前错误地切换到 wvpRequestClient(WVP 后端的 wvp_ai_alert 表)
- 回退到 requestClient + /aiot/alarm/alert/* 路径恢复数据

截图问题:
- /snap/image 代理端点在 Redis+DB 都无缓存时返回 404
- 回退到 /snap 端点,利用其 Accept: image/* 自动 302 重定向逻辑
- 保留 force 参数支持手动刷新截图

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-04 11:05:03 +08:00
parent 0d56b2f221
commit 284f2b8d87
3 changed files with 37 additions and 59 deletions

View File

@@ -1,12 +1,11 @@
import type { PageParam, PageResult } from '@vben/request';
import { wvpRequestClient } from '#/api/aiot/request';
import { requestClient } from '#/api/request';
export namespace AiotAlarmApi {
/** AI 告警 VO */
export interface Alert {
id?: number | string;
alertId?: string;
alarmId?: string;
alertNo?: string;
cameraId?: string;
@@ -24,7 +23,6 @@ export namespace AiotAlarmApi {
triggerTime?: string;
message?: string;
bbox?: string;
imagePath?: string;
snapshotUrl?: string;
ossUrl?: string;
status?: string;
@@ -36,11 +34,9 @@ export namespace AiotAlarmApi {
lastFrameTime?: string;
workOrderId?: number;
aiAnalysis?: Record<string, any>;
receivedAt?: string;
createdAt?: string;
updatedAt?: string;
logInfo?: AlertLogInfo;
extraData?: string;
}
/** 告警日志信息 */
@@ -78,20 +74,20 @@ export namespace AiotAlarmApi {
}
}
// ==================== 告警管理 APIWVP 后端)====================
// ==================== 告警管理 API ====================
/** 分页查询告警列表 */
export function getAlertPage(params: PageParam) {
return wvpRequestClient.get<PageResult<AiotAlarmApi.Alert>>(
'/aiot/device/alert/list',
{ params: { page: params.pageNo, count: params.pageSize, ...params } },
return requestClient.get<PageResult<AiotAlarmApi.Alert>>(
'/aiot/alarm/alert/page',
{ params },
);
}
/** 获取告警详情 */
export function getAlert(id: number | string) {
return wvpRequestClient.get<AiotAlarmApi.Alert>(
`/aiot/device/alert/${id}`,
return requestClient.get<AiotAlarmApi.Alert>(
`/aiot/alarm/alert/get?id=${id}`,
);
}
@@ -101,22 +97,20 @@ export function handleAlert(
status: string,
remark?: string,
) {
return wvpRequestClient.put('/aiot/device/alert/handle', null, {
return requestClient.put('/aiot/alarm/alert/handle', null, {
params: { id, status, remark },
});
}
/** 删除告警 */
export function deleteAlert(id: number | string) {
return wvpRequestClient.delete('/aiot/device/alert/delete', {
params: { alertId: id },
});
return requestClient.delete(`/aiot/alarm/alert/delete?id=${id}`);
}
/** 获取告警统计 */
export function getAlertStatistics(startTime?: string, endTime?: string) {
return wvpRequestClient.get<AiotAlarmApi.AlertStatistics>(
'/aiot/device/alert/statistics',
return requestClient.get<AiotAlarmApi.AlertStatistics>(
'/aiot/alarm/alert/statistics',
{ params: { startTime, endTime } },
);
}
@@ -125,8 +119,8 @@ export function getAlertStatistics(startTime?: string, endTime?: string) {
/** 以摄像头维度获取告警汇总 */
export function getCameraAlertSummary(params: PageParam) {
return wvpRequestClient.get<PageResult<AiotAlarmApi.CameraAlertSummary>>(
'/aiot/device/alert/statistics',
return requestClient.get<PageResult<AiotAlarmApi.CameraAlertSummary>>(
'/aiot/alarm/device-summary/page',
{ params },
);
}

View File

@@ -189,27 +189,19 @@ export function deleteRoi(roiId: string) {
/**
* 获取摄像头截图 URL
*
* 非 force 模式:直接返回 /snap/image 代理 URL从 DB 读取持久化截图,不触发 Edge
* force 模式:先触发 Edge 截新图(更新 DB再返回代理 URL
* /snap 端点会自动处理缓存逻辑:
* - 有 Redis 缓存时直接 302 重定向到 COS presigned URL(快)
* - 无缓存时触发 Edge 截图,等待完成后重定向(首次较慢)
* - force=true 时强制触发 Edge 截新图
*/
export async function getSnapUrl(cameraCode: string, force = false): Promise<string> {
const token = await getWvpToken();
if (force) {
// force 时先触发一次截图请求(确保 Edge 截新图并更新 DB
try {
await wvpRequestClient.get('/aiot/device/roi/snap', {
params: { cameraCode, force: true },
});
} catch {
/* 截图请求可能超时,但 DB 会被更新 */
}
}
// 返回代理 URLWVP 从 DB 读 cos_key → 生成 presigned URL → 下载返回)
return (
`${apiURL}/aiot/device/roi/snap/image` +
`${apiURL}/aiot/device/roi/snap` +
`?cameraCode=${encodeURIComponent(cameraCode)}` +
`&access-token=${encodeURIComponent(token)}` +
(force ? `&t=${Date.now()}` : '')
(force ? `&force=true` : '') +
`&t=${Date.now()}`
);
}