From 284f2b8d87fd88d6d66f5b7d63e1f29b4e29595e Mon Sep 17 00:00:00 2001 From: 16337 <1633794139@qq.com> Date: Wed, 4 Mar 2026 11:05:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(aiot):=20=E5=9B=9E=E9=80=80=E5=91=8A?= =?UTF-8?q?=E8=AD=A6=20API=20=E5=88=B0=20Service=20=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=88=AA=E5=9B=BE=20URL=20=E7=AB=AF?= =?UTF-8?q?=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 告警问题: - 告警数据存储在 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 --- apps/web-antd/src/api/aiot/alarm/index.ts | 32 ++++++-------- apps/web-antd/src/api/aiot/device/index.ts | 22 ++++------ .../src/views/aiot/alarm/list/index.vue | 42 ++++++++----------- 3 files changed, 37 insertions(+), 59 deletions(-) diff --git a/apps/web-antd/src/api/aiot/alarm/index.ts b/apps/web-antd/src/api/aiot/alarm/index.ts index a90a19f12..0c32d7ddb 100644 --- a/apps/web-antd/src/api/aiot/alarm/index.ts +++ b/apps/web-antd/src/api/aiot/alarm/index.ts @@ -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; - receivedAt?: string; createdAt?: string; updatedAt?: string; logInfo?: AlertLogInfo; - extraData?: string; } /** 告警日志信息 */ @@ -78,20 +74,20 @@ export namespace AiotAlarmApi { } } -// ==================== 告警管理 API(WVP 后端)==================== +// ==================== 告警管理 API ==================== /** 分页查询告警列表 */ export function getAlertPage(params: PageParam) { - return wvpRequestClient.get>( - '/aiot/device/alert/list', - { params: { page: params.pageNo, count: params.pageSize, ...params } }, + return requestClient.get>( + '/aiot/alarm/alert/page', + { params }, ); } /** 获取告警详情 */ export function getAlert(id: number | string) { - return wvpRequestClient.get( - `/aiot/device/alert/${id}`, + return requestClient.get( + `/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( - '/aiot/device/alert/statistics', + return requestClient.get( + '/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>( - '/aiot/device/alert/statistics', + return requestClient.get>( + '/aiot/alarm/device-summary/page', { params }, ); } diff --git a/apps/web-antd/src/api/aiot/device/index.ts b/apps/web-antd/src/api/aiot/device/index.ts index 10553bbe0..ba1c7e3fd 100644 --- a/apps/web-antd/src/api/aiot/device/index.ts +++ b/apps/web-antd/src/api/aiot/device/index.ts @@ -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 { const token = await getWvpToken(); - if (force) { - // force 时先触发一次截图请求(确保 Edge 截新图并更新 DB) - try { - await wvpRequestClient.get('/aiot/device/roi/snap', { - params: { cameraCode, force: true }, - }); - } catch { - /* 截图请求可能超时,但 DB 会被更新 */ - } - } - // 返回代理 URL(WVP 从 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()}` ); } diff --git a/apps/web-antd/src/views/aiot/alarm/list/index.vue b/apps/web-antd/src/views/aiot/alarm/list/index.vue index 09874d144..2396c7c3f 100644 --- a/apps/web-antd/src/views/aiot/alarm/list/index.vue +++ b/apps/web-antd/src/views/aiot/alarm/list/index.vue @@ -2,7 +2,7 @@ import type { VxeTableGridOptions } from '#/adapter/vxe-table'; import type { AiotAlarmApi } from '#/api/aiot/alarm'; -import { h, onMounted, ref } from 'vue'; +import { h, ref } from 'vue'; import { Page } from '@vben/common-ui'; @@ -10,7 +10,6 @@ import { Button, Image, message, Modal, Tag } from 'ant-design-vue'; import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; import { getAlert, getAlertPage, handleAlert } from '#/api/aiot/alarm'; -import { getAlertImageUrl } from '#/api/aiot/device'; import { ALERT_LEVEL_OPTIONS, @@ -22,21 +21,6 @@ import { defineOptions({ name: 'AiotAlarmList' }); -/** 告警图片 URL 缓存(imagePath → 代理 URL) */ -const imageUrlCache = ref>({}); - -/** 获取告警图片代理 URL(异步构造后缓存) */ -function getImageProxyUrl(row: AiotAlarmApi.Alert): string { - const imagePath = row.imagePath || row.ossUrl || row.snapshotUrl; - if (!imagePath) return ''; - if (imageUrlCache.value[imagePath]) return imageUrlCache.value[imagePath]!; - // 异步构造并缓存 - getAlertImageUrl(imagePath).then((url) => { - imageUrlCache.value[imagePath] = url; - }); - return ''; -} - /** 格式化持续时长(毫秒 → 可读文本) */ function formatDuration(ms: number | null | undefined): string { // 当 duration_ms 为 null 时,说明告警仍在进行中 @@ -263,12 +247,11 @@ const [Grid, gridApi] = useVbenVxeGrid({