feat: 人员库弹框显示人员图片

This commit is contained in:
2026-04-19 16:43:25 +08:00
parent e75425ac14
commit 69b57b1904
13 changed files with 63 additions and 1 deletions

Binary file not shown.

View File

@@ -195,6 +195,25 @@ async def rename_person(person_id: str, name: str):
raise HTTPException(status_code=404, detail="人员不存在")
@app.get("/api/persons/{person_id}/face")
async def get_person_face(person_id: str):
"""获取人员人脸图片"""
from person_manager import person_manager
from pathlib import Path
if person_id in person_manager.persons:
face_path = person_manager.persons[person_id].get('face_path', '')
if face_path and Path(face_path).exists():
return FileResponse(face_path)
# 检查 faces_dir 中的默认图片
face_file = person_manager.faces_dir / f"{person_id}.jpg"
if face_file.exists():
return FileResponse(str(face_file))
raise HTTPException(status_code=404, detail="人员图片不存在")
@app.get("/api/stats/daily")
async def get_daily_stats(date: str = None):
"""获取每日统计数据"""

View File

@@ -630,7 +630,15 @@ function loadPersonsList() {
var firstSeen = new Date(person.first_seen).toLocaleString();
var lastSeen = new Date(person.last_seen).toLocaleString();
item.innerHTML = '<div class="person-info">' +
// 构建人员图片URL
var faceImgHtml = '<div class="person-face-placeholder">No Image</div>';
if (person.face_path) {
faceImgHtml = '<img class="person-face-img" src="/api/persons/' + person.person_id + '/face" alt="' + person.name + '" onerror="this.parentElement.innerHTML=\'<div class=&quot;person-face-placeholder&quot;>No Image</div>\'">';
}
item.innerHTML = '<div class="person-face">' + faceImgHtml + '</div>' +
'<div class="person-content">' +
'<div class="person-info">' +
'<span class="person-name">' + person.name + '</span>' +
'<span class="person-id">' + person.person_id + '</span>' +
'</div>' +
@@ -642,6 +650,7 @@ function loadPersonsList() {
'<div class="person-actions">' +
'<button onclick="renamePerson(\'' + person.person_id + '\')" class="btn-small">Rename</button>' +
'<button onclick="deletePerson(\'' + person.person_id + '\')" class="btn-small btn-danger">Delete</button>' +
'</div>' +
'</div>';
listDiv.appendChild(item);

View File

@@ -751,6 +751,38 @@ button {
margin-bottom: 8px;
border-radius: 8px;
border-left: 4px solid #2196F3;
display: flex;
gap: 12px;
align-items: flex-start;
}
.person-face {
width: 80px;
height: 80px;
border-radius: 8px;
overflow: hidden;
background: #e0e0e0;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.person-face-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.person-face-placeholder {
color: #888;
font-size: 12px;
text-align: center;
}
.person-content {
flex: 1;
min-width: 0;
}
.person-info {
@@ -771,6 +803,7 @@ button {
.person-stats {
display: flex;
flex-wrap: wrap;
gap: 10px;
color: #555;
font-size: 12px;