fix: improve face detail navigation context matching

- Simplified trace matching to use only trace_id (removed file_uuid requirement)
- Added debug logging to trace navigation context setup
- Added pointer-events: none to modal overlay to allow arrow clicks
- Moved navigation arrows outside modal overlay for proper z-index stacking
This commit is contained in:
2026-10-30 19:52:10 +08:00
parent efe5bcee8a
commit 8b581af7ad

View File

@@ -2523,44 +2523,63 @@ async function openFaceDetailFromTrace(t: any) {
} }
function setFaceDetailNavContext(t: any) { function setFaceDetailNavContext(t: any) {
console.log('[nav] setFaceDetailNavContext called for trace:', t.trace_id, 'file_uuid:', t.file_uuid)
console.log('[nav] traceGroupMap keys:', Object.keys(traceGroupMap.value).length)
console.log('[nav] clusterResults:', clusterResults.value.length)
console.log('[nav] filteredUnassignedTraces:', filteredUnassignedTraces.value.length)
// The trace's own group takes priority — navigation is limited to that group // The trace's own group takes priority — navigation is limited to that group
const groupName = traceGroupMap.value[String(t.trace_id)] const groupName = traceGroupMap.value[String(t.trace_id)]
console.log('[nav] groupName for trace:', t.trace_id, '=', groupName)
if (groupName) { if (groupName) {
const cluster = clusterResults.value.find((c: any) => c.name === groupName) const cluster = clusterResults.value.find((c: any) => c.name === groupName)
console.log('[nav] cluster found:', !!cluster)
if (cluster) { if (cluster) {
const traces = filteredGroupTraces(cluster) const traces = filteredGroupTraces(cluster)
console.log('[nav] filteredGroupTraces count:', traces.length)
const cIdx = traces.findIndex((x: any) => x.trace_id === t.trace_id) const cIdx = traces.findIndex((x: any) => x.trace_id === t.trace_id)
console.log('[nav] findIndex result:', cIdx)
if (cIdx >= 0) { if (cIdx >= 0) {
faceDetailNavSource.value = 'cluster' faceDetailNavSource.value = 'cluster'
faceDetailNavIndex.value = cIdx faceDetailNavIndex.value = cIdx
console.log('[nav] cluster context:', { source: 'cluster', index: cIdx, total: traces.length })
return return
} }
} }
} }
// Truly unassigned traces (already filtered out grouped ones), filter-aware // Truly unassigned traces (already filtered out grouped ones), filter-aware
console.log('[nav] filteredUnassignedTraces sample:', filteredUnassignedTraces.value.slice(0, 2))
const uIdx = filteredUnassignedTraces.value.findIndex( const uIdx = filteredUnassignedTraces.value.findIndex(
(x: any) => x.trace_id === t.trace_id && x.file_uuid === t.file_uuid (x: any) => x.trace_id === t.trace_id
) )
console.log('[nav] unassigned findIndex result:', uIdx)
if (uIdx >= 0) { if (uIdx >= 0) {
faceDetailNavSource.value = 'unassigned' faceDetailNavSource.value = 'unassigned'
faceDetailNavIndex.value = uIdx faceDetailNavIndex.value = uIdx
console.log('[nav] unassigned context:', { source: 'unassigned', index: uIdx, total: filteredUnassignedTraces.value.length })
return return
} }
faceDetailNavSource.value = null faceDetailNavSource.value = null
faceDetailNavIndex.value = -1 faceDetailNavIndex.value = -1
console.log('[nav] no context:', { source: null, index: -1, unassigned: filteredUnassignedTraces.value.length, clusterResults: clusterResults.value.length })
} }
function goFaceDetailPrev() { function goFaceDetailPrev() {
console.log('[nav] goFaceDetailPrev called, canFaceDetailPrev:', canFaceDetailPrev.value, 'index:', faceDetailNavIndex.value, 'list:', faceDetailNavList.value.length)
if (!canFaceDetailPrev.value) return if (!canFaceDetailPrev.value) return
faceDetailNavIndex.value-- faceDetailNavIndex.value--
const prev = faceDetailNavList.value[faceDetailNavIndex.value] const prev = faceDetailNavList.value[faceDetailNavIndex.value]
console.log('[nav] goFaceDetailPrev prev:', prev?.trace_id)
if (prev) openFaceDetailFromTrace(prev) if (prev) openFaceDetailFromTrace(prev)
} }
function goFaceDetailNext() { function goFaceDetailNext() {
console.log('[nav] goFaceDetailNext called, canFaceDetailNext:', canFaceDetailNext.value, 'index:', faceDetailNavIndex.value, 'list:', faceDetailNavList.value.length)
if (!canFaceDetailNext.value) return if (!canFaceDetailNext.value) return
faceDetailNavIndex.value++ faceDetailNavIndex.value++
const next = faceDetailNavList.value[faceDetailNavIndex.value] const next = faceDetailNavList.value[faceDetailNavIndex.value]
console.log('[nav] goFaceDetailNext next:', next?.trace_id)
if (next) openFaceDetailFromTrace(next) if (next) openFaceDetailFromTrace(next)
} }
@@ -2779,6 +2798,7 @@ function faceCtxAction(action: string) {
faceCtxMenu.value.show = false faceCtxMenu.value.show = false
if (action === 'detail') { if (action === 'detail') {
faceDetailModal.value = { show: true, candidate: c, newIdentityName: '' } faceDetailModal.value = { show: true, candidate: c, newIdentityName: '' }
setFaceDetailNavContext(c)
loadCandidateThumb(c) loadCandidateThumb(c)
} }
} }
@@ -4210,8 +4230,9 @@ h1 { margin: 0; }
.ms-ctx-history-btn { padding: 2px 6px !important; font-size: 12px !important; min-width: 24px; } .ms-ctx-history-btn { padding: 2px 6px !important; font-size: 12px !important; min-width: 24px; }
/* Modal overlay */ /* Modal overlay */
.ms-modal-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.35); z-index: 9998; align-items: center; justify-content: center; } .ms-modal-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,.35); z-index: 9998; align-items: center; justify-content: center; pointer-events: none; }
.ms-modal-overlay.show { display: flex; } .ms-modal-overlay.show { display: flex; }
.ms-modal-overlay .ms-modal { pointer-events: auto; }
.close-btn { position: absolute; top: 16px; right: 16px; } .close-btn { position: absolute; top: 16px; right: 16px; }
.fs-delete-btn { position: absolute; top: 16px; right: 56px; color: var(--text-secondary); } .fs-delete-btn { position: absolute; top: 16px; right: 56px; color: var(--text-secondary); }
.fs-delete-btn:hover { color: var(--danger-color); } .fs-delete-btn:hover { color: var(--danger-color); }