修复:从回调URL解析cos_key + 状态栏位置修正
1. 修复cos_key持久化问题(根本原因) - handleCallback原来依赖内存中的pendingCosKeys获取cos_key - 问题:WVP重启或多实例部署时,pendingCosKeys中找不到requestId - 修复:新增extractCosKeyFromUrl方法,直接从回调URL解析cos_key - 降级:解析失败时仍尝试从pendingCosKeys获取 2. 前端状态栏位置修正 - 正确位置:应用名 -> 流ID -> 拉流地址 -> 状态 -> ROI - 之前错误地放在了流ID和拉流地址之间 3. 前端状态检测优化 - 修复导入顺序问题(useAppConfig应在顶部导入) - 移除不必要的access-token参数(/snap/image已免认证) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -210,8 +210,15 @@ public class AiScreenshotServiceImpl implements IAiScreenshotService {
|
||||
String url = (String) data.get("url");
|
||||
writeCache(cameraCode, url);
|
||||
|
||||
// 持久化 cos_key 到 DB(永不过期,供后续直接读取)
|
||||
String cosKey = pendingCosKeys.remove(requestId);
|
||||
// 从URL解析cos_key(优先),失败时降级使用pendingCosKeys
|
||||
String cosKey = extractCosKeyFromUrl(url);
|
||||
if (cosKey == null) {
|
||||
cosKey = pendingCosKeys.remove(requestId);
|
||||
} else {
|
||||
// 解析成功,也要清理pendingCosKeys避免内存泄漏
|
||||
pendingCosKeys.remove(requestId);
|
||||
}
|
||||
|
||||
if (cosKey != null) {
|
||||
try {
|
||||
snapshotMapper.upsert(cameraCode, cosKey);
|
||||
@@ -219,6 +226,8 @@ public class AiScreenshotServiceImpl implements IAiScreenshotService {
|
||||
} catch (Exception e) {
|
||||
log.error("[AI截图] 持久化 cos_key 失败: cameraCode={}, error={}", cameraCode, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
log.warn("[AI截图] 无法获取cos_key: cameraCode={}, url={}", cameraCode, url);
|
||||
}
|
||||
} else {
|
||||
pendingCosKeys.remove(requestId);
|
||||
@@ -233,6 +242,48 @@ public class AiScreenshotServiceImpl implements IAiScreenshotService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从COS预签名URL中提取cos_key
|
||||
* URL格式: https://{bucket}.cos.{region}.myqcloud.com/{cos_key}?q-sign-...
|
||||
* 返回: snapshots/{camera_code}/2026-03-10/08-16-39_xxx.jpg
|
||||
*/
|
||||
private String extractCosKeyFromUrl(String url) {
|
||||
if (url == null || url.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// 移除查询参数,得到路径部分
|
||||
String pathPart = url;
|
||||
int queryStart = url.indexOf('?');
|
||||
if (queryStart > 0) {
|
||||
pathPart = url.substring(0, queryStart);
|
||||
}
|
||||
|
||||
// 找到myqcloud.com后的路径
|
||||
int domainEnd = pathPart.indexOf(".myqcloud.com/");
|
||||
if (domainEnd > 0) {
|
||||
String cosKey = pathPart.substring(domainEnd + ".myqcloud.com/".length());
|
||||
// 确保以snapshots/开头
|
||||
if (cosKey.startsWith("snapshots/")) {
|
||||
return cosKey;
|
||||
}
|
||||
}
|
||||
|
||||
// 降级:尝试最后一个/后的路径
|
||||
int lastSlash = pathPart.lastIndexOf('/');
|
||||
if (lastSlash > 0) {
|
||||
// 往回找snapshots
|
||||
int snapshotsIdx = pathPart.indexOf("snapshots/");
|
||||
if (snapshotsIdx > 0) {
|
||||
return pathPart.substring(snapshotsIdx);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("[AI截图] 从URL解析cos_key失败: {}, error={}", url, e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入截图缓存
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user