diff --git a/FACE_MOVE_DIAGNOSIS_REPORT.md b/FACE_MOVE_DIAGNOSIS_REPORT.md new file mode 100644 index 0000000..4a0ca5c --- /dev/null +++ b/FACE_MOVE_DIAGNOSIS_REPORT.md @@ -0,0 +1,292 @@ +# Face Move/Merge 功能诊断报告 + +**日期**: 2026-07-25 +**状态**: 已完成显示文本改进,待验证数据流 + +--- + +## ✅ 已完成:显示文本改进 + +### 改进内容 + +**修改前**: `F{trace_id}`(如 `F13`) +**修改后**: `Face{trace_id}`(如 `Face13`) + +### 修改位置 + +| 行号 | 位置 | 修改前 | 修改后 | +|------|------|--------|--------| +| 143 | Face Detail Modal | `file_uuid:F13` | `file_uuid:Face13` | +| 262 | Cluster Strip Fallback | `F13` | `Face13` | +| 264 | Cluster Strip Label | `F13 GroupName` | `Face13 GroupName` | + +### 保留的位置 + +**Line 105**: Frame range 显示 +```vue +F{{ t.start_frame }}–{{ t.end_frame }} +``` +- 保持不变,因为这是 Frame 编号范围 +- 示例:`F2219–2225` + +--- + +## 🔍 数据流分析 + +### 理想数据流 + +``` +Core API + ↓ +返回: trace_ids = [13, 14, 15] (i64[]) + ↓ +前端存储 + ↓ +clusterTracesMap["13"] = {trace_id: 13, ...} + ↓ +用户选择 + ↓ +selectedFaces.push("file_uuid:13") + ↓ +API 调用 + ↓ +merge_trace(file_uuid, source_id=13, target_id=...) +``` + +--- + +### 关键检查点 + +#### 检查点 1: 数据存储 + +**代码位置**: PeopleView.vue Line 914-920 +```typescript +clusterTracesMap.value = {} +for (const t of allTraces) { + clusterTracesMap.value[String(t.trace_id)] = t +} +``` + +**验证要点**: +- ✅ `t.trace_id` 应该是 `integer`(如 13) +- ✅ `String(t.trace_id)` 应该是 `"13"`(不是 `"Face13"`) + +--- + +#### 检查点 2: 用户选择 + +**代码位置**: PeopleView.vue Line 1507-1515 +```typescript +function toggleFaceSelection(t: any) { + const key = `${t.file_uuid}:${t.trace_id}` + const idx = selectedFaces.value.indexOf(key) + if (idx >= 0) { + selectedFaces.value.splice(idx, 1) + } else { + selectedFaces.value.push(key) + } +} +``` + +**验证要点**: +- ✅ `t.trace_id` 应该是 `integer`(如 13) +- ✅ `key` 应该是 `"file_uuid:13"`(不是 `"file_uuid:Face13"`) + +--- + +#### 检查点 3: API 调用 + +**代码位置**: PeopleView.vue Line 1810-1827 +```typescript +const traceList: { file_uuid: string; trace_id: number }[] = [] +for (const key of selectedFaces.value) { + const [file_uuid, trace_id] = key.split(':') + traceList.push({ file_uuid, trace_id: parseInt(trace_id) }) +} + +for (const t of traceList) { + await apiCall('merge_trace', { + file_uuid: t.file_uuid, + source_id: t.trace_id, + target_id: targetTraceId + }) +} +``` + +**验证要点**: +- ✅ `key.split(':')` 应该得到 `["file_uuid", "13"]` +- ✅ `parseInt("13")` 应该是 `13`(不是 `NaN`) +- ✅ API 参数应该正确 + +--- + +## 🧪 浏览器验证方案 + +### 方案 1: 检查 selectedFaces 格式 + +```javascript +// 1. 打开 PeopleView 页面 +// 2. 选择一个 Face(如 Face13) +// 3. 打开浏览器控制台,执行: + +const app = document.querySelector('#app').__vueParentComponent +const peopleView = app.ctx.$root.$children[0] + +// 检查 selectedFaces +console.log('=== selectedFaces 内容 ===') +console.log('selectedFaces:', peopleView.selectedFaces) +console.log('First key:', peopleView.selectedFaces[0]) + +// 检查 key 格式 +const [file_uuid, trace_id_str] = peopleView.selectedFaces[0].split(':') +console.log('file_uuid:', file_uuid) +console.log('trace_id (string):', trace_id_str) +console.log('trace_id (parsed):', parseInt(trace_id_str)) + +// 预期结果: +// selectedFaces = ["84d838f260e1881a0daa55fabbc8e434:13"] +// trace_id (string) = "13" +// trace_id (parsed) = 13 +``` + +--- + +### 方案 2: 检查数据源 + +```javascript +// 检查 clusterTracesMap +console.log('=== clusterTracesMap ===') +console.log('Keys:', Object.keys(peopleView.clusterTracesMap)) +const firstKey = Object.keys(peopleView.clusterTracesMap)[0] +console.log('First key:', firstKey) +console.log('Data:', peopleView.clusterTracesMap[firstKey]) + +// 检查 trace_id 类型 +const trace = peopleView.clusterTracesMap[firstKey] +console.log('trace_id:', trace.trace_id, typeof trace.trace_id) + +// 预期结果: +// Keys = ["13", "14", "15"] +// First key = "13" +// trace_id = 13 (number) +``` + +--- + +### 方案 3: 测试 Move 功能 + +```javascript +// 1. 选择几个 Faces +// 2. 点击 Move 按钮 +// 3. 选择目标 Group +// 4. 打开 Network 面板,观察请求 + +// 预期结果: +// URL: POST /api/v1/file/84d8.../trace/13/merge/142 +// 参数正确,API 调用成功 +``` + +--- + +## 📊 潜在问题假设 + +### 假设 1: 数据源错误 + +**问题**: Core API 返回的 `trace_id` 格式不正确 + +**验证**: 检查 Core API 响应 +```bash +curl "http://localhost:3002/api/v1/file/84d838f260e1881a0daa55fabbc8e434/face-groups" +``` + +**预期**: `trace_ids` 应该是 `[13, 14, 15]`(integer array) + +--- + +### 假设 2: 显示文本污染数据 + +**问题**: 显示文本 `"Face13"` 污染了数据层 + +**验证**: 检查 `selectedFaces` 内容 +- 如果发现 `"file_uuid:Face13"`,说明数据被污染 +- 应该改为 `"file_uuid:13"` + +--- + +### 假设 3: 前端转换错误 + +**问题**: 前端某处错误地处理了 `trace_id` + +**验证**: 检查所有 `trace_id` 相关代码 +- 数据加载处 +- 用户选择处 +- API 调用处 + +--- + +## ✅ 已确认的正确实现 + +### Core API 规格 + +**Endpoint**: `POST /api/v1/file/:file_uuid/trace/:trace_id/merge/:target_trace_id` + +**参数类型**: +- `file_uuid`: `string`(无连字符) +- `trace_id`: `integer` +- `target_trace_id`: `integer` + +**示例**: +```bash +POST /api/v1/file/c36f35685177c981aa139b66bbbccc5b/trace/142/merge/396 +``` + +--- + +### Face Group 数据结构 + +**Endpoint**: `GET /api/v1/file/:file_uuid/face-groups` + +**响应**: +```json +{ + "face_groups": [{ + "group_id": 1, + "trace_ids": [13, 14, 15], // i64[] - integer array + "trace_count": 3, + "representative_trace": 13 + }] +} +``` + +--- + +## 📝 下一步行动 + +### 立即执行 + +1. **浏览器验证**: 使用上述验证方案检查 `selectedFaces` 格式 +2. **数据流追踪**: 如果发现问题,定位具体污染位置 +3. **API 测试**: 测试 Move 功能是否正常工作 + +--- + +### 如果发现问题 + +1. **数据污染**: 修复数据存储逻辑 +2. **API 参数错误**: 修正 API 调用参数 +3. **其他问题**: 根据验证结果修复 + +--- + +## 📞 联系方式 + +**Studio Team**: 已完成显示文本改进 +**Core Team**: 提供 API 规格确认 + +**测试环境**: `http://localhost:5173` +**API 环境**: `http://localhost:3002` + +--- + +**生成时间**: 2026-07-25 +**状态**: 显示改进已完成,等待数据流验证 \ No newline at end of file