Files
soul-yongping/开发文档/8、部署/新分销逻辑-代码修改总结.md

9.4 KiB
Raw Blame History

新分销逻辑 - 代码修改总结

已完成的代码修改

1. 数据库层Database Layer

迁移脚本

  • scripts/migration-add-binding-fields.sqlSQL版本
  • scripts/migrate_binding_fields.pyPython完整版
  • scripts/migrate_db_simple.pyPython简化版- 已执行成功

新增字段

referral_bindings 表:
 last_purchase_date DATETIME     - 最后购买时间
 purchase_count INT              - 购买次数
 total_commission DECIMAL(10,2)  - 累计佣金
 status 新增枚举值 'cancelled'    - 被切换状态

新增索引

 idx_referee_status (referee_id, status)
 idx_expiry_purchase (expiry_date, purchase_count, status)

2. 核心业务逻辑Business Logic

2.1 绑定APIapp/api/referral/bind/route.ts

修改前

// ❌ 有效期内不能切换
if (expiryDate < now) {
  // 已过期才能抢夺
} else {
  return { error: '绑定有效期内无法更换' }
}

修改后

// ✅ 立即切换(无条件)
if (existing.referrer_id === referrer.id) {
  action = 'renew'  // 同一推荐人:续期
} else {
  action = 'switch'  // 不同推荐人:立即切换
  
  // 旧绑定标记为 cancelled
  await query("UPDATE referral_bindings SET status = 'cancelled' WHERE id = ?", [existing.id])
}

