商业化四支柱设计(客户端)· slogan-app
目标: 以「个人形象设计」为主流程,把四支柱收入入口从「方案/单品」里长出来:VIP 会员充值、穿山甲广告激励、线下门店引流(美团联盟)、线上商品(京东/淘宝 CPS)。不做泛化场景广场。
核心原则: 客户端零硬编码业务配置;所有商业化入口以「接口可用」为开关 —— 后端未配置 key 时接口报错/返回空 → App 自动隐藏对应入口,主流程(生成方案 → 查看)不受影响。
1. 信息架构改造
开关原则:每个商业化入口包一层 commercialGate(统一查询后端配置/捕获接口错误),未开通 → 按钮不渲染。启动时不做额外网络调用,入口可见性由首次打开该页面的接口结果决定(零新增请求)。
2. 支柱 A:会员中心(/commercial 重构)
2.1 页面结构
2.2 支付时序(App 侧)
- 支付页依赖
webview_flutter(P0 引入,国内 App 常规做法);若平台编译受限,降级方案:url_launcher 唤起系统浏览器支付,返回 App 后仍走轮询(P0 默认 url_launcher 方案,webview_flutter 留 P1,减小依赖风险)
2.3 状态与 Provider
| Provider |
类型 |
数据 |
接口 |
memberProvider |
AsyncNotifier |
isVip, expireAt, planName, benefits[] |
GET /member/status |
memberPlanProvider |
FutureProvider |
套餐列表 |
GET /member/plan/list |
orderCreateProvider |
Notifier.family(planId) |
orderNo, payUrl |
POST /member/order/create |
orderStatusProvider |
FutureProvider.family(orderNo) |
status |
GET /member/order/status |
memberProvider 缓存登录态期间;refresh() 在支付成功、广告领奖后调用
- 权益 chips 文案从套餐
features JSON 解析 → 本地文案 map(effect_unlimited→无限效果图 等)
3. 支柱 B:广告激励(lib/core/ads/ 新建)
3.1 抽象(供应商隔离)
- 初始化:
AdsConfig(AppConfig 常量:pangleAppId 默认空)→ adsServiceProvider 单例
- 降级:appid 空 / SDK 初始化失败 →
enabled=false → 会员中心激励卡、广告位全部不渲染
3.2 激励流程(服务端防刷,客户端只展示)
- 剩余次数展示:
/ad/reward/claim 响应带回 {reward: {ad_type, remaining_today}},App 本地缓存当日显示;或 P0 简单化 —— 仅在领取失败时提示次数用完
- 效果图配额联动:后端限额 = 基础 3 + 当日额外次数;App 端文案统一显示「今日剩余 X 次」(P1 后端在生成接口响应中带
remaining 字段,P0 保持现状提示)
3.3 广告位(P2,本期只留占位)
- 开屏广告:
/home 进入时加载(P2)
- 信息流广告:
/plan-effect 效果图 GridView 底部插一条(P2)
4. 支柱 C/D:方案驱动 CPS 入口
4.1 方案页(/plan-viewer)三处入口
| 位置 |
按钮 |
scene |
请求 |
跳转 |
| 发型卡尾部 |
「做同款发型」 |
haircut |
GET /cps/plan/recommend {plan_id, scene: haircut} |
/cps-product-list(美团丽人/理发券) |
| 穿衣清单每项 trailing |
「买同款」 |
item_buy |
京东搜索单品名 |
/cps-product-list(电商商品) |
| 穿衣清单每项 trailing |
「到店试穿」 |
item_upgrade |
美团服装类目 |
/cps-product-list(门店券) |
| 场合卡(P1,detail 有 occasion 字段后) |
「延伸优惠」 |
occasion |
映射表推荐 |
/cps-product-list |
- 可见性:推荐接口返回空列表 / 接口报错(CPS 未开通)→ 该按钮隐藏;发型卡无发型名(默认发型)→ 隐藏「做同款」
- 交互:推荐返回列表 → push
/cps-product-list?source=&category_code=&city=(带标题「做同款发型 · 丽人」);列表点击 → POST /cps/product/link {product_id, scene, plan_id} → 打开 deeplink
- 打开方式:
url_launcher(系统浏览器,携 pid 转链 URL;电商商品优先深链 App,P1 增强)
4.2 衣橱升级款(/wardrobe 长按菜单加一项)
4.3 商品列表页 /cps-product-list
4.4 Provider
| Provider |
类型 |
接口 |
cpsRecommendProvider |
FutureProvider.family((planId, scene)) |
GET /cps/plan/recommend |
cpsProductProvider |
AsyncNotifierProvider.family((source, categoryCode, city)) |
GET /cps/product/list 分页 |
cpsUpgradeProvider |
FutureProvider.family(itemId) |
GET /cps/wardrobe/upgrade |
cpsLinkAction |
Notifier |
POST /cps/product/link |
5. 会员权益在客户端的呈现
| 权益 |
客户端表现 |
| effect_unlimited |
效果图页配额提示隐藏(「每日限 3 次」文案在 isVip 时不显示) |
| ai_priority |
生成页状态文案「VIP 优先排队」(MVP 仅文案) |
| cps_commission_x15 |
商品卡佣金标签「返现加成 1.5x」(VIP 用户) |
| store_discount |
门店列表「会员价」角标 + 会员码页(P1) |
6. 配置(AppConfig 常量,均为本地编译期配置)
- 商业化开关最终以接口为准(后端 config 未配置 → 接口错误 → App 隐藏入口),本地常量只控制「广告 SDK 是否初始化」
7. API 映射与错误处理
| 后端接口 |
客户端方法 |
错误处理 |
| GET /member/status |
memberProvider.build |
401 → 重登;其他 → 默认非会员 |
| GET /member/plan/list |
memberPlanProvider |
错误 → 套餐区显示「暂未开通」 |
| POST /member/order/create |
下单动作 |
错误 → toast「支付未开通」 |
| GET /member/order/status |
轮询 |
404/错误 → 结束轮询提示稍后查看 |
| POST /member/order/notify |
-(后端回调,客户端不参与) |
- |
| POST /ad/reward/claim |
领奖动作 |
错误 → toast 后端 message(限频等) |
| GET /cps/plan/recommend |
cpsRecommendProvider |
空/错误 → 入口隐藏 |
| GET /cps/product/list |
cpsProductProvider |
空/错误 → 列表空态「暂未开放」 |
| POST /cps/product/link |
cpsLinkAction |
错误 → toast「跳转失败」 |
| GET /cps/my/recent |
recentProvider |
错误 → 整卡隐藏 |
- 所有新接口走现有
apiClientProvider(Dio 封装,自动带 token),无需改动网络层
8. 路由与依赖变更
- 穿山甲 SDK Flutter 插件社区维护不稳定 → P1 先验证 iOS/Android 编译,若插件不可用则改为原生 module 接入(P2);P0 用 MockAdsService 保证业务链路先闭环
9. 分期与对齐
| 分期 |
客户端内容 |
依赖 |
| P0 |
/commercial 重构会员中心(状态/套餐/下单/轮询)+ MockAds + 广告激励入口 + 方案页「做同款发型/买同款/到店试穿」+ /cps-product-list + url_launcher + cps 入口隐藏逻辑 |
后端 P0(会员+广告接口) |
| P1 |
场合卡「延伸优惠」+ 衣橱「找升级款」+ 最近优惠 + 会员码/门店折扣角标 + webview_flutter 内嵌收银台 + 穿山甲 SDK 接入(替换 Mock) |
后端 P1(CPS 引擎) |
| P2 |
开屏/信息流广告位 + 穿山甲插件不可用时的原生 module 兜底 + 收益/返现展示 |
后端 P2 |
10. 合规(客户端侧)
- iOS 充值:App Store 虚拟商品政策风险 → iOS 端隐藏会员套餐充值入口(
Platform.isIOS 判断),保留广告激励 + 门店引流;「会员价」到店核销不受影响
- 广告:隐私政策文案补充穿山甲 SDK 信息收集披露;提供「个性化广告关闭」设置项(穿山甲 SDK 提供,P1)
- 跳转:CPS 转链一律走联盟 deeplink,不在 App 内二次改链
11. 开发规范约束(沿用 slogan-app 现有规范)
- Riverpod 3:AsyncNotifier/Notifier/FutureProvider.family;provider 文件放
lib/features/<feature>/<feature>_provider.dart
- 新页面组件放
lib/features/commercial/(会员中心)、lib/features/cps/(商品列表);广告抽象放 lib/core/ads/
- 图片 URL 一律
AppConfig.resolveUrl();价格字段分 → 元转换写死规则((fen / 100).toStringAsFixed(0))
- 所有「隐藏入口」逻辑集中在入口组件内一行判定,不扩散到业务逻辑
- 新页面必配 empty/error/loading 三态(复用 shared/widgets)