diff --git a/src/api/index.ts b/src/api/index.ts index b7aa266..dc901b8 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -359,6 +359,17 @@ case 'search_keyword': { case 'merge_trace': { return { url: `/api/v1/file/${a.file_uuid}/trace/${a.source_id}/merge/${a.target_id}`, method: 'POST' } } + case 'merge_groups': { + return { + url: `/api/v1/file/${a.fileUuid}/groups/merge`, + method: 'POST', + body: { + file_uuid: a.fileUuid, + source_groups: a.sourceGroups, + target_group_name: a.targetGroupName + } + } + } case 'bind_face': { const bindBody: any = { file_uuid: a.fileUuid } if (a.faceId) bindBody.face_id = a.faceId diff --git a/src/views/PeopleView.vue b/src/views/PeopleView.vue index 53d70e2..16c95ab 100644 --- a/src/views/PeopleView.vue +++ b/src/views/PeopleView.vue @@ -1725,18 +1725,10 @@ async function executeMerge(targetGroupId: string) { console.log('[executeMerge] targetGroup:', targetGroup) if (!targetGroup) return - const targetTraceId = targetGroup.trace_ids?.[0] - console.log('[executeMerge] targetTraceId:', targetTraceId, typeof targetTraceId) - if (!targetTraceId) { - alert('Target group has no traces') - return - } - - const targetTrace = clusterTracesMap.value[String(targetTraceId)] - console.log('[executeMerge] targetTrace:', targetTrace) - const targetFileUuid = targetTrace?.file_uuid - if (!targetFileUuid) { - alert('Target trace has no file_uuid') + const targetGroupName = targetGroup.name + console.log('[executeMerge] targetGroupName:', targetGroupName) + if (!targetGroupName) { + alert('Target group has no name') return } @@ -1745,71 +1737,48 @@ async function executeMerge(targetGroupId: string) { const sourceGroups = clusterAsPending.value.filter((c: any) => sourceGroupIds.includes(c.identity_uuid)) console.log('[executeMerge] sourceGroups:', sourceGroups.length) - let totalTraces = 0 - let validTraces = 0 - for (const g of sourceGroups) { - for (const tid of g.trace_ids || []) { - totalTraces++ - const t = clusterTracesMap.value[String(tid)] - if (t?.file_uuid) validTraces++ - } - } + const sourceGroupNames = sourceGroups.map(g => g.name).filter(Boolean) + console.log('[executeMerge] sourceGroupNames:', sourceGroupNames) - console.log('[executeMerge] totalTraces:', totalTraces, 'validTraces:', validTraces) - - if (validTraces === 0) { - alert('No valid traces to merge (all missing file_uuid)') + if (sourceGroupNames.length === 0) { + alert('No valid source groups to merge') return } - if (!confirm(`Merge ${validTraces}/${totalTraces} trace(s) from ${sourceGroups.length} group(s)?`)) return + if (!confirm(`Merge ${sourceGroupNames.length} group(s) into "${targetGroupName}"?`)) return operationLoading.value = true - operationMessage.value = `Merging ${validTraces} trace(s)...` + operationMessage.value = `Merging ${sourceGroupNames.length} group(s)...` - let successCount = 0 - let failCount = 0 - - for (const g of sourceGroups) { - for (const srcTraceId of g.trace_ids || []) { - const srcTrace = clusterTracesMap.value[String(srcTraceId)] - const srcFileUuid = srcTrace?.file_uuid - if (!srcFileUuid) { - console.warn('[merge] skipping trace without file_uuid:', srcTraceId) - failCount++ - continue - } - if (srcFileUuid !== targetFileUuid) { - console.warn('[merge] skipping cross-file trace:', srcTraceId, srcFileUuid, '!=', targetFileUuid) - failCount++ - continue - } - try { - console.log('[executeMerge] calling merge_trace:', { - file_uuid: srcFileUuid, - source_id: srcTraceId, - target_id: targetTraceId - }) - await apiCall('merge_trace', { - file_uuid: srcFileUuid, - source_id: srcTraceId, - target_id: targetTraceId - }) - successCount++ - } catch (e) { - console.error('Merge trace failed:', srcTraceId, e) - failCount++ - } + try { + console.log('[executeMerge] calling merge_groups API:', { + fileUuid: selectedFileUuid.value, + sourceGroups: sourceGroupNames, + targetGroupName: targetGroupName + }) + + const result = await apiCall('merge_groups', { + fileUuid: selectedFileUuid.value, + sourceGroups: sourceGroupNames, + targetGroupName: targetGroupName + }) + + console.log('[executeMerge] result:', result) + + if (result?.success) { + console.log('[executeMerge] success, traces_merged:', result.traces_merged) + await loadClusterResults() + clearSelection() + } else { + alert(`Merge failed: ${result?.error || 'Unknown error'}`) } + } catch (e) { + console.error('[executeMerge] error:', e) + alert(`Merge failed: ${e}`) + } finally { + operationLoading.value = false + operationMessage.value = '' } - - console.log('[executeMerge] completed:', successCount, 'success,', failCount, 'failed') - - operationLoading.value = false - operationMessage.value = '' - - clearSelection() - await loadClusterResults() } async function batchMoveFaces() {