544 lines
12 KiB
Markdown
544 lines
12 KiB
Markdown
|
|
# 巡检任务工作流程说明
|
|||
|
|
|
|||
|
|
## 📋 功能概述
|
|||
|
|
|
|||
|
|
本文档说明巡检任务的完整执行流程,包括视频录制、保存、AI识别和告警创建。
|
|||
|
|
|
|||
|
|
## 🔄 完整工作流程
|
|||
|
|
|
|||
|
|
### 1. 任务启动
|
|||
|
|
|
|||
|
|
当巡检任务启动时:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
InspectionTaskServiceImpl.executeInspectionTask(taskId)
|
|||
|
|
├── 创建 InspectionTaskRecord(记录ID)
|
|||
|
|
├── 更新任务状态为"执行中"
|
|||
|
|
└── 调用 performVideoAnalysisWithRecord()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 视频录制和保存
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
performVideoAnalysisWithRecord()
|
|||
|
|
├── 从RTSP流抓取视频
|
|||
|
|
├── 录制指定时长的视频
|
|||
|
|
├── 保存为临时文件
|
|||
|
|
├── 上传视频到MinIO
|
|||
|
|
├── 更新InspectionTaskRecord.accessory(视频URL)
|
|||
|
|
└── 调用Python服务进行分析
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. AI识别处理
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
VideoAnalysisService.analyzeVideoWithRecord()
|
|||
|
|
├── 创建HttpYoloDetector(连接Python服务)
|
|||
|
|
├── 逐帧分析视频
|
|||
|
|
├── 每10帧调用一次Python API检测
|
|||
|
|
├── 绘制检测框
|
|||
|
|
├── 去重检测结果(避免重复告警)
|
|||
|
|
├── 创建告警记录
|
|||
|
|
├── 上传处理后的视频
|
|||
|
|
├── 生成检测结果摘要
|
|||
|
|
└── 更新InspectionTaskRecord.result(识别结果)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 告警创建(去重)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
createAlarmRecordForRecord()
|
|||
|
|
├── 提取检测区域图像
|
|||
|
|
├── 上传告警图片到MinIO
|
|||
|
|
├── 创建AlarmRecord
|
|||
|
|
│ ├── 设备ID
|
|||
|
|
│ ├── 告警类型
|
|||
|
|
│ ├── 告警内容(检测类别+置信度)
|
|||
|
|
│ ├── 关联的任务ID
|
|||
|
|
│ ├── 图片URL
|
|||
|
|
│ └── 帧位置
|
|||
|
|
└── 保存到数据库(仅新检测的对象)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📊 数据表关系
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
InspectionTask (巡检任务)
|
|||
|
|
↓ 1:N
|
|||
|
|
InspectionTaskRecord (巡检记录)
|
|||
|
|
├── accessory: 原始视频URL + 处理后视频URL
|
|||
|
|
├── result: AI识别结果摘要
|
|||
|
|
├── duration: 执行时长
|
|||
|
|
└── status: 0=成功, 1=失败, 2=部分成功
|
|||
|
|
|
|||
|
|
InspectionTaskRecord → AlarmRecord (1:N)
|
|||
|
|
├── 同一个record可以有多个告警
|
|||
|
|
└── 告警自动去重(相同位置的相同对象只记录一次)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🎯 关键字段说明
|
|||
|
|
|
|||
|
|
### InspectionTaskRecord
|
|||
|
|
|
|||
|
|
| 字段 | 说明 | 示例 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| recordId | 记录ID | 自增主键 |
|
|||
|
|
| taskId | 关联的任务ID | 1001 |
|
|||
|
|
| executeTime | 执行时间 | 2025-09-30 14:30:00 |
|
|||
|
|
| duration | 执行时长(秒) | 30 |
|
|||
|
|
| accessory | 附件URL | video1.mp4;video2.mp4 |
|
|||
|
|
| result | 识别结果 | 共检测到3个问题,详情:垃圾(2) 烟雾(1) |
|
|||
|
|
| status | 执行状态 | 0=成功, 1=失败, 2=部分成功 |
|
|||
|
|
|
|||
|
|
### AlarmRecord
|
|||
|
|
|
|||
|
|
| 字段 | 说明 | 示例 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| alarmId | 告警ID | 自增主键 |
|
|||
|
|
| deviceId | 设备ID | 1001 |
|
|||
|
|
| taskId | 任务ID | 1001 |
|
|||
|
|
| alarmType | 告警类型 | detection |
|
|||
|
|
| alarmContent | 告警内容 | 垃圾 - 置信度: 0.95 |
|
|||
|
|
| imageOssId | 告警图片ID | MinIO对象ID |
|
|||
|
|
| framePosition | 视频帧位置 | 150 |
|
|||
|
|
| confidence | 置信度 | 0.95 |
|
|||
|
|
| status | 处理状态 | 0=未处理, 1=已处理 |
|
|||
|
|
|
|||
|
|
## 🔧 关键实现细节
|
|||
|
|
|
|||
|
|
### 1. 去重机制
|
|||
|
|
|
|||
|
|
使用`generateDetectionKey`生成唯一键:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
private String generateDetectionKey(Detection detection) {
|
|||
|
|
Rect rect = detection.getRect();
|
|||
|
|
// 取10的倍数,允许小范围波动
|
|||
|
|
int x = rect.x() / 10 * 10;
|
|||
|
|
int y = rect.y() / 10 * 10;
|
|||
|
|
int w = rect.width() / 10 * 10;
|
|||
|
|
int h = rect.height() / 10 * 10;
|
|||
|
|
return String.format("%s_%d_%d_%d_%d", detection.getLabel(), x, y, w, h);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**原理**:
|
|||
|
|
- 相同类别 + 相似位置 → 认为是同一个对象
|
|||
|
|
- 允许10像素的波动
|
|||
|
|
- 超过60秒未检测到自动清除
|
|||
|
|
|
|||
|
|
### 2. Python服务调用
|
|||
|
|
|
|||
|
|
使用容器名调用:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
private static final String PYTHON_API_URL = "http://rtsp-python-service:8000/api/detect/file";
|
|||
|
|
private static final String MODEL_NAME = "yolov8_detector";
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 视频处理流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
RTSP流 → FFmpegFrameGrabber → 录制 → 临时文件
|
|||
|
|
→ 上传MinIO → 保存URL到record.accessory
|
|||
|
|
→ 逐帧分析 → 调用Python API → 绘制检测框
|
|||
|
|
→ 保存处理后视频 → 追加URL到record.accessory
|
|||
|
|
→ 更新record.result
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 附件字段格式
|
|||
|
|
|
|||
|
|
`accessory`字段使用分号分隔多个URL:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
原始视频URL;处理后视频URL
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
示例:
|
|||
|
|
```
|
|||
|
|
http://minio.com/inspection-videos/inspection_1001_1234567890.mp4;http://minio.com/inspection-videos/processed_1234567891.mp4
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🚀 使用方法
|
|||
|
|
|
|||
|
|
### 1. 创建巡检任务
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
InspectionTask task = new InspectionTask();
|
|||
|
|
task.setDeviceId(deviceId);
|
|||
|
|
task.setDuration(30); // 录制30秒
|
|||
|
|
task.setStatus(0); // 待执行
|
|||
|
|
|
|||
|
|
inspectionTaskService.insertInspectionTask(task);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 启动任务
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 异步执行
|
|||
|
|
inspectionTaskService.executeInspectionTask(taskId);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 查看执行记录
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 查询某任务的所有执行记录
|
|||
|
|
SELECT * FROM v_inspection_task_record WHERE task_id = 1001 ORDER BY execute_time DESC;
|
|||
|
|
|
|||
|
|
-- 查询成功的记录
|
|||
|
|
SELECT * FROM v_inspection_task_record WHERE status = 0;
|
|||
|
|
|
|||
|
|
-- 查询某记录的所有告警
|
|||
|
|
SELECT * FROM v_alarm_record WHERE task_id = 1001;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 查看告警
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 查询某任务的所有告警
|
|||
|
|
SELECT * FROM v_alarm_record WHERE task_id = 1001 ORDER BY create_time DESC;
|
|||
|
|
|
|||
|
|
-- 查询未处理的告警
|
|||
|
|
SELECT * FROM v_alarm_record WHERE status = 0;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📝 执行示例
|
|||
|
|
|
|||
|
|
### 执行流程
|
|||
|
|
|
|||
|
|
1. **任务创建**
|
|||
|
|
```
|
|||
|
|
Task ID: 1001
|
|||
|
|
Device ID: 5001
|
|||
|
|
Duration: 30秒
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **记录创建**
|
|||
|
|
```
|
|||
|
|
Record ID: 2001
|
|||
|
|
Task ID: 1001
|
|||
|
|
Execute Time: 2025-09-30 14:30:00
|
|||
|
|
Status: 1 (执行中)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **视频录制**
|
|||
|
|
```
|
|||
|
|
录制30秒视频
|
|||
|
|
保存到MinIO: inspection_1001_1234567890.mp4
|
|||
|
|
更新Record.accessory: http://minio.com/.../inspection_1001_1234567890.mp4
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
4. **AI识别**
|
|||
|
|
```
|
|||
|
|
调用Python服务
|
|||
|
|
检测到: 垃圾(2个), 烟雾(1个)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
5. **告警创建**(去重)
|
|||
|
|
```
|
|||
|
|
Alarm 1: 垃圾 - 位置(100,200) - 置信度0.95
|
|||
|
|
Alarm 2: 垃圾 - 位置(300,400) - 置信度0.87
|
|||
|
|
Alarm 3: 烟雾 - 位置(500,100) - 置信度0.92
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
6. **处理后视频**
|
|||
|
|
```
|
|||
|
|
带检测框的视频上传
|
|||
|
|
保存到MinIO: processed_1234567891.mp4
|
|||
|
|
更新Record.accessory: 原始URL;处理后URL
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
7. **更新记录**
|
|||
|
|
```
|
|||
|
|
Record.result: "共检测到 3 个问题,详情:垃圾(2) 烟雾(1)"
|
|||
|
|
Record.status: 0 (成功)
|
|||
|
|
Record.duration: 32秒
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## ⚙️ 配置说明
|
|||
|
|
|
|||
|
|
### Python服务配置
|
|||
|
|
|
|||
|
|
在Docker环境中,Python服务地址为:
|
|||
|
|
```
|
|||
|
|
http://rtsp-python-service:8000
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 模型配置
|
|||
|
|
|
|||
|
|
确保Python服务使用正确的模型名称:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"name": "yolov8_detector",
|
|||
|
|
"path": "models/yolov8_model.py",
|
|||
|
|
"size": [640, 640]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 检测参数
|
|||
|
|
|
|||
|
|
在`VideoAnalysisService`中可调整:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 检测频率(每N帧检测一次)
|
|||
|
|
if (frameCount % 10 == 0) { ... }
|
|||
|
|
|
|||
|
|
// 去重时间窗口(秒)
|
|||
|
|
detectedGarbageCache.entrySet().removeIf(entry ->
|
|||
|
|
(currentId - entry.getValue()) > grabber.getFrameRate() * 60);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🐛 故障排查
|
|||
|
|
|
|||
|
|
### 问题1: 视频未保存
|
|||
|
|
|
|||
|
|
**检查**:
|
|||
|
|
```sql
|
|||
|
|
-- 查看record的accessory字段
|
|||
|
|
SELECT record_id, accessory FROM v_inspection_task_record WHERE task_id = ?;
|
|||
|
|
|
|||
|
|
-- 查看MinIO对象
|
|||
|
|
SELECT * FROM v_minio_object WHERE bucket_name = 'inspection-videos' ORDER BY create_time DESC;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**解决**:
|
|||
|
|
- 检查MinIO服务是否可用
|
|||
|
|
- 检查网络连接
|
|||
|
|
- 查看后端日志
|
|||
|
|
|
|||
|
|
### 问题2: Python识别未执行
|
|||
|
|
|
|||
|
|
**检查**:
|
|||
|
|
```bash
|
|||
|
|
# 查看Python服务日志
|
|||
|
|
docker-compose logs python-service
|
|||
|
|
|
|||
|
|
# 测试Python服务
|
|||
|
|
curl http://rtsp-python-service:8000/health
|
|||
|
|
curl http://rtsp-python-service:8000/api/models
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**解决**:
|
|||
|
|
- 确认Python服务运行正常
|
|||
|
|
- 确认模型文件存在
|
|||
|
|
- 检查网络连通性
|
|||
|
|
|
|||
|
|
### 问题3: 告警未创建
|
|||
|
|
|
|||
|
|
**检查**:
|
|||
|
|
```sql
|
|||
|
|
-- 查看告警记录
|
|||
|
|
SELECT * FROM v_alarm_record WHERE task_id = ? ORDER BY create_time DESC;
|
|||
|
|
|
|||
|
|
-- 查看检测结果
|
|||
|
|
SELECT result FROM v_inspection_task_record WHERE record_id = ?;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**解决**:
|
|||
|
|
- 检查检测置信度阈值
|
|||
|
|
- 查看视频内容是否有检测对象
|
|||
|
|
- 检查Python服务返回结果
|
|||
|
|
|
|||
|
|
### 问题4: 重复告警
|
|||
|
|
|
|||
|
|
**检查**:
|
|||
|
|
- 去重机制是否正常工作
|
|||
|
|
- `generateDetectionKey`逻辑是否合理
|
|||
|
|
|
|||
|
|
**调整**:
|
|||
|
|
```java
|
|||
|
|
// 调整去重的位置容差
|
|||
|
|
int x = rect.x() / 20 * 20; // 从10改为20,更宽松的去重
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📊 性能优化
|
|||
|
|
|
|||
|
|
### 1. 检测频率
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 降低检测频率以提升性能(CPU模式)
|
|||
|
|
if (frameCount % 30 == 0) { // 从10改为30
|
|||
|
|
// 每30帧检测一次
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 视频质量
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 降低视频比特率节省存储
|
|||
|
|
recorder.setVideoBitrate(500000); // 降低比特率
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 去重时间窗口
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 缩短去重时间窗口
|
|||
|
|
(currentId - entry.getValue()) > grabber.getFrameRate() * 30 // 从60秒改为30秒
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🔍 调试方法
|
|||
|
|
|
|||
|
|
### 查看执行日志
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 查看后端日志
|
|||
|
|
docker-compose logs -f backend | grep "inspection"
|
|||
|
|
|
|||
|
|
# 查看Python服务日志
|
|||
|
|
docker-compose logs -f python-service
|
|||
|
|
|
|||
|
|
# 查看特定记录的处理过程
|
|||
|
|
docker-compose logs backend | grep "recordId=2001"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 数据库查询
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 查看最新的执行记录
|
|||
|
|
SELECT
|
|||
|
|
r.record_id,
|
|||
|
|
r.task_id,
|
|||
|
|
r.execute_time,
|
|||
|
|
r.duration,
|
|||
|
|
r.status,
|
|||
|
|
r.result,
|
|||
|
|
LENGTH(r.accessory) as accessory_length
|
|||
|
|
FROM v_inspection_task_record r
|
|||
|
|
ORDER BY r.create_time DESC
|
|||
|
|
LIMIT 10;
|
|||
|
|
|
|||
|
|
-- 查看记录对应的告警
|
|||
|
|
SELECT
|
|||
|
|
a.alarm_id,
|
|||
|
|
a.alarm_content,
|
|||
|
|
a.confidence,
|
|||
|
|
a.frame_position,
|
|||
|
|
a.create_time
|
|||
|
|
FROM v_alarm_record a
|
|||
|
|
WHERE a.task_id = ?
|
|||
|
|
ORDER BY a.create_time DESC;
|
|||
|
|
|
|||
|
|
-- 统计告警数量
|
|||
|
|
SELECT
|
|||
|
|
r.record_id,
|
|||
|
|
r.execute_time,
|
|||
|
|
COUNT(a.alarm_id) as alarm_count
|
|||
|
|
FROM v_inspection_task_record r
|
|||
|
|
LEFT JOIN v_alarm_record a ON r.task_id = a.task_id
|
|||
|
|
AND a.create_time >= r.execute_time
|
|||
|
|
AND a.create_time <= DATE_ADD(r.execute_time, INTERVAL r.duration SECOND)
|
|||
|
|
GROUP BY r.record_id
|
|||
|
|
ORDER BY r.create_time DESC;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 💡 扩展建议
|
|||
|
|
|
|||
|
|
### 1. 添加检测类型过滤
|
|||
|
|
|
|||
|
|
在`createAlarmRecordForRecord`中:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 只对特定类型创建告警
|
|||
|
|
List<String> alarmTypes = Arrays.asList("垃圾", "烟雾", "火焰");
|
|||
|
|
if (!alarmTypes.contains(detection.getLabel())) {
|
|||
|
|
return; // 忽略其他类型
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 添加置信度阈值
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 只对高置信度的检测创建告警
|
|||
|
|
if (detection.getConfidence() < 0.7) {
|
|||
|
|
return; // 忽略低置信度检测
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 添加区域过滤
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 只对特定区域的检测创建告警
|
|||
|
|
Rect rect = detection.getRect();
|
|||
|
|
if (!isInMonitorArea(rect, task)) {
|
|||
|
|
return; // 忽略监控区域外的检测
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. 添加告警级别
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 根据检测类型设置告警级别
|
|||
|
|
String alarmLevel = "medium";
|
|||
|
|
if (detection.getLabel().contains("火焰")) {
|
|||
|
|
alarmLevel = "high";
|
|||
|
|
} else if (detection.getLabel().contains("垃圾")) {
|
|||
|
|
alarmLevel = "low";
|
|||
|
|
}
|
|||
|
|
alarmRecord.setAlarmLevel(alarmLevel);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 🔒 安全考虑
|
|||
|
|
|
|||
|
|
### 1. 异常处理
|
|||
|
|
|
|||
|
|
所有方法都包含完整的异常处理:
|
|||
|
|
- 视频录制失败 → 更新record状态为失败
|
|||
|
|
- Python服务调用失败 → 记录错误但不影响整体流程
|
|||
|
|
- MinIO上传失败 → 记录错误并回滚
|
|||
|
|
|
|||
|
|
### 2. 资源清理
|
|||
|
|
|
|||
|
|
使用try-finally确保资源释放:
|
|||
|
|
- FFmpegFrameGrabber自动关闭
|
|||
|
|
- FFmpegFrameRecorder自动关闭
|
|||
|
|
- 临时文件自动删除
|
|||
|
|
|
|||
|
|
### 3. 并发控制
|
|||
|
|
|
|||
|
|
使用`@Async`异步执行,避免阻塞:
|
|||
|
|
- 任务执行不阻塞API响应
|
|||
|
|
- 多个任务可并发执行
|
|||
|
|
- 通过runningTasks避免重复执行
|
|||
|
|
|
|||
|
|
## 📈 监控指标
|
|||
|
|
|
|||
|
|
### 建议监控的指标
|
|||
|
|
|
|||
|
|
1. **执行成功率**
|
|||
|
|
```sql
|
|||
|
|
SELECT
|
|||
|
|
COUNT(CASE WHEN status = 0 THEN 1 END) * 100.0 / COUNT(*) as success_rate
|
|||
|
|
FROM v_inspection_task_record
|
|||
|
|
WHERE execute_time >= DATE_SUB(NOW(), INTERVAL 1 DAY);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **平均执行时长**
|
|||
|
|
```sql
|
|||
|
|
SELECT AVG(duration) as avg_duration
|
|||
|
|
FROM v_inspection_task_record
|
|||
|
|
WHERE status = 0 AND execute_time >= DATE_SUB(NOW(), INTERVAL 1 DAY);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **告警统计**
|
|||
|
|
```sql
|
|||
|
|
SELECT
|
|||
|
|
alarm_type,
|
|||
|
|
COUNT(*) as count
|
|||
|
|
FROM v_alarm_record
|
|||
|
|
WHERE create_time >= DATE_SUB(NOW(), INTERVAL 1 DAY)
|
|||
|
|
GROUP BY alarm_type;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 📞 技术支持
|
|||
|
|
|
|||
|
|
如有问题,请查看:
|
|||
|
|
1. 后端日志:`docker-compose logs backend`
|
|||
|
|
2. Python服务日志:`docker-compose logs python-service`
|
|||
|
|
3. 数据库记录:查询`v_inspection_task_record`和`v_alarm_record`表
|
|||
|
|
4. MinIO对象:查询`v_minio_object`表
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**文档版本**: 1.0
|
|||
|
|
**最后更新**: 2025-09-30
|
|||
|
|
**适用版本**: YOLOv8, Docker Compose部署
|