diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3168dca --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# 密钥与敏感配置 —— 绝不入库 +apikey.bash +apikey.* +.env +.env.* + +# 运行时产物 +node_modules/ +*.log +__pycache__/ diff --git a/design/设计规范.md b/design/设计规范.md index 3309c87..c68c0fc 100644 --- a/design/设计规范.md +++ b/design/设计规范.md @@ -131,7 +131,7 @@ design/ ## 8. 还原建议 1. **流程**:启动页(授权弹窗)→ 档案填写(年龄/性别/地区/肤质轮播)→ 拍照弹窗 → 正面/左/右三连拍 → 生成报告。 -2. 肤质选择是**轮播交互**(轮播标识×4 圆点 + 偏干↔偏油轴标签),插画随选项换色。 +2. 肤质选择是**轮播交互**(轮播标识×5 圆点 + 偏干↔偏油轴标签),插画随选项换色。 3. 报告页为长滚动页:总分(82 分/100)→ 六维度 → 三维度拆解 → 具体描述(配检测图)→ 护理建议 → 产品推荐 → 免责声明。 4. 位图素材均为 PNG(原始命名 .jpg 已改),报告页背景 4915×11457 建议压缩后再入包。 5. 颜色、字号直接抄本规范第 2、3 节;组件直接用 assets/svg 切图。 diff --git a/h5/README.md b/h5/README.md new file mode 100644 index 0000000..e1f0e87 --- /dev/null +++ b/h5/README.md @@ -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% 压暗遮罩保证白字可读。 diff --git a/h5/assets/favicon.svg b/h5/assets/favicon.svg new file mode 100644 index 0000000..0127094 --- /dev/null +++ b/h5/assets/favicon.svg @@ -0,0 +1,4 @@ + diff --git a/h5/assets/img/bg-profile.jpg b/h5/assets/img/bg-profile.jpg deleted file mode 100644 index 220d6d2..0000000 Binary files a/h5/assets/img/bg-profile.jpg and /dev/null differ diff --git a/h5/assets/img/bg-report.jpg b/h5/assets/img/bg-report.jpg deleted file mode 100644 index 69f150f..0000000 Binary files a/h5/assets/img/bg-report.jpg and /dev/null differ diff --git a/h5/assets/img/det-3.jpg b/h5/assets/img/det-3.jpg deleted file mode 100644 index 776f9c2..0000000 Binary files a/h5/assets/img/det-3.jpg and /dev/null differ diff --git a/h5/assets/img/prod-2.jpg b/h5/assets/img/prod-2.jpg deleted file mode 100644 index 4799bb1..0000000 Binary files a/h5/assets/img/prod-2.jpg and /dev/null differ diff --git a/h5/assets/img/prod-3.jpg b/h5/assets/img/prod-3.jpg deleted file mode 100644 index 1c615fb..0000000 Binary files a/h5/assets/img/prod-3.jpg and /dev/null differ diff --git a/h5/assets/img/prod-4.jpg b/h5/assets/img/prod-4.jpg deleted file mode 100644 index 496e356..0000000 Binary files a/h5/assets/img/prod-4.jpg and /dev/null differ diff --git a/h5/assets/svg/按钮-主按钮.svg b/h5/assets/svg/按钮-主按钮.svg deleted file mode 100644 index 9ad0646..0000000 --- a/h5/assets/svg/按钮-主按钮.svg +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/h5/assets/svg/肤质-面部插画.svg b/h5/assets/svg/肤质-面部插画.svg deleted file mode 100644 index 8edab13..0000000 --- a/h5/assets/svg/肤质-面部插画.svg +++ /dev/null @@ -1,28 +0,0 @@ - diff --git a/h5/css/style.css b/h5/css/style.css index 415e09d..880c336 100644 --- a/h5/css/style.css +++ b/h5/css/style.css @@ -85,7 +85,7 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } text-shadow: 0 1px 8px rgba(0,0,0,.18); } .splash-bottom { - position: absolute; left: 0; right: 0; bottom: 7%; + position: absolute; left: 0; right: 0; bottom: 11%; display: flex; flex-direction: column; align-items: center; gap: 18px; padding-bottom: env(safe-area-inset-bottom); } @@ -105,7 +105,14 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } .nav-dark { background: rgba(20,20,20,.55); } .nav-dark .nav-title { color: #fff; } .nav-dark .chev { border-color: #fff; } -.nav-back { width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; } +.nav-back { + width: 27px; height: 27px; + display: flex; align-items: center; justify-content: center; + border: 1px solid #E5E5E5; border-radius: 50%; + background: #fff; +} +/* 深色导航(拍照页):半透明白底盘 + 浅白描边 */ +.nav-dark .nav-back { background: rgba(255,255,255,.18); border-color: rgba(255,255,255,.4); } .nav-title { position: absolute; left: 50%; transform: translateX(-50%); font-size: 14px; font-weight: 500; color: #000; @@ -125,9 +132,10 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } .profile-body { position: relative; z-index: 1; min-height: 100%; - padding: calc(var(--nav-h) + 18px) 38px 40px; - display: flex; flex-direction: column; justify-content: flex-end; - gap: 13px; + /* 设计:标题在导航下 23px;按钮随内容流(卡底→按钮间距按设计节奏约 22px) */ + padding: calc(var(--nav-h) + 23px) 64px clamp(48px, 8vh, 121px); + display: flex; flex-direction: column; justify-content: flex-start; + gap: 16px; } .page-title { color: #fff; font-size: 21px; font-weight: 700; @@ -138,7 +146,7 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } color: #fff; font-size: 14px; font-weight: 400; margin-bottom: 6px; letter-spacing: .5px; } -.form-row.two { display: flex; gap: 8px; } +.form-row.two { display: flex; gap: 22px; } .form-row.two .field { flex: 1; } .field-input { display: block; width: 100%; height: 38px; @@ -153,37 +161,38 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } /* 肤质卡片 */ .skin-card { - background: #fff; border-radius: 10px; - padding: 12px 10px 14px; + background: #fff; border-radius: 6px; + padding: 24px 10px 26px; } .skin-axis { - display: flex; justify-content: center; gap: 14px; - margin-bottom: 4px; + display: flex; justify-content: center; gap: 8px; + margin: 0 0 14px; } .axis-item { display: inline-flex; align-items: center; gap: 4px; font-size: 9px; color: var(--ink); } .chip { width: 8px; height: 8px; border-radius: 2px; display: inline-block; } -.skin-carousel { overflow: hidden; } +.skin-carousel { overflow: hidden; touch-action: pan-y; /* 纵向滚动交给浏览器,横向留给拖拽 */ } .skin-track { display: flex; transition: transform .32s cubic-bezier(.22,.61,.36,1); } .skin-item { flex: 0 0 100%; display: flex; flex-direction: column; align-items: center; } .skin-item img { width: 109px; height: 109px; } -.skin-name { font-size: 13px; font-weight: 500; color: #000; margin-top: 2px; } +.skin-name { font-size: 13px; font-weight: 500; color: #000; margin-top: 12px; } .skin-desc { font-size: 10px; color: var(--ink); font-weight: 400; line-height: 1.5; text-align: center; - margin-top: 5px; padding: 0 12px; + margin-top: 5px; padding: 0 26px; } -.skin-dots { display: flex; justify-content: center; gap: 7px; margin-top: 10px; } +.skin-dots { display: flex; justify-content: center; gap: 7px; margin-top: 16px; } .skin-dots i { - width: 6px; height: 6px; border-radius: 50%; + width: 8px; height: 8px; border-radius: 50%; background: #D6D6D6; transition: background .25s; } -.skin-dots i.on { background: var(--ink); } +.skin-dots i.on { background: #000; } +/* 按钮随内容流:卡底→按钮间距 22px(= flex gap 16 + 此处 6),两侧 auto 居中 */ .btn-submit { margin: 6px auto 0; } /* ═══════════ 05-07 拍照页 ═══════════ */ @@ -192,9 +201,21 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } position: absolute; inset: 0; background-size: cover; background-position: center; } +/* 实时相机画面(getUserMedia 成功后显示,盖住静态示意图) */ +#cam-video { + position: absolute; inset: 0; + width: 100%; height: 100%; + object-fit: cover; + transform: scaleX(-1); /* 自拍镜面预览 */ + display: none; z-index: 0; +} +#s-cam.cam-live #cam-video { display: block; } +#s-cam.cam-live .cam-bg { display: none; } +/* 15% 黑遮罩,压住画面保证白色文案可读(静态示意图与实时画面共用) */ +#s-cam::before { content: ""; position: absolute; inset: 0; background: rgba(0,0,0,.15); z-index: 1; } #s-cam .nav { position: fixed; left: 0; right: 0; } .cam-step { - position: absolute; left: 0; right: 0; top: 15%; + position: absolute; left: 0; right: 0; top: 16.5%; text-align: center; color: #fff; font-size: 21px; font-weight: 500; line-height: 1.5; letter-spacing: 1px; @@ -202,17 +223,17 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } z-index: 2; } .cam-guide { - position: absolute; left: 0; right: 0; bottom: 17%; + position: absolute; left: 0; right: 0; bottom: 20%; display: flex; justify-content: center; align-items: center; gap: 18px; z-index: 2; } .cam-guide span { color: #fff; font-size: 14px; font-weight: 400; opacity: .92; } -.cam-guide i { width: 0; height: 15px; border-left: 1px solid rgba(255,255,255,.5); } +.cam-guide i { width: 0; height: 15px; border-left: 1px solid #fff; } .cam-controls { - position: absolute; left: 0; right: 0; bottom: 6%; + position: absolute; left: 0; right: 0; bottom: 5.2%; display: flex; align-items: center; justify-content: space-between; padding: 0 55px; - padding-bottom: calc(10px + env(safe-area-inset-bottom)); + padding-bottom: env(safe-area-inset-bottom); z-index: 2; } .cam-side img { width: 31px; height: 31px; } @@ -220,7 +241,7 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } .cam-shutter:active { transform: scale(.92); } .cam-flash { position: absolute; inset: 0; background: #fff; - opacity: 0; pointer-events: none; z-index: 9; + opacity: 0; pointer-events: none; z-index: 30; /* 盖住导航(z 20) */ transition: opacity .18s ease; } .cam-flash.on { opacity: .92; } @@ -229,28 +250,35 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } .report-body { padding: 12px 38px 34px; } .report-title { font-size: 20px; font-weight: 700; color: var(--ink); - text-align: center; margin: 8px 0 12px; + text-align: center; margin: 10px 0 16px; letter-spacing: .5px; } .card { - background: #fff; border-radius: 10px; + background: #fff; border-radius: 6px; padding: 14px 15px; margin-bottom: 9px; } /* 总分 */ -.card-stats { display: flex; } +.card-stats { display: flex; padding: 11px 15px; } .stat { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px; } .stat-label { font-size: 9px; font-weight: 500; color: var(--grey); } -.stat-value { font-size: 29px; font-weight: 400; color: var(--ink); letter-spacing: 1px; } -/* 维度 */ -.dims-intro { font-size: 10px; font-weight: 500; color: #464646; line-height: 1.6; margin-bottom: 10px; } +/* label 下短横线(34×1 居中) */ +.stat-label::after { + content: ""; display: block; + width: 34px; height: 1px; background: #EFEFEF; + margin: 4px auto 0; +} +.stat-value { font-size: 29px; font-weight: 400; color: var(--ink); letter-spacing: 1px; line-height: 34px; } +/* 维度(灰底独立文字,置于总分卡与维度卡之间) */ +.dims-intro { font-size: 10px; font-weight: 500; color: #464646; line-height: 1.6; margin: 0 2px 9px; } .dims-row { display: flex; } .dim { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px; } +.dim + .dim { border-left: 1px solid #EFEFEF; } .dim-name { font-size: 9px; font-weight: 500; color: var(--grey); } .dim-score { font-size: 29px; font-weight: 500; color: var(--ink); } .dim-bad { color: var(--bad); } -.dims-note { font-size: 9px; font-weight: 500; color: var(--grey); line-height: 1.55; margin-top: 9px; } -.dims-disclaimer { font-size: 7px; font-weight: 400; color: var(--grey-3); margin-top: 8px; line-height: 1.5; } +.dims-note { font-size: 9px; font-weight: 500; color: var(--grey); line-height: 1.55; margin-top: 9px; text-align: center; } +.dims-disclaimer { font-size: 7px; font-weight: 400; color: var(--grey-3); margin: 0 2px 9px; line-height: 1.5; } /* 具体描述 */ .detail-tabs { display: flex; @@ -266,47 +294,60 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } .dtab.active::after { content: ""; position: absolute; left: 50%; transform: translateX(-50%); bottom: -1px; - width: 46px; height: 4px; border-radius: 2px; + width: 78px; height: 7px; border-radius: 3.5px; background: var(--yellow); } .dpanel { display: none; } .dpanel.active { display: block; animation: fade .25s ease; } @keyframes fade { from { opacity: 0; } to { opacity: 1; } } -.ditem { display: flex; gap: 11px; } +.ditem { display: flex; gap: 11px; align-items: flex-start; } .ditem + .ditem { margin-top: 13px; padding-top: 13px; border-top: 1px solid #F0F0F0; } .ditem-img { width: 92px; height: 96px; object-fit: cover; border-radius: 4px; flex-shrink: 0; } .ditem-text { flex: 1; } -.ditem-title { font-size: 11.5px; font-weight: 500; color: var(--ink); margin-bottom: 4px; } -.ditem-para { font-size: 10px; font-weight: 400; color: var(--para); line-height: 1.55; } +/* 检测条目标题:竖排,位于图左(设计稿如此) */ +.ditem-title { + writing-mode: vertical-rl; + letter-spacing: 4px; + font-size: 11.5px; font-weight: 500; color: var(--ink); + margin-right: 12px; flex-shrink: 0; +} +.ditem-para { font-size: 10px; font-weight: 400; color: var(--para); line-height: 1.45; overflow-wrap: anywhere; } .dempty { padding: 26px 0; text-align: center; font-size: 10px; color: var(--grey-2); } /* 护理建议 */ .card-heading { font-size: 13px; font-weight: 700; color: #000; margin-bottom: 8px; } -.care-item { font-size: 10px; color: var(--para); line-height: 1.6; margin-bottom: 8px; } +.care-item { font-size: 10px; color: var(--para); line-height: 1.6; margin-bottom: 8px; overflow-wrap: anywhere; } .care-summary { font-size: 11px; font-weight: 500; color: #000; margin-top: 10px; } -/* 产品推荐 */ +/* 产品推荐:白底圆角卡,左侧文案 + 右侧单图(图高撑卡) */ .prod-title { font-size: 21px; font-weight: 700; color: var(--ink); line-height: 1.45; text-align: center; margin: 4px 0 12px; } +.card-product { padding: 0; overflow: hidden; } +.prod-card { display: flex; align-items: stretch; } +.prod-info { + flex: 1; min-width: 0; + padding: 18px 12px 18px 16px; + display: flex; flex-direction: column; justify-content: center; gap: 7px; +} +.prod-badge { font-size: 8px; font-weight: 500; letter-spacing: 3px; color: #B9B9B9; } +.prod-name { font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.4; overflow-wrap: anywhere; } +.prod-sub { font-size: 7.5px; font-weight: 500; color: var(--grey-3); } .prod-scroll { - display: flex; gap: 9px; - overflow-x: auto; - margin: 0 -6px; padding: 0 6px 4px; + flex-shrink: 0; margin: 0; padding: 0; + display: flex; overflow: hidden; scrollbar-width: none; } .prod-scroll::-webkit-scrollbar { display: none; } .prod-scroll img { - width: 130px; height: 162px; - object-fit: cover; border-radius: 6px; - flex-shrink: 0; + width: 168px; height: 225px; + object-fit: cover; flex-shrink: 0; + border-radius: 0 6px 6px 0; } -.prod-name { font-size: 13px; font-weight: 700; color: var(--ink); margin: 11px 0 3px; } -.prod-sub { font-size: 7.5px; font-weight: 500; color: var(--grey-3); } .btn-more { margin: 16px auto 0; } .report-disclaimer { font-size: 7px; font-weight: 300; color: var(--grey-3); line-height: 1.7; text-align: center; - margin-top: 14px; + margin: 5px 2px 9px; /* 灰底独立文字,位于描述卡与护理建议卡之间 */ } /* ═══════════ 弹窗 ═══════════ */ @@ -314,7 +355,7 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } position: absolute; inset: 0; z-index: 50; display: none; align-items: center; justify-content: center; - background: rgba(0,0,0,.45); + background: rgba(0,0,0,.5); } .overlay.show { display: flex; } .overlay .popup { animation: popIn .3s cubic-bezier(.34,1.4,.64,1) both; } @@ -322,8 +363,8 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } .popup { position: relative; width: 307px; - background: #fff; border-radius: 14px; - padding: 34px 26px 26px; + background: #fff; border-radius: 10px; + padding: 34px 26px 33px; text-align: left; } .popup-close { @@ -338,11 +379,18 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } margin-bottom: 15px; } .popup-title-center { text-align: center; margin: 18px 0 24px; } +/* 拍照引导弹窗:近方形比例,标题垂直居中偏上,按钮贴底 */ +#p-photoguide .popup { + min-height: 312px; + display: flex; flex-direction: column; + padding: 34px 26px 52px; +} +#p-photoguide .popup-title-center { margin: 56px 0 auto; } .popup-body { font-size: 11.5px; color: var(--ink); line-height: 1.55; margin-bottom: 20px; } -.privacy-row { display: flex; align-items: center; gap: 8px; margin-bottom: 24px; cursor: pointer; } +.privacy-row { display: flex; align-items: center; gap: 8px; margin-bottom: 40px; cursor: pointer; } .checkbox { width: 11px; height: 11px; border-radius: 50%; - border: 1px solid #9B9B9B; background: #fff; + border: 1px solid #282828; background: #fff; flex-shrink: 0; position: relative; } .checkbox.checked::after { @@ -381,3 +429,11 @@ button { font-family: inherit; border: 0; background: none; cursor: pointer; } z-index: 99; white-space: nowrap; } .toast.show { opacity: 1; transform: translateX(-50%) translateY(0); } + +/* ═══════════ 第3轮上线打磨新增(以下均为新增规则,不动以上已验收样式) ═══════════ */ +/* 隐私协议链接:下划线、色值不变,点击开占位弹层 */ +.privacy-link { color: var(--grey-2); text-decoration: underline; cursor: pointer; } +.privacy-link:active { opacity: .7; } +/* 隐私协议占位弹层(轻量,复用 .overlay/.popup 骨架) */ +#p-policy .popup { padding: 30px 26px 34px; } +.popup-title-policy { font-size: 18px; margin-bottom: 12px; } diff --git a/h5/index.html b/h5/index.html index d69ca25..b641580 100644 --- a/h5/index.html +++ b/h5/index.html @@ -4,7 +4,14 @@ + + + + +
1/3
请单人正脸出镜