# App 邀请列表与商品套餐折扣需求梳理 本文基于当前 `ppanel-server` 代码现状,对以下两个需求做整理: 1. App 需要一个“邀请列表/邀请记录”接口。 2. 商品套餐需要补充“折扣信息”,当存在折扣时,App 需要做样式展示,并支持用户继续下单购买。 目标是帮助产品、前端、后端快速统一口径,明确: - 现在已有哪些接口可以复用 - 哪些地方确实需要新增 - “接口增加三个字段”更适合加在哪一层 --- ## 1. 需求结论 ### 1.1 邀请列表 当前公开侧已经有一部分邀请能力,但**没有一个完全匹配“App 邀请记录列表”语义的公开接口**。 现状: - 已有 `GET /v1/public/user/affiliate/list` - 能返回“我邀请了哪些用户” - 但字段较少,只包含基础信息 - 已有 `GET /v1/public/user/invite_sales` - 返回的是“被邀请用户的成交订单记录” - 不是“邀请用户记录列表” - 已有 `GET /v1/public/user/invite_stats` - 返回邀请统计 - 不是列表 结论: - 如果 App 只是要展示“我邀请了哪些人”,`/affiliate/list` 可以复用。 - 如果 App 需要展示“邀请时间、是否购买、购买次数、带来的佣金/赠送天数”等完整邀请记录,则**建议新增一个公开接口**。 ### 1.2 商品套餐折扣 当前公开侧套餐列表接口 `GET /v1/public/subscribe/list` **已经返回 `discount` 字段**,下单预览接口 `POST /v1/public/order/pre` 也已经支持折扣计算。 现状: - 套餐列表已有折扣规则数组 `discount` - 预下单接口已有: - 原价 `price` - 实付 `amount` - 折扣金额 `discount` - 活动优惠 `promo_discount` - 优惠券减免 `coupon_discount` - 手续费 `fee_amount` 结论: - 后端**不是完全没有折扣能力**,而是“已经有计算能力,但 App 展示层使用起来不够直接”。 - 如果需求明确要求“接口增加三个字段”,**更推荐补在套餐列表返回的 `discount[]` 子项里**,而不是直接加在下单接口里。 --- ## 2. 当前代码现状 ## 2.1 邀请相关 ### 2.1.1 已有公开接口 #### A. 邀请基础列表 接口: - `GET /v1/public/user/affiliate/list` 请求: - `page` - `size` 返回结构: - `total` - `list[]` - `identifier` - `avatar` - `registered_at` - `enable` 特点: - 能表达“我邀请了谁” - 不能表达“是否购买 / 购买次数 / 给我带来多少收益” 对应代码: - `apis/public/user.api` - `internal/logic/public/user/queryUserAffiliateListLogic.go` #### B. 邀请成交记录 接口: - `GET /v1/public/user/invite_sales` 返回结构: - `total` - `list[]` - `amount` - `updated_at` - `user_hash` - `product_name` 特点: - 更像“邀请带来的订单流水” - 不是邀请用户列表 对应代码: - `internal/logic/public/user/getInviteSalesLogic.go` #### C. 邀请统计 接口: - `GET /v1/public/user/invite_stats` 返回结构: - `friendly_count` - `history_count` 特点: - 只适合头部统计卡片 - 不适合列表页 对应代码: - `internal/logic/public/user/getUserInviteStatsLogic.go` ### 2.1.2 已有后台接口 后台已经有更完整的邀请记录能力,可以直接参考: - `GetAdminUserInviteList` - `GetInviteManageList` 这些接口已经能返回: - 邀请时间 - 是否购买 - 购买次数 - 邀请人佣金 - 邀请人赠送天数 - 被邀请人赠送天数 对应代码: - `internal/logic/admin/user/getAdminUserInviteListLogic.go` - `internal/logic/admin/invite/getInviteManageListLogic.go` 结论: - 邀请记录的统计逻辑后端已经有现成实现思路。 - 新增 App 公开接口时,建议复用这部分逻辑,不要从零再写一套。 --- ## 2.2 套餐折扣相关 ### 2.2.1 套餐列表接口已有折扣规则 接口: - `GET /v1/public/subscribe/list` 当前返回的套餐结构 `Subscribe` 中已包含: - `unit_price` - `discount []SubscribeDiscount` 其中 `SubscribeDiscount` 当前字段为: - `quantity` - `discount` - `new_user_only` - `map_apple` - `promo` 对应代码: - `apis/public/subscribe.api` - `internal/logic/public/subscribe/querySubscribeListLogic.go` - `internal/types/types.go` 说明: - `discount` 是按购买数量 `quantity` 生效的阶梯折扣 - 不是单个套餐固定只有一个折扣值 ### 2.2.2 预下单接口已有价格计算结果 接口: - `POST /v1/public/order/pre` 当前已返回: - `price`:原价 - `amount`:最终应付 - `discount`:折扣减免金额 - `promo_discount`:活动优惠金额 - `gift_amount`:礼品余额抵扣 - `coupon_discount`:优惠券减免 - `fee_amount`:手续费 对应代码: - `apis/public/order.api` - `internal/logic/public/order/preCreateOrderLogic.go` 说明: - 只要 App 知道 `subscribe_id + quantity [+ coupon] [+ payment]`,就已经能拿到准确的下单金额 - 所以“下单购买”这件事本身,后端主链路已经具备 --- ## 3. 差距分析 ## 3.1 邀请列表的真实缺口 如果产品要的是“邀请记录页”,通常至少会关心以下内容: - 被邀请用户 - 邀请时间 - 是否已购买 - 购买次数 - 给邀请人带来的佣金 - 双方赠送天数 而当前: - `/affiliate/list` 只有基础用户列表 - `/invite_sales` 是订单成交记录 - `/invite_stats` 是统计值 所以当前公开侧缺一个“**邀请关系维度的邀请记录列表**”。 ## 3.2 套餐折扣的真实缺口 后端目前的主要问题不是“不会算折扣”,而是: - `discount[]` 更偏规则定义 - App 如果只想直接展示“折后价 / 优惠金额 / 折扣标签”,还需要自己再算一层 - 这会增加前端理解成本,也容易和后端口径不一致 所以当前更合理的改法是: - 保留现有折扣规则 - 再额外补充几个**面向展示的字段** --- ## 4. 推荐方案 ## 4.1 邀请记录接口 ### 方案建议 新增一个公开接口,例如: - `GET /v1/public/user/invite_records` 说明: - 从登录态中取当前用户 ID - 不从前端传 `user_id` - 只查“当前用户邀请的记录” ### 请求参数建议 ```json { "page": 1, "size": 10 } ``` ### 返回字段建议 ```json { "total": 2, "list": [ { "invitee_id": 1001, "invitee_identifier": "138****8888", "invitee_avatar": "https://...", "invitee_enable": true, "invited_at": 1716800000, "order_count": 3, "has_purchased": true, "inviter_commission": 1200, "inviter_gift_days": 30, "invitee_gift_days": 7 } ] } ``` ### 字段说明 - `invitee_id`:被邀请用户 ID - `invitee_identifier`:被邀请用户展示账号 - `invitee_avatar`:头像 - `invitee_enable`:是否启用 - `invited_at`:邀请时间 - `order_count`:该被邀请用户产生的有效订单数 - `has_purchased`:是否已购买 - `inviter_commission`:给邀请人带来的佣金,单位建议继续沿用分 - `inviter_gift_days`:邀请人获赠天数 - `invitee_gift_days`:被邀请人获赠天数 ### 实现建议 优先复用现有后台逻辑思路: - 参考 `internal/logic/admin/user/getAdminUserInviteListLogic.go` - 或参考 `internal/logic/admin/invite/getInviteManageListLogic.go` 公开接口与后台接口的主要差异只有两点: - 公开接口不允许前端指定 `user_id` - 公开接口按当前登录用户本人维度返回 ### 是否可以不新增接口 可以,但前提是 App 接受以下拆分: - 列表页用 `/affiliate/list` - 顶部统计用 `/invite_stats` - 订单流水页用 `/invite_sales` 如果产品要的是一个完整“邀请记录页”,不建议这样拆三次请求,前端维护成本偏高。 --- ## 4.2 套餐折扣字段建议 ### 核心建议 “接口增加三个字段”建议**加在 `SubscribeDiscount` 子项里**,不要直接加在 `Subscribe` 顶层。 原因: - 折扣是按 `quantity` 生效的 - 一个套餐可能有多个折扣档位 - 如果加在套餐顶层,很难表达“买 1 个月”和“买 12 个月”对应不同折扣 ### 推荐新增字段 建议在 `SubscribeDiscount` 中增加以下三个展示字段: - `discount_price` - `discount_amount` - `discount_desc` 推荐结构如下: ```json { "quantity": 12, "discount": 80, "new_user_only": false, "map_apple": "", "promo": null, "discount_price": 9600, "discount_amount": 2400, "discount_desc": "年付8折" } ``` ### 三个字段的含义 #### 1. `discount_price` - 含义:该档位折后总价 - 计算建议:`unit_price * quantity * discount / 100` - 单位:分 作用: - App 可直接展示“折后价” - 下单时直接把该项的 `quantity` 带入 `/order/pre` 或 `/order/purchase` #### 2. `discount_amount` - 含义:该档位比原价便宜多少钱 - 计算建议:`unit_price * quantity - discount_price` - 单位:分 作用: - App 可直接展示“立省 xx” #### 3. `discount_desc` - 含义:折扣展示文案 - 示例: - `年付8折` - `季付9折` - `新用户首单8折` 作用: - App 可直接做角标、标签、促销文案展示 ### 为什么不推荐这三个字段加在下单接口 因为下单接口本来就是“结果型接口”,它已经能返回: - 原价 - 折扣金额 - 实付金额 如果只是为了 App 卡片展示,再去每个套餐都调一次 `/order/pre`,成本会比较高: - 请求次数多 - 页面首屏会更慢 - 前端链路更复杂 更合适的做法是: - 套餐列表接口负责“展示友好” - 预下单接口负责“结算准确” --- ## 5. 推荐改动清单 ## 5.1 邀请列表 建议新增: - 新接口:`GET /v1/public/user/invite_records` 建议新增类型: - `GetUserInviteRecordsRequest` - `UserInviteRecord` - `GetUserInviteRecordsResponse` 建议实现位置: - `apis/public/user.api` - `internal/types/types.go` - `internal/handler/public/user/` - `internal/logic/public/user/` ## 5.2 套餐折扣 建议调整: - `SubscribeDiscount` 增加 3 个字段: - `discount_price` - `discount_amount` - `discount_desc` 建议实现位置: - `apis/types.api` - `internal/types/types.go` - `internal/logic/public/subscribe/querySubscribeListLogic.go` --- ## 6. 前后端协作建议 ## 6.1 App 侧调用建议 邀请页建议: - 头部统计:`/v1/public/user/invite_stats` - 邀请记录列表:`/v1/public/user/invite_records` - 如果还要看成交流水:`/v1/public/user/invite_sales` 套餐页建议: - 先调 `/v1/public/subscribe/list` 渲染套餐和折扣标签 - 用户点某个折扣档位时,带 `subscribe_id + quantity` 调 `/v1/public/order/pre` - 用户确认后再调 `/v1/public/order/purchase` ## 6.2 单位口径建议 建议继续保持后端金额统一为“分”: - `unit_price` - `discount_price` - `discount_amount` - `amount` - `coupon_discount` 这样可以避免前后端出现小数精度问题。 --- ## 7. 最终建议 ### 建议一 如果你们只是要“邀请用户名单”,可直接复用: - `GET /v1/public/user/affiliate/list` ### 建议二 如果你们要的是完整“邀请记录”,建议新增: - `GET /v1/public/user/invite_records` 这是本次需求里更合理的新增接口。 ### 建议三 商品套餐“折扣信息”不建议重新设计一整套下单逻辑。 当前后端已经具备: - 套餐折扣规则 - 预下单价格计算 - 正式下单购买 更推荐做法是: - 在 `SubscribeDiscount` 里补 3 个展示字段: - `discount_price` - `discount_amount` - `discount_desc` 这样改动最小,也最贴近 App 展示场景。 --- ## 8. 相关代码位置 - `internal/logic/public/user/queryUserAffiliateListLogic.go` - `internal/logic/public/user/getInviteSalesLogic.go` - `internal/logic/public/user/getUserInviteStatsLogic.go` - `internal/logic/admin/user/getAdminUserInviteListLogic.go` - `internal/logic/admin/invite/getInviteManageListLogic.go` - `internal/logic/public/subscribe/querySubscribeListLogic.go` - `internal/logic/public/order/preCreateOrderLogic.go` - `internal/logic/public/order/purchaseLogic.go` - `internal/types/types.go` - `apis/public/user.api` - `apis/public/subscribe.api` - `apis/public/order.api`