# Portal Face Candidates 前端实现报告

> Date: 2026-04-28 21:30
> Status: ✅ 完成

---

## 实现内容

### 新增文件

| 文件 | 说明 |
|------|------|
| `portal/src/views/FaceCandidatesView.vue` | Face Candidates 页面组件 |
| `portal/src/api/client.ts` | 新增 API 函数 |
| `portal/src/router.ts` | 新增路由 |

---

## API 函数

### client.ts 新增

```typescript
export async function listFaceCandidates(
  fileUuid?: string,
  minConfidence = 0.5,
  page = 1,
  pageSize = 20
): Promise<any> {
  // ...
}

export async function getIdentityFaces(
  identityId: number,
  page = 1,
  pageSize = 100
): Promise<any> {
  // ...
}
```

---

## FaceCandidatesView.vue

### 功能

- 显示未绑定的 Face candidates
- 筛选: min_confidence
- 分页: page, page_size
- 点击选择（为后续注册准备）

### UI 结构

```
Header
  ↓
Filter Panel
  - Min Confidence (input)
  - Page Size (input)
  ↓
Statistics
  - Showing X of Y candidates
  - Z selected
  ↓
Face Grid (5 columns)
  - Each card:
    - Placeholder thumbnail
    - Frame number
    - Confidence score (color-coded)
    - Gender/Age (if available)
  ↓
Pagination
  - Previous/Next buttons
```

### 状态管理

```typescript
const candidates = ref<FaceCandidate[]>([])
const loading = ref(false)
const total = ref(0)
const page = ref(1)
const pageSize = ref(20)
const minConfidence = ref(0.8)
const selectedFaces = ref<number[]>([])
```

### Confidence 颜色编码

| Confidence | 颜色 |
|-----------|------|
| >= 0.9 | 🟢 green |
| >= 0.8 | 🔵 blue |
| >= 0.7 | 🟡 yellow |
| < 0.7 | ⚪ gray |

---

## 路由配置

```typescript
{
  path: '/faces/candidates',
  name: 'face-candidates',
  component: () => import('./views/FaceCandidatesView.vue'),
  meta: { requiresAuth: true }
}
```

---

## 访问路径

```
http://localhost:1420/faces/candidates
```

---

## Vite 热更新

Portal 使用 Vite，修改自动生效：
- ✅ client.ts 修改 → 自动生效
- ✅ FaceCandidatesView.vue 创建 → 自动生效
- ✅ router.ts 修改 → 需刷新页面

---

## 待完成功能

### 高优先级

- 🔧 Face 缩略图显示（需要 thumbnail API）
- 🔧 Register Identity 流程（选择 → 输入 name → 提交）

### 中优先级

- 🔧 file_uuid 篛选（显示特定文件的 candidates）
- 🔧 pose_angle 篛选（frontal/profile）
- 🔧 IdentityDetailView Faces tab

---

## Thumbnail API（待实现）

当前使用 placeholder，需要：

**后端**:
```rust
// /api/v1/faces/:id/thumbnail
async fn get_face_thumbnail(face_id: i32) -> Result<Vec<u8>>
```

**前端**:
```typescript
export async function getFaceThumbnail(faceId: number): Promise<string> {
  const config = getConfig()
  return `${config.api_base_url}/api/v1/faces/${faceId}/thumbnail`
}
```

---

## 测试清单

- [ ] 访问 `/faces/candidates` 路径
- [ ] API 调用成功（78 candidates）
- [ ] 篛选功能正常（min_confidence）
- [ ] 分页功能正常
- [ ] 选择功能正常（点击 toggle）

---

## 文件清单

| 文件 | 说明 |
|------|------|
| `portal/src/views/FaceCandidatesView.vue` | 主组件 |
| `portal/src/api/client.ts` | API 函数 |
| `portal/src/router.ts` | 路由配置 |
| `docs_v1.0/PORTAL_FACE_FRONTEND_IMPLEMENTATION.md` | 实现报告 |

---

## 后续建议

### 立即可做

1. 测试页面访问：`http://localhost:1420/faces/candidates`
2. 验证 API 调用
3. 测试篛选和分页

### 短期

1. 实现 Face thumbnail API
2. 实现 Register Identity modal
3. 更新 IdentityDetailView Faces tab

---

## 完整演示流程（未来）

```
访问 Face Candidates
  ↓
篛选 min_confidence > 0.8
  ↓
选择 5 个高质量 faces
  ↓
点击 "Register Identity" 按钮
  ↓
输入 name: "Audrey Hepburn"
  ↓
提交 → POST /api/v1/identities/register
  ↓
跳转到 Identity 详情页
  ↓
显示已绑定的 5 个 faces
```

---

## 总结

**实现时间**: 约 10 分钟

**当前状态**: 
- ✅ 后端 API 完成（2 个）
- ✅ 前端基础 UI 完成（Face Candidates 页面）
- 🔧 缩略图待实现
- 🔧 注册流程待实现

**下一步**: 测试页面，验证 API 调用
