|
|
@@ -0,0 +1,373 @@
|
|
|
+# 家庭推广体系重构设计文档
|
|
|
+
|
|
|
+## 概述
|
|
|
+
|
|
|
+将现有个人级推广/佣金体系重构为家庭级体系,所有二维码改为微信小程序码(wxacode),推广收益归入家庭公共账户,重新设计推广中心前端页面。
|
|
|
+
|
|
|
+## 1. 二维码体系
|
|
|
+
|
|
|
+### 1.1 全部改用 wxacode
|
|
|
+
|
|
|
+所有二维码强制使用 `WechatService.generateWxacode()`,移除 ZXing 兜底。改造现有点:
|
|
|
+
|
|
|
+| 端点 | 原有方式 | 改造后 |
|
|
|
+|------|---------|--------|
|
|
|
+| `POST /api/common/qrcode` | ZXing 普通二维码 | wxacode,新注册使用 |
|
|
|
+| `POST /api/invite/qrcode` | wxacode + ZXing 降级 | 仅 wxacode,移除降级 |
|
|
|
+| `POST /api/family/invite/generate` | wxacode + ZXing 降级 | 仅 wxacode,移除降级 |
|
|
|
+
|
|
|
+### 1.2 两种二维码类型
|
|
|
+
|
|
|
+**类型A:注册推广码**
|
|
|
+
|
|
|
+| 字段 | 值 |
|
|
|
+|------|-----|
|
|
|
+| scene | `ref={referralCode}` (referralCode = 6位字母数字) |
|
|
|
+| page | `pages/invite/join` |
|
|
|
+| 生成端点 | `POST /api/common/qrcode` → 入参 `{ type: "register", referralCode: "xxx" }` |
|
|
|
+| 说明 | 废弃旧版 `{ content }` 入参,改 type 区分场景;wxacode 失败时返回错误信息(用户可重试),不再降级为 ZXing 普通码 |
|
|
|
+
|
|
|
+扫码流程:
|
|
|
+```
|
|
|
+用户扫码 → 打开小程序 → App.vue handleScene()
|
|
|
+ → 解析 scene 中的 ref=xxx → navigateTo /pages/invite/join?refCode=xxx
|
|
|
+ → 新用户注册时将 refCode 转为 referrerId 写入 user.referrerId
|
|
|
+ → 结算时 referrerId → familyId → 归属到家庭公共账户
|
|
|
+```
|
|
|
+
|
|
|
+**类型B:家庭邀请码**
|
|
|
+
|
|
|
+| 字段 | 值 |
|
|
|
+|------|-----|
|
|
|
+| scene | `invite={token}` (token = UUID,已有) |
|
|
|
+| page | `pages/invite/join` |
|
|
|
+| 生成端点 | `POST /api/family/invite/generate`(已有,不变) |
|
|
|
+
|
|
|
+扫码流程(已有,不变):
|
|
|
+```
|
|
|
+用户扫码 → 打开小程序 → App.vue handleScene()
|
|
|
+ → 解析 scene 中的 invite=token → navigateTo /pages/invite/join?token=xxx
|
|
|
+ → 验证 token → 加入家庭
|
|
|
+```
|
|
|
+
|
|
|
+### 1.3 修复 env_version 硬编码
|
|
|
+
|
|
|
+### 1.4 wxacode 失败处理
|
|
|
+
|
|
|
+移除 ZXing 降级后,wxacode 生成失败的策略:
|
|
|
+
|
|
|
+| 失败原因 | 处理方式 |
|
|
|
+|----------|---------|
|
|
|
+| access_token 过期 | 自动重试一次(重新获取 token) |
|
|
|
+| 频率超限(45009) | 返回错误码提示用户稍后重试,不降级 |
|
|
|
+| 其他 API 错误 | 记录日志,返回错误信息 |
|
|
|
+| 微信 API 不可达 | 返回错误,提示用户稍后再试 |
|
|
|
+
|
|
|
+前端收到错误后显示「生成二维码失败,请稍后重试」,不自动降级。
|
|
|
+
|
|
|
+### 1.5 修复 env_version 硬编码
|
|
|
+
|
|
|
+```java
|
|
|
+@Value("${wechat.env-version:release}")
|
|
|
+private String envVersion;
|
|
|
+```
|
|
|
+
|
|
|
+各环境配置:
|
|
|
+| 环境 | 值 |
|
|
|
+|------|-----|
|
|
|
+| dev | `development` |
|
|
|
+| test | `trial` |
|
|
|
+| prod | `release` |
|
|
|
+
|
|
|
+## 2. 推广体系重构
|
|
|
+
|
|
|
+### 2.1 核心变更:个人 → 家庭
|
|
|
+
|
|
|
+现有体系(个人级):
|
|
|
+```
|
|
|
+用户 referralCode → 推荐新用户 → 佣金记到 user 个人
|
|
|
+```
|
|
|
+
|
|
|
+新体系(家庭级):
|
|
|
+```
|
|
|
+用户 referralCode → 推荐新用户 → 佣金记到 family 公共账户
|
|
|
+ ↓
|
|
|
+ 个人贡献记录保留(用于展示谁推荐了多少)
|
|
|
+```
|
|
|
+
|
|
|
+### 2.2 数据模型
|
|
|
+
|
|
|
+#### 新增表:`family_earnings`(家庭公共账户总账)
|
|
|
+
|
|
|
+```sql
|
|
|
+CREATE TABLE family_earnings (
|
|
|
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
|
+ family_id BIGINT NOT NULL UNIQUE COMMENT '家庭ID',
|
|
|
+ total_earned BIGINT NOT NULL DEFAULT 0 COMMENT '累计推荐收入(分)',
|
|
|
+ available_amount BIGINT NOT NULL DEFAULT 0 COMMENT '当前可支配余额(分)',
|
|
|
+ withdrawn_amount BIGINT NOT NULL DEFAULT 0 COMMENT '已提现金额(分)',
|
|
|
+ distributed_amount BIGINT NOT NULL DEFAULT 0 COMMENT '已颁发给成员的金额(分)',
|
|
|
+ updated_at DATETIME,
|
|
|
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
|
+ INDEX idx_family_id (family_id)
|
|
|
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭公共账户';
|
|
|
+```
|
|
|
+
|
|
|
+#### 新增表:`family_earnings_member`(成员已获分配余额)
|
|
|
+
|
|
|
+```sql
|
|
|
+CREATE TABLE family_earnings_member (
|
|
|
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
|
+ family_id BIGINT NOT NULL,
|
|
|
+ user_id BIGINT NOT NULL,
|
|
|
+ allocated_amount BIGINT NOT NULL DEFAULT 0 COMMENT '管理员累计分配(分)',
|
|
|
+ consumed_amount BIGINT NOT NULL DEFAULT 0 COMMENT '已消费金额(分)',
|
|
|
+ available_amount BIGINT NOT NULL DEFAULT 0 COMMENT '可消费余额 = allocated - consumed(分)',
|
|
|
+ can_use_family_balance TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否允许使用家庭公共池',
|
|
|
+ updated_at DATETIME,
|
|
|
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
|
+ UNIQUE INDEX idx_family_user (family_id, user_id)
|
|
|
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭成员已分配余额';
|
|
|
+```
|
|
|
+
|
|
|
+#### 新增表:`family_earnings_record`(收支流水)
|
|
|
+
|
|
|
+```sql
|
|
|
+CREATE TABLE family_earnings_record (
|
|
|
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
|
+ family_id BIGINT NOT NULL,
|
|
|
+ type VARCHAR(20) NOT NULL COMMENT 'earn收入/withdraw提现/distribute颁发/consume消费',
|
|
|
+ amount BIGINT NOT NULL COMMENT '金额(分)',
|
|
|
+ from_user_id BIGINT COMMENT '操作人',
|
|
|
+ to_user_id BIGINT COMMENT '受益人(颁发/消费时填写)',
|
|
|
+ note VARCHAR(255) COMMENT '备注',
|
|
|
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
|
+ INDEX idx_family_id (family_id),
|
|
|
+ INDEX idx_type (type)
|
|
|
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭收益收支流水';
|
|
|
+```
|
|
|
+
|
|
|
+#### 修改表:`commission_records` 加列
|
|
|
+
|
|
|
+```sql
|
|
|
+ALTER TABLE commission_records ADD COLUMN family_id BIGINT COMMENT '归属家庭ID';
|
|
|
+```
|
|
|
+
|
|
|
+### 2.3 收益流转
|
|
|
+
|
|
|
+```
|
|
|
+成员推荐新用户 → 新人消费产生订单
|
|
|
+ ↓
|
|
|
+ CommissionService.settle()
|
|
|
+ ├── 写 commission_records(个人级别,+family_id)
|
|
|
+ ├── family_earnings.total_earned += 佣金
|
|
|
+ ├── family_earnings.available_amount += 佣金
|
|
|
+ └── family_earnings_record (type=earn)
|
|
|
+```
|
|
|
+
|
|
|
+### 2.4 交互流程
|
|
|
+
|
|
|
+#### 管理员提现
|
|
|
+
|
|
|
+```
|
|
|
+管理员发起提现(¥100起)
|
|
|
+ → 扣 family_earnings.available_amount
|
|
|
+ → 写 family_earnings_record (type=withdraw)
|
|
|
+ → 写 withdrawal_requests(新增 family_withdraw 类型,关联 family_id)
|
|
|
+ → 平台管理员审核 → 打款到管理员支付宝
|
|
|
+```
|
|
|
+
|
|
|
+#### 管理员颁发给成员
|
|
|
+
|
|
|
+```
|
|
|
+管理员选择成员 + 输入金额
|
|
|
+ → 扣 family_earnings.available_amount
|
|
|
+ → 加 family_earnings_member.allocated_amount
|
|
|
+ → 重算 family_earnings_member.available_amount
|
|
|
+ → 写 family_earnings_record (type=distribute)
|
|
|
+```
|
|
|
+
|
|
|
+#### 管理员开关"允许使用家庭余额"
|
|
|
+
|
|
|
+```
|
|
|
+管理员切换某成员的 can_use_family_balance 开关
|
|
|
+ → UPDATE family_earnings_member SET can_use_family_balance = ?
|
|
|
+```
|
|
|
+
|
|
|
+#### 成员消费(购物支付)
|
|
|
+
|
|
|
+```
|
|
|
+成员下单结算时,支付选项含「家庭余额」
|
|
|
+选择家庭余额 → 按以下顺序扣款:
|
|
|
+
|
|
|
+ ① family_earnings_member.available_amount(个人分配额度)
|
|
|
+ ↓ 不够才进下一步
|
|
|
+ ② 如果 can_use_family_balance=true 且 family_earnings.available_amount > 0
|
|
|
+ 从 family_earnings.available_amount 扣差额
|
|
|
+ ↓ 还不够
|
|
|
+ ③ 微信支付补差
|
|
|
+
|
|
|
+ 扣款成功后:
|
|
|
+ - 写 family_earnings_record (type=consume)
|
|
|
+ - 更新 family_earnings_member.consumed_amount
|
|
|
+ - 如果用了公共池,更新 family_earnings.available_amount
|
|
|
+```
|
|
|
+
|
|
|
+## 3. 推广中心前端重构
|
|
|
+
|
|
|
+### 3.1 页面结构
|
|
|
+
|
|
|
+```
|
|
|
+推广中心(pages/promotion/index.vue)
|
|
|
+├── 头部:家庭总数据卡片
|
|
|
+│ ├── 累计推荐人数
|
|
|
+│ ├── 家庭总收益(元)
|
|
|
+│ └── 可支配余额(元)
|
|
|
+│
|
|
|
+├── 成员贡献榜
|
|
|
+│ ├── 列表:头像 + 昵称 + 推荐人数 + 角色标签
|
|
|
+│ └── 当前用户高亮
|
|
|
+│
|
|
|
+├── 管理员专属面板(仅 isFamilyAdmin 可见)
|
|
|
+│ ├── 提现按钮 → 弹窗输入金额
|
|
|
+│ ├── 颁发给成员 → 选择成员 + 输入金额
|
|
|
+│ └── 成员权限管理 → 开关 can_use_family_balance
|
|
|
+│
|
|
|
+├── 操作区
|
|
|
+│ ├── 生成推广二维码(wxacode)
|
|
|
+│ ├── 分享海报
|
|
|
+│ └── 复制邀请码
|
|
|
+│
|
|
|
+├── Tab 导航
|
|
|
+│ ├── 推广明细 → 现有 commission.vue 改为显示家庭级
|
|
|
+│ ├── 我的团队 → 现有 team.vue 适配家庭模式
|
|
|
+│ └── 排行榜 → 现有 leaderboard.vue
|
|
|
+│
|
|
|
+└── 提现入口 → 现有 withdraw.vue 增加家庭余额提现
|
|
|
+```
|
|
|
+
|
|
|
+### 3.2 孩子角色可见
|
|
|
+
|
|
|
+- 孩子可访问推广中心(当前只有 parent/teacher 能看到)
|
|
|
+- 孩子可查看自己的贡献(推荐人数)
|
|
|
+- 孩子可看到家庭总数据(只读)
|
|
|
+- 孩子可生成自己的推广二维码
|
|
|
+- 孩子不可见管理员操作面板
|
|
|
+
|
|
|
+## 4. 后端 API 变化
|
|
|
+
|
|
|
+### 4.1 新增 API
|
|
|
+
|
|
|
+| 方法 | 端点 | 说明 |
|
|
|
+|------|------|------|
|
|
|
+| POST | `/api/earnings/family/summary` | 家庭收益总览(总推荐数、总收益、可用余额) |
|
|
|
+| POST | `/api/earnings/family/members` | 各成员贡献列表(推荐人数 + 分配余额) |
|
|
|
+| POST | `/api/earnings/family/records` | 家庭收益流水 |
|
|
|
+| POST | `/api/earnings/admin/distribute` | 管理员颁发给成员 |
|
|
|
+| POST | `/api/earnings/admin/toggle-member` | 开关成员的家庭余额权限 |
|
|
|
+| POST | `/api/earnings/admin/withdraw` | 管理员提现(走现有 withdrawal_requests) |
|
|
|
+
|
|
|
+### 4.2 改造 API
|
|
|
+
|
|
|
+| 端点 | 改动 |
|
|
|
+|------|------|
|
|
|
+| `POST /api/common/qrcode` | 改为 wxacode,新增 `type=register` 支持 |
|
|
|
+| `POST /api/invite/summary` | 返回家庭总推荐数 + 个人贡献 |
|
|
|
+| `POST /api/commission/summary` | 返回家庭级统计数据 |
|
|
|
+| `POST /api/family/invite/generate` | 移除 ZXing 降级,仅用 wxacode |
|
|
|
+
|
|
|
+### 4.3 各订单服务结算改造
|
|
|
+
|
|
|
+6 个调用 `settle()` 的服务需同步改造:
|
|
|
+
|
|
|
+| 服务 | 改动 |
|
|
|
+|------|------|
|
|
|
+| `AssessmentOrderService` | 结算时取买家 familyId 写入 commission_records 并更新 family_earnings |
|
|
|
+| `PaymentService` | 同上 |
|
|
|
+| `PackagePaymentService` | 同上 |
|
|
|
+| `ProductOrderService` | 同上 |
|
|
|
+| `MemberSubscriptionService` | 同上 |
|
|
|
+| `MembershipService` | 同上 |
|
|
|
+
|
|
|
+## 5. 注册场景处理
|
|
|
+
|
|
|
+### 5.1 新用户通过推广码注册
|
|
|
+
|
|
|
+```
|
|
|
+pages/invite/join?refCode=xxx 打开
|
|
|
+ → 注册页显示推荐人信息(昵称 + 家庭名)
|
|
|
+ → 用户完成注册(微信登录 + 授权)
|
|
|
+ → 后端:
|
|
|
+ 1. 通过 referralCode 查 user
|
|
|
+ 2. 取 user.familyId
|
|
|
+ 3. 新用户写入 user.referrerId = 推荐人ID
|
|
|
+ 4. 更新推荐人的 directCount
|
|
|
+ 5. 家庭公共账户绑定关系建立
|
|
|
+ → 新用户创建自己的家庭(或加入已有家庭)
|
|
|
+```
|
|
|
+
|
|
|
+### 5.2 App.vue scene 解析
|
|
|
+
|
|
|
+```javascript
|
|
|
+handleScene(options) {
|
|
|
+ if (!options || !options.query) return
|
|
|
+ var scene = decodeURIComponent(options.query.scene || '')
|
|
|
+ if (scene.indexOf('ref=') === 0) {
|
|
|
+ var refCode = scene.substring(3)
|
|
|
+ uni.navigateTo({ url: '/pages/invite/join?refCode=' + refCode })
|
|
|
+ } else if (scene.indexOf('invite=') === 0) {
|
|
|
+ var token = scene.substring(7)
|
|
|
+ uni.navigateTo({ url: '/pages/invite/join?token=' + token })
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+## 6. 前端 API 新增
|
|
|
+
|
|
|
+```javascript
|
|
|
+// api.js 新增
|
|
|
+export const getFamilyEarningsSummary = () =>
|
|
|
+ request('/api/earnings/family/summary', 'POST')
|
|
|
+
|
|
|
+export const getFamilyEarningsMembers = () =>
|
|
|
+ request('/api/earnings/family/members', 'POST')
|
|
|
+
|
|
|
+export const getFamilyEarningsRecords = (params) =>
|
|
|
+ request('/api/earnings/family/records', 'POST', params)
|
|
|
+
|
|
|
+export const distributeToMember = (userId, amount) =>
|
|
|
+ request('/api/earnings/admin/distribute', 'POST', { userId, amount })
|
|
|
+
|
|
|
+export const toggleMemberBalance = (userId, enabled) =>
|
|
|
+ request('/api/earnings/admin/toggle-member', 'POST', { userId, enabled })
|
|
|
+
|
|
|
+export const withdrawFamilyEarnings = (amount) =>
|
|
|
+ request('/api/earnings/admin/withdraw', 'POST', { amount })
|
|
|
+```
|
|
|
+
|
|
|
+## 7. 管理员后台
|
|
|
+
|
|
|
+### 新增页面:家庭收益管理
|
|
|
+
|
|
|
+- 搜索:按家庭名称/ID
|
|
|
+- 查看:家庭总账、成员分配情况
|
|
|
+- 提现审核:列表显示待审核的家庭提现申请
|
|
|
+- 操作:通过/拒绝家庭提现
|
|
|
+
|
|
|
+## 8. 忽略/不做的范围
|
|
|
+
|
|
|
+- ❌ 不重建完整的家庭间分润系统
|
|
|
+- ❌ 不改现有 `promotion_tier`(R0-R4)等级体系
|
|
|
+- ❌ 不改现有 `referral_tree` 物化路径表
|
|
|
+- ❌ 不改现有 `invite_milestone` 里程碑奖励
|
|
|
+
|
|
|
+## 9. 实施分阶段建议
|
|
|
+
|
|
|
+| 阶段 | 内容 | 涉及 |
|
|
|
+|:----:|------|------|
|
|
|
+| **P1** | 二维码改造:全部切 wxacode + 修复 env_version + 新增 `ref=` 场景处理 | WechatService, CommonController, App.vue |
|
|
|
+| **P2** | 家庭公共账户:建表 + CommissionService 改造 + settle 调用点改造 + 注册绑定 referralCode | 3 张新表 + 6 个 order service |
|
|
|
+| **P3** | 前端重构:推广中心重设计 + 成员贡献榜 + 管理员面板 + 消费支付集成 | 7 个 frontend pages + 支付流程 |
|
|
|
+| **P4** | 管理后台:家庭收益管理 + 提现审核 | admin panel |
|
|
|
+
|
|
|
+每阶段可独立上线,P1 无业务影响(二维码表现不变),P2/P3 为核心功能,P4 为运营配套。
|