git-subtree-dir: app git-subtree-mainline:6ebd902c6bgit-subtree-split:a11a668869
10 KiB
10 KiB
slogan-app 客户端设计方案
日期:2026-07-31 关联:slogan-agent 服务端方案(Go + GoFrame)见 slogan-agent 仓库对应文档
1. 项目概述
slogan 是一个"人形象设计"应用:用户上传大头照和全身多角度照片、维护个人服装资产(衣橱),指定日期范围和地点后一键生成最适合的穿搭方案(含发型、发色、服装穿搭),方案以 3D 化身 + 2D 效果图双形态呈现,手指滑动切换方案与查看角度。
本仓库为客户端(slogan-app),Flutter 实现,一次编写双端(iOS/Android)运行,追求类原生用户操作体验。
2. 技术选型
| 决策点 | 选择 | 理由 |
|---|---|---|
| 语言/框架 | Flutter (Dart) | 一次编写双端;自绘引擎保证体验一致;动画/手势流畅 |
| 状态管理 | Riverpod | 类型安全、可测试,适合表单/异步任务/缓存类状态 |
| 网络层 | Dio + 拦截器 | JWT 自动注入、统一响应解析 {code,message,data}、超时重试 |
| 3D 渲染 | three_dart v1 + 渲染抽象层 | 稳定发布版(v0.3.0,GLTF/GLB loader,纯 Dart 双端);flutter_scene 进 stable 后经抽象层无缝替换 |
| 图片缓存 | cached_network_image | 效果图/服装照片懒加载缓存 |
| 拍照/相册 | camera + image_picker | 大头照/全身多角度拍摄引导 |
| 本地存储 | shared_preferences | token/偏好;身形微调参数本地实时生效 |
| 手势 | 原生 GestureDetector 组合 | 方案横滑切换(PageView)+ 化身旋转拖拽/捏合缩放 + 惯性滚动 |
3D 渲染层风险控制:AvatarViewer 接口抽象(loadGLB / setHairstyle / setHairColor / rotate / zoom / switchOutfit),v1 实现为 three_dart;flutter_scene(官方,基于 Flutter GPU)进入 stable 后提供第二实现,业务代码零改动。
3. 项目结构
slogan-app/
├── lib/
│ ├── main.dart # 入口 + 路由 + 主题
│ ├── core/
│ │ ├── network/ # Dio 封装:JWT 拦截器/统一响应/错误码映射
│ │ ├── auth/ # 登录页 + token 管理(账号密码,复用服务端 /user/login)
│ │ ├── config/ # API 地址/环境
│ │ ├── storage/ # shared_preferences 封装(token/偏好)
│ │ └── router/ # go_router(未登录 → 登录页)
│ ├── features/
│ │ ├── profile/ # Tab1 我的形象
│ │ │ ├── photo_guide/ # 拍照引导页(大头照/全身多角度拍摄指引)
│ │ │ ├── avatar_viewer/ # 3D 化身查看(AvatarViewer 抽象层实现)
│ │ │ └── body_tune/ # 滑杆微调(身高/胖瘦/肤色,本地实时)
│ │ ├── wardrobe/ # Tab2 我的衣橱
│ │ │ ├── upload/ # 服装照片上传 + 分类标签
│ │ │ └── item_grid/ # 服装资产网格/详情
│ │ ├── outfit/ # Tab3 穿搭方案
│ │ │ ├── generate/ # 生成入口(日期范围选择器/地点选择)
│ │ │ ├── task_status/ # 生成任务进度(轮询)
│ │ │ ├── plan_flow/ # 方案流(PageView 横滑切换方案)
│ │ │ ├── viewer_3d/ # 3D 方案查看(发型切换/发色取色/旋转/捏合)
│ │ │ ├── effect_images/ # 2D 效果图(正面/侧面/背面切换)
│ │ │ └── review/ # 收藏/反馈
│ │ └── commercial/ # Tab4 门店/电商
│ │ ├── stores/ # LBS 附近门店(形象设计/服装)
│ │ ├── leads/ # 导流订单/到店核销
│ │ ├── products/ # CPS 商品跳转
│ │ └── subscription/ # 会员订阅
│ └── shared/ # 组件/主题/工具(日期选择器/评分展示等)
├── assets/
│ ├── avatars/ # 模板/发型 GLB 缓存(与后端 assets 对应,v1 从服务端拉取)
│ └── images/ # 图标/占位图
└── test/ # 单元/widget 测试
4. 页面与交互设计(4 Tab 主框架)
┌─────────────────────────────────────────┐
│ Tab 架构(底部导航,类原生体验) │
│ ┌────────┬────────┬────────┬─────────┐ │
│ │ 我的形象│ 我的衣橱│ 穿搭方案 │ 门店/电商│ │
│ └────────┴────────┴────────┴─────────┘ │
└─────────────────────────────────────────┘
Tab1 我的形象
- 首次进入:拍照引导流程(大头照 + 全身正面/侧面/背面 4 张,含姿势示例图)
- 化身构建进度(后端任务轮询)
- 3D 化身查看:单指拖拽旋转、双指捏合缩放
- 滑杆微调:身高/胖瘦/肤色,调参即时反映(本地计算,GLB 缩放参数 + 肤色材质)
Tab2 我的衣橱
- 服装照片上传(多选)+ 分类(上衣/下装/鞋/配饰)+ 季节/风格标签自动识别(后端 AI 辅助,本地可手改)
- 网格展示 + 详情编辑/删除
Tab3 穿搭方案(核心)
- 生成入口:日期范围选择器 + 地点选择(定位/搜索)
- 生成任务进度页(规则规划 → 方案评分 → 完成)
- 方案流:PageView 左右滑动切换 3 套方案;每套方案卡片 = 3D 化身 + 方案摘要(评分/来源标签:衣橱组合/AI 推荐)
- 3D 查看:发型点击切换 + 发色取色盘(HSV 调色实时渲染)+ 拖拽旋转 + 捏合缩放
- 主方案选定 → 触发 2D 效果图生成(3 视角:正面/侧面/背面,切换查看)
- 方案条目明细:每件服装(衣橱照片 或 电商商品图)+ 单品操作(跳转商品/加入衣橱)
- 收藏/反馈 → 回流 Agent 优化下次生成
Tab4 门店/电商
- LBS 附近合作门店(类型筛选:形象设计/服装),导航/预约/到店核销
- CPS 商品推荐列表(跳转电商)
- 会员订阅入口与权益展示
5. 3D 查看器设计(核心模块)
AvatarViewer 抽象接口
abstract class AvatarViewer extends StatelessWidget {
// 由具体实现提供(three_dart v1 / flutter_scene v2)
}
abstract class AvatarViewerController {
Future<void> loadAvatar(AvatarSpec spec); // 头像 + 体型 + 皮肤贴图
Future<void> loadHairstyle(String glbUrl); // 加载发型
void setHairColor(Color color); // 发色(PBR baseColor 调色)
void setOutfit(List<OutfitLayer> layers); // 换装(简模 GLB 层)
void rotateBy(double dx, double dy); // 旋转
void zoomBy(double scale); // 缩放
void resetView();
}
- v1 实现(three_dart):加载服务端
avatar_model.glb(头部/身体/发型分离分层),发型切换 = 换层 + 发色材质 HSV 调整 - 性能:GLB 经服务端 glTF-Transform 压缩;发型资产首次加载后本地缓存;页面级预取下一套方案
- 降级:GLB 加载失败 → 显示用户大头照 + 方案文本卡片(核心功能不受 3D 影响)
手势实现
- 方案切换:
PageView(水平滑动 + 惯性 + 阻尼边缘效果) - 化身旋转:
GestureDetector.onPanUpdate→ controller.rotateBy,松手无惯性(或轻量衰减) - 缩放:
ScaleGestureRecognizer双指捏合,1.0-4.0 范围限制 - 发色:
HSVColorPicker自定义取色盘,onChanged 实时 setHairColor
6. 网络层与状态管理
ApiClient(Dio):baseUrl 可配置、token 注入、code==0判定、401 自动登出、超时 30s- 任务轮询:
outfit/task/status每 3s 轮询(RiverpodStreamProvider),任务完成自动停止 - 上传:Multipart,进度条反馈
- 缓存:效果图/服装照片 cached_network_image;化身 GLB 本地文件缓存(LRU,256MB 上限)
7. 拍摄引导设计
- 大头照:正面、面部无遮挡、光线均匀说明图;相机取景框对齐提示
- 全身照:距镜 2-3 米、全身入框、正面/侧面/背面 三角度示例图(类原生"手势引导"UI)
- 照片本地压缩(宽边 ≤ 2048)后上传
8. 错误处理与加载状态
- 统一
ErrorView/LoadingView组件(骨架屏) - 生成任务失败:明确错误文案("衣橱为空,请先添加服装"等)+ 重试按钮
- 网络离线:离线提示 + 本地缓存优先展示(方案历史本地快照)
- 轮询超时(>10 分钟):提示"生成时间较长"并提供结果通知路径(v2 推送)
9. 测试策略
- 单元测试:手势计算/发色 HSV 调色/方案缓存 key 逻辑
- Widget 测试:方案流滑动切换、3D 查看器骨架降级、拍照引导流程
- 集成(v1 手工 + 冒烟脚本):登录 → 上传 → 生成 → 查看全链路
- 渲染层测试:AvatarViewer 接口 mock,业务测试不依赖具体 3D 实现
10. 与后端 API 对接清单
见 slogan-agent 方案第 11 节 API 路由表。App 端关键时序:
登录 → 上传照片(4张) → 填写身形 → [build 化身(异步)] → 上传衣橱服装
→ 生成穿搭 {日期范围, 地点} → 轮询任务 → 方案流(3D 即时查看)
→ 选主方案 → 效果图生成(异步) → 3 视角查看 → 收藏/跳转商品/门店预约
11. 开发规范约束(App 端)
- 状态管理统一 Riverpod,禁止 setState 在页面间传递业务状态
- 所有网络请求必须走
ApiClient,禁止散落 Dio 实例 - 3D 渲染只允许通过
AvatarViewer抽象层,禁止业务代码直接依赖 three_dart 类型 - 命名:目录
features/<domain>/,组件shared/;文件 snake_case,类 PascalCase - 测试随功能同步编写(TDD:先写失败测试再实现)