---
id: FEAT-009
title: album
domain: profile
status: done
since_version: 0.5.0
---

# FEAT-009 — 相册管理（多张展示照片）

## User Story

As a **已有头像的用户**, I want to **传 3-5 张生活照进相册**, so that **对方看到我头像感兴趣后能看更多，提高信封转化率**。

## Acceptance Criteria

- [x] `xq profile album add <file>` 加一张相册照
- [x] `xq profile album list` 列自己相册（含签名 URL）
- [x] `xq profile album remove <photo_id>` 删一张
- [x] 相册照片**不影响 avatar**（purpose 分开，profile.avatar_photo_id 不变）
- [x] 和 avatar 共享 OSS 桶（同一 bucket 不同 prefix: `users/<uid>/album/`）
- [x] 同样的 content_type / size 限制（jpeg/png/webp，≤ 5MB）
- [x] 只能删自己的（403）
- [x] list 按 uploaded_at 倒序

## Tests

- `test/test_photo.py::test_upload_album_does_not_touch_profile_avatar`
- `test/test_photo.py::test_list_album_only_returns_album_purpose`
- `test/test_photo.py::test_delete_own_photo`
- `test/test_photo.py::test_delete_someone_elses_photo_forbidden`
- `test/test_photo.py::test_delete_nonexistent_returns_not_found`

## CLI / API

- CLI:
  - `xq profile album add <file>` 实现：`src/xiangqin/cli.py::album_add`
  - `xq profile album list` 实现：`src/xiangqin/cli.py::album_list`
  - `xq profile album remove <photo_id>` 实现：`src/xiangqin/cli.py::album_remove`
- API:
  - `POST /photo/album`（multipart） → `src/xiangqin/app.py::photo_album_add`
  - `GET /photo/album` → `src/xiangqin/app.py::photo_album_list`
  - `DELETE /photo/{photo_id}` → `src/xiangqin/app.py::photo_delete`

## 依赖 / 被依赖

- **依赖**：和 `FEAT-008 avatar` 共享 OSS / 审核 / db.user_photos 表
- **被依赖**：
  - 查匹配详情 API（未来）会返回对方相册签名 URL 列表
  - `FEAT-014 dm.send` 发信时可预览对方相册决定称呼

## 风险 / 边界

- **相册张数上限**：当前无限制，未来加上限（建议 20 张）防刷 + 控制 OSS 成本
- **审核**：和 avatar 同规则，stub 待绿网集成
- **相册展示顺序**：当前按上传时间，未来可能加 `display_order` 字段让用户排序
- **公开性**：相册照片通过签名 URL 暴露，任何登录用户 query 到对方都能看 —— 等同公开（和 Tinder / 相亲场景一致）
- **不做**：短视频 / GIF 动图（存储成本高 + 审核复杂）

## 相关

- issue `#015`
- FEAT-008 avatar（同模块）
- 未来：query 详情页返回对方相册（产品演进点）
