save code

This commit is contained in:
Ubuntu
2026-02-10 10:09:24 +08:00
parent c93d8b7236
commit cf1cbbd597
10 changed files with 1060 additions and 7 deletions
+556
View File
@@ -0,0 +1,556 @@
# 发型更换H5项目 — 完整项目分析文档
> 分析日期:2026-02-10
> 分析范围:项目架构、前端、后端、API、数据、测试、部署及问题汇总
---
## 目录
1. [项目概览](#1-项目概览)
2. [项目结构](#2-项目结构)
3. [技术栈总览](#3-技术栈总览)
4. [后端分析](#4-后端分析)
5. [前端分析](#5-前端分析)
6. [API 接口分析](#6-api-接口分析)
7. [数据流分析](#7-数据流分析)
8. [第三方依赖与外部服务](#8-第三方依赖与外部服务)
9. [测试分析](#9-测试分析)
10. [部署现状](#10-部署现状)
11. [已有文档评估](#11-已有文档评估)
12. [存在的问题与风险](#12-存在的问题与风险)
13. [优化建议](#13-优化建议)
14. [总结](#14-总结)
---
## 1. 项目概览
### 1.1 产品定位
这是一个基于 H5 的 **AI 发型更换与发色更换应用**,用户可以:
- **上传照片** → **选择发型** → 获取 AI 换发型后的效果图
- **上传照片** → **选择颜色和强度** → 获取 AI 换发色后的效果图
核心价值:帮助用户在剪发/染发前,直观预览不同发型和发色效果。
### 1.2 功能模块
| 模块 | 功能 | 状态 |
|------|------|------|
| 图片上传 | 支持上传本地照片 | ✅ 已实现 |
| 发型更换 | 从发型库选择发型,AI 替换 | ✅ 已实现 |
| 发色更换 | 通过颜色选择器选色,AI 替换发色 | ✅ 已实现 |
| 结果预览 | 查看效果图,支持保存下载 | ✅ 已实现 |
| 拍照功能 | 移动端拍照 | ❌ PRD中提及但未实现 |
| 性别分类 | 按男/女分类发型 | ❌ PRD中提及但未实现 |
| 分享功能 | 社交分享 | ❌ PRD中提及但未实现 |
---
## 2. 项目结构
```
hair_change_color/
├── backend/ # 后端 Python/Flask 服务
│ ├── app.py # Flask 主应用(391行)- 路由、API、业务逻辑
│ ├── config.py # 配置文件(20行)- API URL、超时、文件限制
│ ├── data/
│ │ └── hairstyles.json # 发型数据(实际未使用,数据从 hairId2url.txt 加载)
│ ├── requirements.txt # Python 依赖(Flask, Flask-CORS, requests
│ ├── app.log # Gunicorn 日志
│ └── nohup.out # 开发服务器日志
├── frontend/ # 前端 H5 页面
│ ├── index.html # 主页面(142行)- 单页应用
│ ├── css/
│ │ └── style.css # 样式文件(393行)- 响应式设计
│ ├── js/
│ │ ├── main.js # 主逻辑(452行)- 状态管理、交互、API调用
│ │ └── api.js # API封装(32行)- 实际未被引用
│ └── frontend.log # 前端日志
├── docs/ # 项目文档
│ ├── PRD.md # 产品需求文档
│ ├── ARCHITECTURE.md # 系统架构文档
│ ├── API.md # API接口文档
│ └── DEPLOYMENT.md # 部署文档
├── test/ # 测试目录
│ ├── test_hair.py # 发型更换API压测脚本
│ └── wertwert.jpg # 测试用图片
└── hairId2url.txt # 发型ID到OSS URL的映射文件(60条记录)
```
---
## 3. 技术栈总览
### 3.1 前端
| 技术 | 用途 |
|------|------|
| HTML5 | 页面结构,单页应用 |
| CSS3 | 响应式布局、动画、Flexbox/Grid |
| JavaScript (ES6+) | 交互逻辑、DOM操作 |
| Axios (CDN) | HTTP 请求 |
| FileReader API | 本地图片读取预览 |
### 3.2 后端
| 技术 | 用途 |
|------|------|
| Python 3.8+ | 核心语言 |
| Flask | Web 框架 |
| Flask-CORS | 跨域支持 |
| requests | 远程 API 调用 |
| Gunicorn | 生产部署 WSGI 服务器 |
### 3.3 外部服务
| 服务 | 地址 | 用途 |
|------|------|------|
| 发型替换 API | `http://xiangsilian.com:18801/api/swapHair/v1` | AI 发型替换 |
| 发色替换 API | `http://xiangsilian.com:18801/hairColor/v2` | AI 发色替换 |
| 阿里云 OSS | `xiangsilian.oss-cn-beijing.aliyuncs.com` | 发型图片存储 |
---
## 4. 后端分析
### 4.1 应用入口 (`app.py`)
Flask 应用作为 **API 网关/代理层**,主要职责:
1. 管理发型数据,向前端提供发型列表
2. 接收用户上传的图片,转发给远程 AI API 处理
3. 将处理结果(base64图片)返回前端
4. 开发模式下提供前端静态文件
### 4.2 配置管理 (`config.py`)
```python
APP_NAME = "Hair Change Color"
REMOTE_API_URL = "http://xiangsilian.com:18801/api/swapHair/v1"
REMOTE_HAIR_COLOR_API_URL = "http://xiangsilian.com:18801/hairColor/v2"
API_TIMEOUT = 120 # 超时120秒(远程AI处理耗时较长)
MAX_CONTENT_LENGTH = 16MB # 上传文件限制
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
DEBUG = True
```
### 4.3 数据加载机制
- 启动时从 `../hairId2url.txt` 读取发型 ID 与 OSS URL 的映射
- 解析规则:`文件名.jpg -> OSS URL`,提取文件名作为 ID
- 自动生成发型名称:`发型{ID后4位}`
-**60 个发型** 可供选择
- **注意**`data/hairstyles.json` 文件存在但实际未被使用
### 4.4 核心处理流程
#### 发型更换流程
```
用户上传图片 + 选择发型ID
后端接收 (POST /api/change-hair)
验证文件类型和参数
图片转 base64
调用远程 API (swapHair/v1)
- 参数: hair_id, task_id, user_img_path(base64), is_hr, output_format
解析响应,提取处理后的图片
返回 base64 data URL 给前端
```
#### 发色更换流程
```
用户上传图片 + 选择RGB颜色 + 设置强度(ratio)
后端接收 (POST /api/change-hair-color)
验证文件类型和参数
图片转 base64,解析 RGB 数组
调用远程 API (hairColor/v2)
- 参数: img(base64), userId, rgb, ratio, output_format
解析响应,提取处理后的图片
返回 base64 data URL 给前端
```
### 4.5 错误处理策略
| 类型 | 状态码 | 处理方式 |
|------|--------|----------|
| 缺少图片/参数 | 400 | 返回中文错误消息 |
| 文件类型不合法 | 400 | 返回错误消息 |
| 远程API失败 | 500 | 返回原图作为降级方案 |
| 其他异常 | 500 | 返回通用错误消息 |
---
## 5. 前端分析
### 5.1 页面结构(单页应用)
采用 **手动页面切换** 的单页应用模式(无路由库):
| 页面 | DOM ID | 功能 |
|------|--------|------|
| 首页 | `homePage` | 图片上传 + 功能入口(换发型/换发色) |
| 发型选择页 | `hairstylePage` | 发型网格列表,点击选择 |
| 发色选择页 | `hairColorPage` | 颜色选择器 + 强度滑块 |
| 结果预览页 | `resultPage` | 结果展示 + 重选/保存操作 |
### 5.2 状态管理
使用全局变量管理状态:
```javascript
uploadedImage // 上传的文件对象
selectedHairstyle // 选中的发型ID
hairstylesData // 缓存的发型列表
selectedColor // 选中的颜色(hex
selectedRatio // 颜色强度(0-1
currentFunction // 当前模式:'hairstyle' | 'color'
```
### 5.3 用户交互流程
```
首页
├── 上传图片 → 显示预览
├── 点击"更换发型" → 发型选择页
│ ├── 选择发型 → 高亮反馈
│ └── 确认 → Loading → 结果页
└── 点击"更换头发颜色" → 发色选择页
├── 选择颜色 → 实时预览RGB值
├── 调节强度 → 滑块
└── 确认 → Loading → 结果页
结果页
├── 重新选择发型/颜色
├── 重新上传图片
└── 保存结果(下载图片)
```
### 5.4 UI设计
- **设计风格**:现代简约,蓝色(#4A90E2)为主色调,青色(#50E3C2)为辅色
- **响应式**:三个断点(移动端 < 768px / 平板 768-1024px / PC > 1024px
- **交互效果**:悬停阴影、选中高亮边框、加载动画
- **导航**:顶部固定导航栏 + 返回按钮
### 5.5 关键工具函数
| 函数 | 功能 |
|------|------|
| `hexToRgb()` | 将 hex 颜色值转换为 RGB 对象 |
| `showPage()` | 管理页面可见性切换 |
| `showLoading()` / `hideLoading()` | 全屏加载遮罩控制 |
| `getHairstyles()` | 获取发型列表 |
| `changeHair()` | 调用发型更换 API |
| `changeHairColor()` | 调用发色更换 API |
---
## 6. API 接口分析
### 6.1 接口总览
| 接口 | 方法 | 功能 | 认证 |
|------|------|------|------|
| `/api/hairstyles` | GET | 获取发型列表 | 无 |
| `/api/change-hair` | POST | AI 发型替换 | 无 |
| `/api/change-hair-color` | POST | AI 发色替换 | 无 |
| `/``/<path>` | GET | 静态文件服务 | 无 |
### 6.2 接口详情
#### GET `/api/hairstyles`
**响应示例:**
```json
{
"success": true,
"data": {
"hairstyles": [
{
"id": "1953267161121464322",
"name": "发型4322",
"image_url": "https://xiangsilian.oss-cn-beijing.aliyuncs.com/hair_images/1953267161121464322.jpg"
}
]
}
}
```
#### POST `/api/change-hair`
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `image` | File | 是 | 用户照片 |
| `hairstyle_id` | String | 是 | 发型 ID |
**响应:** `{ "success": true, "data": { "result_image": "data:image/jpeg;base64,..." } }`
#### POST `/api/change-hair-color`
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `image` | File | 是 | 用户照片 |
| `rgb` | String | 是 | RGB 数组字符串,如 `"[255, 106, 0]"` |
| `ratio` | String | 是 | 替换强度 0.0-1.0 |
**响应:** `{ "success": true, "data": { "result_image": "data:image/jpeg;base64,..." } }`
### 6.3 API 文档与实现差异
| 项目 | 文档描述 | 实际实现 |
|------|----------|----------|
| `/api/change-hair-color` | 文档中 **未记录** | 已实现 |
| 发型数据源 | `data/hairstyles.json` | 实际从 `hairId2url.txt` 加载 |
| 性别分类 | 文档描述有 `gender` 字段 | 未实现 |
| 响应格式 | 统一 `message` 字段 | 部分接口缺少 `message` 字段 |
---
## 7. 数据流分析
```
┌──────────────┐ HTTP ┌──────────────┐ HTTP ┌──────────────────┐
│ 前端 H5 │ ◄──────────► │ Flask 后端 │ ◄──────────► │ 远程 AI API │
│ (浏览器) │ JSON/Base64 │ (代理层) │ JSON/Base64 │ xiangsilian.com │
└──────────────┘ └──────────────┘ └──────────────────┘
│ │ │
│ 1. 上传图片+参数 │ │
│ ─────────────────────────► │ │
│ │ 2. base64编码+转发 │
│ │ ────────────────────────────► │
│ │ │
│ │ 3. AI处理结果(base64) │
│ │ ◄──────────────────────────── │
│ 4. 返回结果图片 │ │
│ ◄───────────────────────── │ │
│ │ │
│ 发型图片 │ │
│ ◄─────────────────────────────────── 阿里云 OSS ─────────┘
```
**数据传输特点:**
- 图片全程使用 **base64 编码** 传输,不存储在服务器文件系统
- 远程 API 超时设置为 **120秒**AI 处理耗时较长)
- 发型缩略图直接从 **阿里云 OSS** CDN 加载
---
## 8. 第三方依赖与外部服务
### 8.1 Python 依赖
| 包名 | 用途 | 风险评估 |
|------|------|----------|
| Flask | Web 框架 | 低 - 成熟稳定 |
| Flask-CORS | 跨域支持 | 低 |
| requests | HTTP 客户端 | 低 |
### 8.2 前端依赖
| 库 | 来源 | 用途 |
|----|------|------|
| Axios | CDN (jsdelivr) | HTTP 请求 |
### 8.3 外部服务依赖
| 服务 | 可控性 | 风险 |
|------|--------|------|
| AI API (xiangsilian.com:18801) | **不可控** | 高 - 服务不可用则核心功能失效 |
| 阿里云 OSS | 可控 | 中 - 影响发型图片展示 |
---
## 9. 测试分析
### 9.1 现有测试
项目仅有一个测试文件 `test/test_hair.py`,功能为:
- **压力测试脚本**:多线程并发请求发型更换 API
- 将本地图片编码为 base64 发送请求
- 记录 QPS 和总耗时
- 保存 API 返回的结果图片
### 9.2 测试覆盖不足
| 测试类型 | 状态 |
|----------|------|
| 单元测试 | ❌ 无 |
| 接口测试 | ❌ 无(仅有手动压测脚本) |
| 前端测试 | ❌ 无 |
| 端到端测试 | ❌ 无 |
| 发色更换测试 | ❌ 无 |
| 错误场景测试 | ❌ 无 |
---
## 10. 部署现状
### 10.1 当前部署方式
根据日志文件分析:
| 组件 | 部署方式 | 端口 |
|------|----------|------|
| 后端 | Gunicorn (生产) / Flask dev server (开发) | 48080 / 5000 |
| 前端 | 由后端 Flask 提供静态文件 | 同后端 |
### 10.2 存在的问题
- 日志显示 **Gunicorn worker 超时**,表明远程 API 响应慢导致请求阻塞
- 日志中有大量 **非法 HTTP 请求**,可能是扫描/攻击流量
- `DEBUG = True` 在生产环境中仍然开启
- 使用 **HTTP**(非 HTTPS)暴露在公网
---
## 11. 已有文档评估
| 文档 | 文件 | 完整性 | 准确性 | 备注 |
|------|------|--------|--------|------|
| 产品需求文档 | `docs/PRD.md` | ⭐⭐⭐ | ⭐⭐ | 缺少发色更换功能描述,部分功能未实现 |
| 架构文档 | `docs/ARCHITECTURE.md` | ⭐⭐⭐ | ⭐⭐ | 缺少发色更换 API 描述,数据源描述与实际不符 |
| API 文档 | `docs/API.md` | ⭐⭐ | ⭐⭐ | 缺少 `/api/change-hair-color` 接口 |
| 部署文档 | `docs/DEPLOYMENT.md` | ⭐⭐⭐⭐ | ⭐⭐⭐ | 较为完整但缺少实际端口配置 |
**总体评估**:文档在项目初期创建,后续代码演进(新增发色更换功能、数据源更改等)后 **未同步更新**
---
## 12. 存在的问题与风险
### 12.1 代码质量问题
| 严重度 | 问题 | 位置 | 说明 |
|--------|------|------|------|
| 🔴 高 | `api.js` 未被引用 | `frontend/js/api.js` | 使用 ES6 export 但 main.js 未 importAPI 函数在 main.js 中重复定义 |
| 🔴 高 | `userId` 硬编码 | `backend/app.py` | 发色 API 中 userId 硬编码为 `"18701620166"` |
| 🟡 中 | 拼写错误 | `frontend/js/main.js` | `disabled` 拼写为 `disbled` |
| 🟡 中 | `hairstyles.json` 未使用 | `backend/data/` | 存在但不被加载,容易误导 |
| 🟡 中 | 无环境变量支持 | `backend/config.py` | 所有配置硬编码,无法按环境切换 |
| 🟢 低 | 代码重复 | `backend/app.py` | `change_hair``change_hair_color` 有大量重复逻辑 |
### 12.2 安全问题
| 严重度 | 问题 | 说明 |
|--------|------|------|
| 🔴 高 | 无认证机制 | 所有 API 完全公开,无任何访问控制 |
| 🔴 高 | 无限流保护 | 无 Rate Limiting,可被恶意调用 |
| 🔴 高 | DEBUG 模式生产环境开启 | 可能泄露敏感信息 |
| 🔴 高 | HTTP 明文传输 | 未使用 HTTPS |
| 🟡 中 | CORS 全开 | 允许所有来源跨域请求 |
| 🟡 中 | 无请求体大小验证 | 虽配置了 16MB 限制,但缺少前端校验 |
### 12.3 可靠性问题
| 严重度 | 问题 | 说明 |
|--------|------|------|
| 🔴 高 | 远程 API 单点依赖 | 远程 AI API 不可用则核心功能全部失效 |
| 🔴 高 | 同步阻塞处理 | 请求阻塞最长120秒,占用 worker 进程 |
| 🟡 中 | 无重试机制 | 远程 API 调用失败不会重试 |
| 🟡 中 | 错误降级返回原图 | 用户可能不知道处理失败 |
| 🟡 中 | Worker 超时 | Gunicorn 日志显示频繁 worker timeout |
### 12.4 文档与代码不一致
| 问题 | 说明 |
|------|------|
| 发色更换 API 未记录 | 已实现的 `/api/change-hair-color` 未出现在 API 文档中 |
| 数据源不一致 | 文档说使用 `hairstyles.json`,实际使用 `hairId2url.txt` |
| 目录结构过时 | 文档中的目录结构缺少 `test/``hairId2url.txt` 等 |
| PRD 与实现偏差 | 性别分类、拍照功能、分享功能均未实现 |
---
## 13. 优化建议
### 13.1 优先级高(建议立即修复)
1. **关闭生产环境 DEBUG 模式**
- `config.py``DEBUG = True` 改为通过环境变量控制
2. **添加基础安全防护**
- 添加 Rate Limiting(如 `flask-limiter`
- 配置 CORS 白名单,而非允许所有来源
- 启用 HTTPS
3. **修复代码缺陷**
- 修复 `main.js` 中的拼写错误
- 移除或整合未使用的 `api.js`
- 清理未使用的 `hairstyles.json`
4. **同步更新文档**
- API 文档补充 `/api/change-hair-color` 接口
- 更新架构文档中的数据源描述
### 13.2 优先级中(建议近期优化)
5. **引入环境变量配置**
```python
import os
REMOTE_API_URL = os.getenv('REMOTE_API_URL', 'http://...')
DEBUG = os.getenv('FLASK_DEBUG', 'false').lower() == 'true'
```
6. **异步处理优化**
- 使用 `gevent` 或 `asyncio` 替代同步阻塞
- 或使用任务队列(如 Celery)处理长耗时请求
7. **增加错误提示**
- 远程 API 失败时明确告知用户"处理失败",而非默默返回原图
8. **添加基础测试**
- 编写 API 接口单元测试
- 添加参数校验边界测试
### 13.3 优先级低(长期改进)
9. **前端重构**
- 考虑使用 Vue/React 等框架重构
- 引入前端构建工具(Vite 等)
10. **添加缓存层**
- 对相同图片+相同发型的请求结果进行缓存
11. **完善监控**
- 引入结构化日志
- 添加 API 调用指标监控
12. **实现 PRD 中未完成的功能**
- 性别分类筛选
- 移动端拍照
- 社交分享
---
## 14. 总结
### 14.1 项目整体评价
| 维度 | 评分 | 说明 |
|------|------|------|
| 功能完成度 | ⭐⭐⭐ | 核心功能(换发型+换发色)已实现,部分 PRD 功能未实现 |
| 代码质量 | ⭐⭐ | 结构清晰但存在代码重复、未使用文件、拼写错误等问题 |
| 架构设计 | ⭐⭐⭐ | 前后端分离合理,代理模式设计得当 |
| 安全性 | ⭐ | 缺少认证、限流、HTTPS 等基本安全措施 |
| 可维护性 | ⭐⭐ | 文档与代码不同步,缺少测试覆盖 |
| 可扩展性 | ⭐⭐⭐ | 架构简单,扩展方便 |
| 部署运维 | ⭐⭐ | 有基础部署但缺少监控和自动化 |
### 14.2 一句话总结
> 这是一个功能可用的 **AI 发型/发色更换 H5 应用**,采用经典的 Flask 代理 + 原生前端架构,核心业务逻辑依赖远程 AI API。项目已具备基本功能但在 **安全防护、测试覆盖、文档维护** 方面存在明显不足,建议优先解决安全问题和文档同步,再逐步优化架构和代码质量。