review+docs: 接口4 回收到网关、对齐错误码、合并文档为一份实现说明

代码 review 后的清理:
- 接口4 由网关本机实现,worker app.py 的 /face/features 回退 Mock(保持 worker 无外网依赖);
  worker requirements 标注 volcengine 改为网关侧;移除 worker 的接口4 测试(随实现挪到网关)
- 网关接口4 业务错误 HTTP 状态统一改 200(与其余接口/worker 约定一致,原为400/503)
- 接口文档:gender 非法码 1004(原误写1008);修正指向已删文档的链接

文档合并:把各接口技术方案/开发任务书/系统架构/网关任务书 合并成 docs/实现说明.md(简要总览),
删除原 7 份分散文档,README 收敛为索引(实现说明/接口文档/需求/OFFLINE_ASSETS)。

pytest 44 全绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
xsl
2026-06-15 20:58:33 +08:00
co-authored by Claude Opus 4.8
parent 68fe1c1406
commit 76f7c06905
15 changed files with 131 additions and 2624 deletions
+2 -26
View File
@@ -151,32 +151,8 @@ def test_hairline_gen_female(client):
assert "image_url" not in d["hairline_images"][0]
FEATURES = "/api/v1/face/features"
def test_features_success(client, monkeypatch):
import face_features as ff
monkeypatch.setattr(ff, "analyze_features", lambda *a, **k: {
"图片是否有人脸": "有人", "脸型": "鹅蛋脸", "face_shape": "鹅蛋脸",
"gender": "", "gene_style": "少女型"})
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
body = client.post(FEATURES, headers=H, files=files).json()
assert body["code"] == 0, body
f = json.loads(body["data"]["features"]) # features 是 JSON 字符串
assert f["face_shape"] == "鹅蛋脸" and f["gender"] == ""
def test_features_no_face_1001(client, monkeypatch):
import face_features as ff
monkeypatch.setattr(ff, "analyze_features", lambda *a, **k: {"图片是否有人脸": "没人"})
files = {"image_file": ("x.jpg", open(fixture("landscape.jpg"), "rb"), "application/octet-stream")}
assert client.post(FEATURES, headers=H, files=files).json()["code"] == 1001
def test_features_multi_param_1007(client):
files = {"image_file": ("frontal.jpg", open(fixture("frontal.jpg"), "rb"), "application/octet-stream")}
r = client.post(FEATURES, headers=H, files=files, data={"image_url": "http://x/y.jpg"})
assert r.json()["code"] == 1007
# 接口4(用户特征)已迁到网关本机实现(直接调豆包),不再在 worker;
# 其测试随实现一起在网关侧做,worker 这边不再覆盖。
def test_success_structure(client):