fix: increase z-index of face detail navigation arrows

- Navigation arrows z-index increased from 10010 to 10100
- Fixes issue where modal overlay was covering the arrows
- Left/right buttons now clickable in face detail modal
This commit is contained in:
2026-10-30 14:33:12 +08:00
parent 81f11d4294
commit 8382590c58

View File

@@ -1097,7 +1097,14 @@ const faceMoveTarget = ref('')
const faceMoveNewGroupName = ref('')
// Cluster results (synced with store for cross-navigation persistence)
const clusterResults = computed(() => clusterResultsCache.value[selectedFileUuid.value] || [])
const clusterResults = computed(() => {
const results = clusterResultsCache.value[selectedFileUuid.value] || []
console.log('[clusterResults] cache for', selectedFileUuid.value, ':', results.length, 'groups')
if (results.length > 0) {
console.log('[clusterResults] first group:', JSON.stringify(results[0], null, 2))
}
return results
})
const clusterTracesMap = ref<Record<string, any>>({})
const clusterRunning = computed(() => isClusterRunning(selectedFileUuid.value))
@@ -1131,6 +1138,10 @@ const faceGroups = computed(() => {
}
const defaultName = `group ${String(idx + 1).padStart(2, '0')}`
if (!c.name) c.name = defaultName
// Convert Person_X to Group_X for display
if (c.name && c.name.startsWith('Person_')) {
c.name = 'Group_' + c.name.substring(7)
}
const visibleTraceIds = ffFilterActive.value
? traceIds.filter(tid => !ffHiddenTraces.value.has(tid))
: traceIds
@@ -1176,11 +1187,19 @@ const clusterDetailCluster = computed(() => {
// Map trace_id → group name for Faces section
const traceGroupMap = computed(() => {
const map: Record<string, string> = {}
console.log('[traceGroupMap] clusterResults:', clusterResults.value.length, 'groups')
for (const c of clusterResults.value) {
let name = c.name || ''
// Convert Person_X to Group_X for display
if (name.startsWith('Person_')) {
name = 'Group_' + name.substring(7)
}
console.log('[traceGroupMap] cluster:', c.cluster_id, 'name:', name, 'trace_ids:', c.trace_ids)
for (const tid of c.trace_ids || []) {
map[String(tid)] = c.name
map[String(tid)] = name
}
}
console.log('[traceGroupMap] final map:', map)
return map
})
@@ -1218,7 +1237,25 @@ const facesTotalPages = computed(() => {
})
function traceLabel(tr: any): string {
const n = tr?.name || traceGroupMap.value[String(tr.trace_id)]
// Prefer cluster name from clusterResultsCache
const clusters = clusterResultsCache.value[selectedFileUuid.value] || []
console.log('[traceLabel] trace_id:', tr.trace_id, 'clusters in cache:', clusters.length)
if (clusters.length > 0) {
console.log('[traceLabel] first cluster:', clusters[0])
}
for (const c of clusters) {
if (c.trace_ids && c.trace_ids.includes(tr.trace_id)) {
let name = c.name || ''
// Convert Person_X to Group_X for display
if (name.startsWith('Person_')) {
name = 'Group_' + name.substring(7)
}
console.log('[traceLabel] Found cluster name:', name)
return name
}
}
const n = tr?.name
console.log('[traceLabel] Fallback to:', n || t('people.section.unassigned'))
return n || t('people.section.unassigned')
}
@@ -2028,6 +2065,11 @@ async function loadClusterResults() {
}
const groups = results?.face_groups || results?.clusters || []
const frames = results?.frames || []
console.log('[loadClusterResults] groups:', groups.length, 'frames:', frames.length)
if (frames.length > 0) {
console.log('[loadClusterResults] first frame faces:', frames[0].faces)
console.log('[loadClusterResults] first group:', groups[0])
}
// 統一 group_id → cluster_id, 並添加 group_uuid
for (const g of groups) {
if (g.group_id !== undefined && g.cluster_id === undefined) {
@@ -2069,6 +2111,7 @@ async function loadClusterResults() {
const cid = c.cluster_id || c.group_id
c.member_faces = clusterFacesMap[cid] || []
c.face_count = c.member_faces.length
console.log(`[loadClusterResults] group ${c.name} (cid=${cid}): member_faces=${c.member_faces.length}`)
c.trace_ids = Array.from(clusterTraceIdsMap[cid] || [])
// Set representative_trace from representative_face
if (c.representative_face?.face_id) {
@@ -2083,7 +2126,10 @@ async function loadClusterResults() {
}
}
if (groups.length) {
console.log('[loadClusterResults] Calling setClusterResults with', groups.length, 'groups')
console.log('[loadClusterResults] First group trace_ids:', groups[0]?.trace_ids)
setClusterResults(fileUuid, groups)
console.log('[loadClusterResults] After setClusterResults, cache:', clusterResultsCache.value[fileUuid]?.length)
// Load trace profiles for names in background (non-blocking)
loadClusterNames(fileUuid, groups).catch(() => {})
@@ -2749,7 +2795,7 @@ function closeClusterCtxMenu(e?: MouseEvent) {
clusterCtxMenu.value.show = false
}
function clusterCtxAction(action: string) {
async function clusterCtxAction(action: string) {
const c = clusterCtxMenu.value.cluster
if (!c) return
clusterCtxMenu.value.show = false
@@ -2766,7 +2812,7 @@ function clusterCtxAction(action: string) {
// Update trace profiles via API
const traceIds = clusters[idx]?.trace_ids || []
if (traceIds.length && selectedFileUuid.value) {
updateTraceProfileGroup(selectedFileUuid.value, traceIds, { name })
await updateTraceProfileGroup(selectedFileUuid.value, traceIds, { name })
}
}
} else if (action === 'skip') {
@@ -3297,24 +3343,75 @@ async function executeMerge(targetGroupId: string) {
const sourceGroupIds = groupIds.filter(id => id !== targetGroupId)
const sourceGroups = faceGroups.value.filter((c: any) => sourceGroupIds.includes(c.group_uuid))
const sourceGroupNames = sourceGroups.map(g => g.name).filter(Boolean)
// Collect all trace_ids from source groups
const allTraceIds: number[] = []
for (const g of sourceGroups) {
if (g.trace_ids) {
allTraceIds.push(...g.trace_ids)
}
}
if (sourceGroupNames.length === 0) {
alert('No valid source groups to merge')
if (allTraceIds.length === 0) {
alert('No traces to merge')
return
}
if (!confirm(`Merge ${sourceGroupNames.length} group(s) into "${targetGroupName}"?`)) return
if (!confirm(`Merge ${sourceGroups.length} group(s) with ${allTraceIds.length} trace(s) into "${targetGroupName}"?`)) return
operationLoading.value = true
operationMessage.value = `Merging ${sourceGroupNames.length} group(s)...`
operationMessage.value = `Merging ${sourceGroups.length} group(s)...`
try {
const result = await apiCall('merge_groups', {
fileUuid: selectedFileUuid.value,
sourceGroups: sourceGroupNames,
targetGroupName: targetGroupName
})
// Update all source traces to target group name
console.log('[executeMerge] Updating trace_ids:', allTraceIds, 'to name:', targetGroupName)
// 1. Update trace_profiles via API
const result = await updateTraceProfileGroup(selectedFileUuid.value, allTraceIds, { name: targetGroupName })
console.log('[executeMerge] API Result:', result)
// 2. Update clusterResultsCache locally
const clusters = getClusterResults(selectedFileUuid.value)
// Find target cluster
const targetCluster = clusters.find((c: any) => c.name === targetGroupName || c.cluster_id === targetGroup.cluster_id)
if (targetCluster) {
// Add source trace_ids to target cluster (avoid duplicates)
if (!targetCluster.trace_ids) targetCluster.trace_ids = []
for (const tid of allTraceIds) {
if (!targetCluster.trace_ids.includes(tid)) {
targetCluster.trace_ids.push(tid)
}
}
targetCluster.trace_count = targetCluster.trace_ids.length
}
// Remove trace_ids from source clusters
for (const sourceGroup of sourceGroups) {
const sourceCluster = clusters.find((c: any) => c.cluster_id === sourceGroup.cluster_id || c.group_id === sourceGroup.group_id)
if (sourceCluster && sourceCluster.trace_ids) {
sourceCluster.trace_ids = sourceCluster.trace_ids.filter((tid: number) => !allTraceIds.includes(tid))
sourceCluster.trace_count = sourceCluster.trace_ids.length
}
}
// Remove empty source clusters
const nonEmptyClusters = clusters.filter((c: any) => !sourceGroups.some(sg =>
(c.cluster_id === sg.cluster_id || c.group_id === sg.group_id) && (!c.trace_ids || c.trace_ids.length === 0)
))
setClusterResults(selectedFileUuid.value, nonEmptyClusters)
console.log('[executeMerge] Updated cache')
// Reload thumbnails for updated clusters
for (const c of nonEmptyClusters) {
if (c.trace_ids && c.trace_ids.length > 0) {
const repId = c.representative_trace || c.trace_ids[0]
if (repId) {
loadTraceThumb({ trace_id: repId, file_uuid: selectedFileUuid.value, best_face_id: 0 })
}
}
}
if (result?.success) {
@@ -4121,7 +4218,7 @@ h1 { margin: 0; }
/* Face detail side navigation arrows */
.ms-fs-nav-arrow {
position: fixed; top: 50%; transform: translateY(-50%); z-index: 10010;
position: fixed; top: 50%; transform: translateY(-50%); z-index: 10100;
width: 44px; height: 44px; border-radius: 50%; border: none;
background: rgba(0,0,0,0.5); color: #fff; cursor: pointer;
display: flex; align-items: center; justify-content: center;