功能:摄像头状态指示器 + 截图缓存优化 + 截图预热
1. 摄像头列表状态指示器(绿/红点) - 新增状态列显示摄像头截图可用性 - 绿色=截图正常,红色=截图失败,灰色=加载中 - 使用 /snap/image 代理端点检测状态 2. 截图缓存优化(getSnapUrl 重写) - 非强制模式:返回稳定URL(无时间戳),浏览器缓存5分钟 - 强制模式:先触发边缘截图,再返回带时间戳URL破缓存 - 使用 /snap/image 代理端点,避免COS预签名URL过期问题 3. 截图预热(新增摄像头时) - 添加摄像头成功后自动触发首次截图 - 预热失败不影响主流程(非阻塞) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -189,19 +189,33 @@ export function deleteRoi(roiId: string) {
|
||||
/**
|
||||
* 获取摄像头截图 URL
|
||||
*
|
||||
* /snap 端点会自动处理缓存逻辑:
|
||||
* - 有 Redis 缓存时直接 302 重定向到 COS presigned URL(快)
|
||||
* - 无缓存时触发 Edge 截图,等待完成后重定向(首次较慢)
|
||||
* - force=true 时强制触发 Edge 截新图
|
||||
* 非 force 模式:直接返回 /snap/image 代理 URL(无时间戳,浏览器自动缓存)
|
||||
* force 模式:先触发边缘端截图,再返回带时间戳的代理 URL 破缓存
|
||||
*/
|
||||
export async function getSnapUrl(cameraCode: string, force = false): Promise<string> {
|
||||
const token = await getWvpToken();
|
||||
if (force) {
|
||||
// 强制刷新:先触发边缘端截图(等待完成)
|
||||
try {
|
||||
await wvpRequestClient.get('/aiot/device/roi/snap', {
|
||||
params: { cameraCode, force: true },
|
||||
});
|
||||
} catch {
|
||||
// 截图请求可能超时,但 COS 上可能已有图片,继续返回代理 URL
|
||||
}
|
||||
// 加时间戳破浏览器缓存
|
||||
return (
|
||||
`${apiURL}/aiot/device/roi/snap/image` +
|
||||
`?cameraCode=${encodeURIComponent(cameraCode)}` +
|
||||
`&access-token=${encodeURIComponent(token)}` +
|
||||
`&t=${Date.now()}`
|
||||
);
|
||||
}
|
||||
// 非 force:使用代理端点,不加时间戳,浏览器自动缓存
|
||||
return (
|
||||
`${apiURL}/aiot/device/roi/snap` +
|
||||
`${apiURL}/aiot/device/roi/snap/image` +
|
||||
`?cameraCode=${encodeURIComponent(cameraCode)}` +
|
||||
`&access-token=${encodeURIComponent(token)}` +
|
||||
(force ? `&force=true` : '') +
|
||||
`&t=${Date.now()}`
|
||||
`&access-token=${encodeURIComponent(token)}`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user