核心变化

  • 删除"有效期内不能切换"限制
  • 点击新链接立即切换推荐人
  • 旧绑定标记为 cancelled(不是 expired
  • 新绑定重新计算30天

2.2 支付回调:app/api/miniprogram/pay/notify/route.ts

修改前

// ❌ 购买后标记为 converted不再累加
await query(`
  UPDATE referral_bindings 
  SET status = 'converted',
      commission_amount = ?
  WHERE id = ?
`, [commission, binding.id])

修改后

// ✅ 保持 active累加购买次数和佣金
await query(`
  UPDATE referral_bindings 
  SET last_purchase_date = CURRENT_TIMESTAMP,
      purchase_count = purchase_count + 1,
      total_commission = total_commission + ?
  WHERE id = ?
`, [commission, binding.id])

核心变化

  • 不再改变 status(保持 active
  • 累加 purchase_count
  • 累加 total_commission
  • 记录 last_purchase_date
  • 支持同一绑定多次购买分佣

2.3 支付订单:app/api/miniprogram/pay/route.ts

新增功能:好友优惠折扣

// ✅ 读取好友优惠配置
const referralConfig = await getConfig('referral_config')
const userDiscount = referralConfig?.userDiscount || 0

// ✅ 如果有推荐码,应用折扣
if (userDiscount > 0 && body.referralCode) {
  const discountRate = userDiscount / 100
  finalAmount = amount * (1 - discountRate)
  // 原价 1.00 → 优惠 5% → 实付 0.95
}

核心变化

  • 通过推荐链接购买会自动打折
  • 折扣比例从后台配置读取
  • 佣金基于实付金额计算

2.4 提现APIapp/api/withdraw/route.ts

新增功能:读取最低提现门槛

// ✅ 从配置读取最低提现门槛
const config = await getConfig('referral_config')
const minWithdrawAmount = config?.minWithdrawAmount || 10

// ✅ 检查最低门槛
if (amount < minWithdrawAmount) {
  return { error: `最低提现金额为 ¥${minWithdrawAmount}` }
}

核心变化

  • 提现门槛可通过后台配置
  • 替代了硬编码的 10 元

3. 管理后台Admin Panel

3.1 推广设置页面:app/admin/referral-settings/page.tsx

新增功能

  • 配置好友优惠userDiscount
  • 配置推广者分成distributorShare
  • 配置绑定有效期bindingDays
  • 配置最低提现金额minWithdrawAmount
  • 配置自动提现开关enableAutoWithdraw

数据安全

// ✅ 保存时强制类型转换
const safeConfig = {
  distributorShare: Number(config.distributorShare) || 0,
  minWithdrawAmount: Number(config.minWithdrawAmount) || 0,
  bindingDays: Number(config.bindingDays) || 0,
  userDiscount: Number(config.userDiscount) || 0,
  enableAutoWithdraw: Boolean(config.enableAutoWithdraw),
}

3.2 菜单入口:app/admin/layout.tsx

// ✅ 新增菜单项
{ icon: CreditCard, label: "推广设置", href: "/admin/referral-settings" }

4. 小程序MiniProgram

4.1 分销中心UIminiprogram/pages/referral/referral.wxml

修改

<!-- ✅ 删除"我的邀请码"卡片 -->
<!-- 保留分享按钮和收益明细 -->

5. 定时任务Scheduled Task

自动解绑脚本

  • scripts/auto-unbind-expired.js(标准版)
  • scripts/auto-unbind-expired-simple.js简化版直接连MySQL

解绑条件

WHERE status = 'active'
  AND expiry_date < NOW()
  AND purchase_count = 0

执行逻辑

  1. 查询符合条件的绑定
  2. 标记为 expired
  3. 更新推荐人的 referral_count
  4. 输出日志

📋 完整的业务流程

场景1新用户绑定

用户操作B 点击 A 的分享链接
触发API/api/referral/bind
数据变化:
  - referral_bindings 新增记录
    - referee_id: B
    - referrer_id: A
    - status: active
    - expiry_date: NOW + 30天
    - purchase_count: 0
  - users.referred_by: A
  - users.referral_count (A): +1

场景2切换推荐人

用户操作B 点击 C 的分享链接
触发API/api/referral/bind
数据变化:
  - 旧绑定 (A -> B):
    - status: active → cancelled
  - 新绑定 (C -> B):
    - 新增记录
    - status: active
    - expiry_date: NOW + 30天
  - users.referred_by: A → C
  - users.referral_count (A): -1
  - users.referral_count (C): +1

场景3购买分佣

用户操作B 购买文章1元假设无优惠
触发API/api/miniprogram/pay/notify
数据变化:
  - referral_bindings (C -> B):
    - purchase_count: 0 → 1
    - total_commission: 0 → 0.90
    - last_purchase_date: NOW
    - status: 保持 active
  - users.pending_earnings (C): +0.90

场景4好友优惠购买

用户操作B 通过推荐链接购买原价1元优惠5%
触发API/api/miniprogram/pay
计算逻辑:
  - 原价: 1.00元
  - 优惠: 1.00 × 5% = 0.05元
  - 实付: 0.95元
  
后续分佣:
  - 佣金 = 0.95 × 90% = 0.855元
  - C 获得 0.86元(四舍五入)

场景5自动解绑

触发定时任务每天02:00
执行脚本scripts/auto-unbind-expired-simple.js
筛选条件:
  - status = 'active'
  - expiry_date < NOW
  - purchase_count = 0
  
数据变化:
  - referral_bindings: status → expired
  - users.referral_count: -1对应的推荐人

🎯 核心逻辑总结

功能 实现状态 说明
立即切换绑定 完成 点击新链接立即切换推荐人
佣金归属 完成 给购买时的当前推荐人
购买累加 完成 同一绑定可多次购买分佣
好友优惠 完成 通过推荐链接自动打折
提现门槛 完成 后台可配置最低金额
自动解绑 完成 30天无购买自动解绑
推广设置页 完成 管理后台统一配置入口

📦 已部署文件清单

后端API7个文件

  1. app/api/referral/bind/route.ts - 立即切换绑定
  2. app/api/miniprogram/pay/notify/route.ts - 累加分佣
  3. app/api/miniprogram/pay/route.ts - 好友优惠
  4. app/api/withdraw/route.ts - 提现门槛
  5. app/admin/referral-settings/page.tsx - 推广设置页
  6. app/admin/layout.tsx - 菜单入口

小程序1个文件

  1. miniprogram/pages/referral/referral.wxml - 去掉邀请码卡片

脚本5个文件

  1. scripts/migrate_db_simple.py - 数据库迁移
  2. scripts/auto-unbind-expired-simple.js - 定时任务
  3. scripts/test-referral-flow.js - 功能测试

文档3个文件

  1. 开发文档/8、部署/新分销逻辑设计方案.md
  2. 开发文档/8、部署/新分销逻辑-部署步骤.md
  3. 开发文档/8、部署/新分销逻辑-宝塔操作清单.md

🔄 部署状态

  • 数据库字段已添加
  • 代码已构建pnpm build
  • 代码已上传服务器python devlop.py
  • 待操作:宝塔面板重启服务
  • 待操作:宝塔面板配置定时任务

🚦 下一步操作

必须完成(服务才能生效)

  1. 重启 Node.js 服务

    • 宝塔面板 → 网站 → soul.quwanzhi.com → Node项目 → 重启
    • 或SSH执行/www/server/nodejs/v16.20.2/bin/pm2 restart soul
  2. 配置定时任务

    • 宝塔面板 → 计划任务 → 添加Shell脚本
    • 执行周期:每天 02:00
    • 脚本内容:
      cd /www/wwwroot/soul/dist && /www/server/nodejs/v16.20.2/bin/node scripts/auto-unbind-expired-simple.js >> /www/wwwroot/soul/logs/auto-unbind.log 2>&1
      

建议测试

  1. 验证功能
    • 访问推广设置页面:https://soul.quwanzhi.com/admin/referral-settings
    • 小程序测试绑定切换
    • 测试购买分佣

代码逻辑完成度100%

所有核心逻辑已全部实现并部署!

剩余工作仅为:

  1. 宝塔面板重启服务1分钟
  2. 宝塔面板配置定时任务2分钟
  3. 功能测试验证(可选)