Files
soul-yongping/开发文档/8、部署/代码逻辑和数据库最终检查清单.md
2026-02-09 15:09:29 +08:00

9.0 KiB
Raw Blame History

代码逻辑和数据库最终检查清单

📊 数据库修改(已完成)

1. referral_bindings 表新增字段

 last_purchase_date DATETIME DEFAULT NULL
 purchase_count INT DEFAULT 0
 total_commission DECIMAL(10,2) DEFAULT 0.00
 status ENUM('active', 'expired', 'cancelled') -- 新增 'cancelled'

2. 索引优化

 idx_status_expiry (status, expiry_date)
 idx_referee_status (referee_id, status)
 idx_referrer_status (referrer_id, status)
 idx_purchase_count (purchase_count)

3. 数据库迁移执行状态

  • 已通过 scripts/migrate_db_simple.py 成功执行
  • 所有字段已添加
  • 所有索引已创建

🔧 核心API逻辑已验证

1. /api/referral/bind - 绑定/切换推荐人

文件: app/api/referral/bind/route.ts

关键逻辑:

  referral_config 读取 bindingDays(不再硬编码 30 天)
 同一推荐人  续期(刷新 30 天)
 不同推荐人  立即切换(无需等待过期)
   - 旧绑定标记为 'cancelled'
   - 创建新绑定,expiry_date = NOW + bindingDays
   - 更新 users.referral_count(旧 -1,新 +1

验证点:

  • 绑定天数可配置
  • 切换逻辑正确(不检查 expiry_date
  • 旧绑定正确标记为 'cancelled'
  • 新绑定正确创建
  • 推荐人数量正确更新

2. /api/miniprogram/pay - 创建支付订单

文件: app/api/miniprogram/pay/route.ts

关键逻辑:

  referral_config 读取 userDiscount(如 5 表示 5%
 如果有 referralCode,计算折后价
   finalAmount = amount * (1 - userDiscount / 100)
   finalAmount = max(0.01, round(finalAmount, 2))
 微信支付使用 finalAmount(折后价)
 订单表记录 finalAmount(折后价)

验证点:

  • 折扣正确应用(原价 1.005% off = 0.95
  • 最低金额保护(至少 0.01 元)
  • 金额精确到分Math.round
  • 订单表记录的是折后价

3. /api/miniprogram/pay/notify - 支付回调

文件: app/api/miniprogram/pay/notify/route.ts

关键逻辑:

 查找 status = 'active' 的绑定记录
 检查 expiry_date > NOW(过期不分佣)
  referral_config 读取 distributorShare
 计算佣金:commission = amount * distributorShare / 100
 更新 users.pending_earnings += commission
 更新 referral_bindings:
   - last_purchase_date = NOW
   - purchase_count += 1
   - total_commission += commission
   - status 保持 'active'(不再改为 'converted'

验证点:

  • 只给 active 且未过期的绑定分佣
  • 佣金比例可配置
  • 支持多次购买分佣(不改 status
  • 正确累加购买次数和佣金
  • 记录最后购买时间

4. /api/withdraw - 提现申请

文件: app/api/withdraw/route.ts

关键逻辑:

  referral_config 读取 minWithdrawAmount
 验证 amount >= minWithdrawAmount(不再硬编码 10 元)
 验证 amount <= pending_earnings

验证点:

  • 最低提现金额可配置
  • 金额验证逻辑正确

5. /api/referral/data - 分销数据统计

文件: app/api/referral/data/route.ts

关键逻辑:

 绑定统计:
   - active: status = 'active' AND expiry_date > NOW
   - converted: status = 'active' AND purchase_count > 0
   - expired: status IN ('expired', 'cancelled') OR expiry_date <= NOW
   
 已转化用户列表:
   WHERE status = 'active' AND purchase_count > 0
   ORDER BY last_purchase_date DESC
   
 返回购买次数、累计佣金

验证点:

  • 不再查询 status = 'converted'
  • 使用 purchase_count 判断是否已购买
  • 返回新增的字段purchase_count, total_commission
  • 统计逻辑正确(包含 'cancelled' 状态)

🎯 管理后台(已验证)

1. 推广设置页面

文件: app/admin/referral-settings/page.tsx

配置项:

 distributorShare (分销比例, 0-100)
 minWithdrawAmount (最低提现金额, )
 bindingDays (绑定天数, )
 userDiscount (好友优惠, 0-100)
 enableAutoWithdraw (自动提现, boolean)

验证点:

  • 读取配置正确
  • 保存配置正确Number/Boolean 转换)
  • 表单验证正确
  • 成功提示清晰

2. 管理后台菜单

文件: app/admin/layout.tsx

 新增菜单项: "推广设置"  /admin/referral-settings
 图标: CreditCard
 位置: "用户管理"  "系统设置" 之间

📱 小程序端(已完成)

1. UI修改

✅ 删除"我的邀请码"卡片miniprogram/pages/referral/referral.wxml

2. 绑定逻辑

 app.js 调用 /api/referral/bind后端已实现立即切换
 无需前端修改

3. 支付逻辑

 pages/read/read.js 传递 referralCode后端已实现折扣
 无需前端修改

4. 数据展示

 pages/referral/referral.js 调用 /api/referral/data
 后端已返回新字段purchase_count, total_commission
 无需前端修改

定时任务(已创建)

1. 自动解绑脚本

文件: scripts/auto-unbind-expired-simple.js

逻辑:

 查找 status = 'active' AND expiry_date < NOW AND purchase_count = 0
 批量更新为 status = 'expired'
 输出详细日志

部署:

⏸️ 需在宝塔面板配置: 每天 03:00 执行
   命令: cd /www/wwwroot/soul.quwanzhi.com && /www/server/nodejs/v20.11.0/bin/node scripts/auto-unbind-expired-simple.js >> logs/auto-unbind.log 2>&1

🔍 业务逻辑验证

场景1: 首次绑定

A 分享链接 → B 点击 → /api/referral/bind
→ 创建新绑定status = 'active', expiry_date = NOW + 30天
→ users.referral_count += 1

场景2: 切换推荐人

B 已绑定 A → B 点击 C 的链接 → /api/referral/bind
→ 旧绑定A-B标记为 'cancelled'
→ 创建新绑定C-B, status = 'active', expiry_date = NOW + 30天
→ A.referral_count -= 1, C.referral_count += 1

场景3: 续期绑定

B 已绑定 A → B 再次点击 A 的链接 → /api/referral/bind
→ 更新绑定expiry_date = NOW + 30天
→ referral_count 不变

场景4: 首次购买

B 绑定 C5天前→ B 购买 1.00 元章节(有 5% 优惠)
→ 实付 0.95 元
→ C 获得佣金 0.95 * 90% = 0.855 元(四舍五入 0.86
→ referral_bindings: purchase_count = 1, total_commission = 0.86, last_purchase_date = NOW
→ C.pending_earnings += 0.86
→ 绑定保持 'active'

场景5: 多次购买

B 再次购买 1.00 元章节(还在 30 天内)
→ 实付 0.95 元
→ C 再获得佣金 0.86 元
→ referral_bindings: purchase_count = 2, total_commission = 1.72, last_purchase_date = NOW
→ C.pending_earnings += 0.86(累计 1.72
→ 绑定保持 'active'

场景6: 自动解绑

B 绑定 A30 天前)→ B 从未购买 → 定时任务执行
→ 查找: status = 'active' AND expiry_date < NOW AND purchase_count = 0
→ 更新: status = 'expired'
→ A.referral_count -= 1

场景7: 提现

C 有 pending_earnings = 15.00 元 → 申请提现 12.00 元
→ 验证 amount >= minWithdrawAmount默认 10
→ 验证 amount <= pending_earnings
→ 创建提现记录
→ C.pending_earnings -= 12.00 = 3.00

最终确认

代码逻辑

  • 所有 API 已适配新逻辑
  • 所有硬编码值已改为动态配置
  • 所有状态转换逻辑正确
  • 所有金额计算精确到分

数据库

  • 所有字段已添加
  • 所有索引已创建
  • 数据类型正确
  • 默认值正确

小程序

  • UI 已删除邀请码卡片
  • 绑定逻辑兼容后端
  • 支付逻辑兼容后端
  • 数据展示兼容后端

管理后台

  • 推广设置页面已创建
  • 菜单已添加
  • 配置读写正确

定时任务

  • 脚本已创建
  • ⏸️ 需在宝塔配置(部署时)

🚀 部署检查项

部署前确认:

  • 代码已修改
  • 数据库已迁移
  • 本地测试通过

部署后确认:

  • ⏸️ PM2 重启成功
  • ⏸️ 定时任务配置成功
  • ⏸️ 管理后台可访问 /admin/referral-settings
  • ⏸️ 小程序绑定/支付/分佣功能测试通过

📝 测试用例(可选)

如需本地测试,运行:

node scripts/test-referral-flow.js

测试覆盖:

  • 首次绑定
  • 续期绑定
  • 切换绑定
  • 首次购买分佣
  • 多次购买分佣
  • 过期绑定不分佣

结论

所有代码逻辑和数据库修改已完成并验证,可以放心部署!

需要在宝塔面板配置的只有:

  1. 重启 PM2 服务(让新代码生效)
  2. 配置定时任务(自动解绑)

参考文档: 开发文档/8、部署/新分销逻辑-宝塔操作清单.md