feat: 接入 Face++ 真实测肤 + 三轮多角色迭代修复

Face++ 集成(高阶版 skinanalyze_advanced):
- h5/server.js:零依赖 Node 后端,静态托管 + /api/skin-analyze 中转,
  api_secret 只存服务端(从 apikey.bash/env 读取,.gitignore 已排除)
- 实时相机:getUserMedia 自拍取景,不可用时降级系统相机;
  相机令牌防授权回调泄漏摄像头;离开拍照页即释放
- 检测流:三连拍仅送检正面照(压至 1280px JPEG),错误码→友好提示
- 结果映射:肌肤年龄=skin_age 真实值;紧塑力/活力感/稳定力由真实
  维度合成;具体描述按检出项动态生成;检测图用用户实拍
- ?mock=1 内置样本供离线/自动化验证;README 补充部署与 HTTPS 说明

三轮迭代修复(QA+美术并行审计→开发统一修复,共 ~28 项):
- 功能:P1 鼠标拖拽轮播(Pointer Events+setPointerCapture)、
  快门/返回竞态(camSeq 令牌)、报告页状态重置、弹窗 ESC/遮罩关闭
- 视觉:还原度 80%→94%,档案页布局/弹窗比例/报告页产品卡等
  结构性偏差修正,字号/间距逐项实测核销
- 工程化:首屏 701KB→386KB(懒加载+preload+清理 212KB 无用资源)、
  favicon/SEO meta/隐私协议占位层/README

Review 修复:server.js 路径穿越前缀绕过(ROOT+sep 校验)、
getUserMedia 迟到回调释放相机(camSeqCam 令牌)
This commit is contained in:
xsl
2026-09-22 21:06:33 +08:00
parent e4e85d2805
commit 5957ef04fc
36 changed files with 712 additions and 126 deletions
+95
View File
@@ -0,0 +1,95 @@
# 1'me 在线肌肤测试 H5
拍摄正面与左右侧面照片,调用 **Face++ 皮肤分析(高阶版)** 真实检测,即时生成肌肤状态分析与护理建议的移动端 H5。
- 前端:原生 HTML/CSS/JS,零依赖、零构建
- 后端:`server.js`(Node ≥ 18,零依赖)静态托管 + Face++ API 中转,**api_secret 只存在服务端**
## 目录结构
```
h5/
├── index.html 页面结构(启动 / 档案 / 拍照 / 报告 + 弹层)
├── server.js 后端:静态托管 + POST /api/skin-analyze(Face++ 中转)
├── css/style.css 全部样式(375px 基准)
├── js/app.js 全部交互(屏幕切换、肤质轮播、实时相机、结果映射)
├── assets/
│ ├── favicon.svg 站点图标
│ ├── img/ 背景图、肤质插画、拍照底图、报告检测/产品图
│ └── svg/ 品牌 Logo 与控件图标
└── preview/ 开发期整页截图(仅存档,部署时可整目录剔除)
../apikey.bash Face++ 密钥(export SKIN_API_KEY=... / SKIN_API_SECRET=...,已 .gitignore)
```
## 密钥配置
二选一:
1. 环境变量:`export SKIN_API_KEY=xxx SKIN_API_SECRET=xxx` 后启动 server.js
2. 密钥文件:项目根目录放 `apikey.bash`(内容为 `export SKIN_API_KEY=...` 等,server.js 会自动解析)
**密钥文件已被 .gitignore 排除,严禁提交到版本库。**
## 本地运行
```bash
cd h5
node server.js # 默认 8080,可用 PORT=xxx 修改
# 打开 http://127.0.0.1:8080
```
调试:`http://127.0.0.1:8080/?mock=1` 使用内置样本数据跳过真实检测(离线/自动化验证用)。
## 检测流程与数据映射
1. 三连拍(正面/右脸/左脸):getUserMedia 实时取景,不支持/被拒时自动降级调起系统相机
2. **仅正面照**送检(Face++ 高阶版只接受正脸,yaw>45° 会报错)
3. 照片压缩到最长边 1280 JPEG 后 POST `/api/skin-analyze`,服务端转发 Face++ `skinanalyze_advanced`
4. 映射层(`mapSkinResult`):设计稿的 紧塑力/活力感/稳定力/综合评分 由真实维度合成——
- 紧塑力 ← 法令纹(+严重度)、眼袋(+严重度)
- 活力感 ← 黑眼圈、眼部细纹、鱼尾纹、抬头纹、眉间纹
- 稳定力 ← 敏感泛红(面积/强度)、痘痘、闭口、毛孔、黑头
- 肌肤年龄 = Face++ `skin_age` 真实值;综合评分 = 三维加权(0.35/0.33/0.32)×10
- 具体描述文案按检出项动态生成;报告第一/二张检测图使用用户实拍照片
5. 检测失败(无人脸/距离远/网络等)按错误码给出友好提示并退回档案页
## 部署
需要 Node ≥ 18 运行 `server.js`(负责静态与 API 中转),**不能用纯静态托管**(密钥不能进前端)。
```bash
PORT=8080 node server.js # 建议 pm2 / systemd 常驻
```
nginx 反代示例(静态与 API 都交给 server.js,nginx 只做 HTTPS 终结):
```nginx
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
client_max_body_size 12m; # 与 server.js 请求上限一致
}
}
```
> **HTTPS 必需**:getUserMedia 相机权限仅在安全上下文可用(localhost 除外)。正式域名必须上 HTTPS,否则前端自动降级为系统相机拍照。
## 已知占位清单
- 报告页「活力感 / 稳定力」两个 Tab 为占位文案("以实际检测报告为准")。
- 「相关隐私协议」点击弹出的是占位说明层,协议全文待法务提供后接入。
- 产品图(prod-1.jpg)为设计稿素材;检测图已替换为用户实拍。
- 相册、切换镜头、「了解更多」为开发中占位(Toast 提示)。
- 护理建议为设计稿静态文案,未按检测结果个性化。
## 技术说明
- 尺寸换算:设计稿 1080px 基准 ÷ 2.88 = 375px 落地基准。
- 图片性能:首屏背景 preload;首屏外 `loading="lazy"`。
- 快门防连点/流程令牌(camSeq)防竞态;拍照页 15% 压暗遮罩保证白字可读。