Files
soul-yongping/开发文档/8、部署/新分销逻辑-部署步骤.md
2026-03-07 22:58:43 +08:00

12 KiB
Raw Permalink Blame History

新分销逻辑 - 部署步骤

📋 部署前检查

确认新逻辑

  • 点击谁的链接,立即绑定谁(无条件切换)
  • 购买时,佣金给当前推荐人
  • 30天内无购买 → 自动解绑
  • 方案A购买后不重置30天

备份数据

# 1. 备份数据库
mysqldump -u root -p mycontent_db > backup_before_referral_$(date +%Y%m%d).sql

# 2. 备份代码
cd /www/wwwroot/soul
tar -czf backup_code_$(date +%Y%m%d).tar.gz app/ lib/ scripts/

🚀 部署步骤

Step 1: 数据库迁移

方式1使用 Python 脚本(推荐)

# 1. 上传脚本到服务器
cd /www/wwwroot/soul
# 将 scripts/migrate_binding_fields.py 上传到服务器

# 2. 确保环境变量正确(.env 文件)
cat .env | grep DB_

# 3. 执行迁移
python3 scripts/migrate_binding_fields.py

预期输出

==========================================================
数据库迁移referral_bindings 表字段升级
==========================================================

✅ 已连接到数据库: mycontent_db

步骤 1: 添加新字段
------------------------------------------------------------
✅ 添加字段 last_purchase_date
✅ 添加字段 purchase_count
✅ 添加字段 total_commission

步骤 2: 添加索引
------------------------------------------------------------
✅ 添加索引 idx_referee_status
✅ 添加索引 idx_expiry_purchase

步骤 3: 更新 status 枚举(添加 cancelled
------------------------------------------------------------
✅ 更新 status 枚举类型

步骤 4: 验证迁移结果
------------------------------------------------------------
✅ 字段 last_purchase_date 已存在
✅ 字段 purchase_count 已存在
✅ 字段 total_commission 已存在

==========================================================
✅ 迁移完成!
==========================================================

方式2直接执行 SQL

# 连接数据库
mysql -u root -p mycontent_db

# 执行迁移SQL
source scripts/migration-add-binding-fields.sql;

# 验证字段
SHOW COLUMNS FROM referral_bindings;

Step 2: 部署代码

本地构建

# 在本地项目目录
cd e:\Gongsi\Mycontent

# 构建
pnpm build

# 确认构建产物
ls -la .next/standalone

上传到服务器

# 使用 devlop.py自动化部署
python devlop.py

# 或手动上传
# 1. 上传修改的文件:
#    - app/api/referral/bind/route.ts
#    - app/api/miniprogram/pay/notify/route.ts
#    - scripts/auto-unbind-expired-simple.js

Step 3: 重启服务

# 重启 PM2
pm2 restart soul

# 查看日志确认启动正常
pm2 logs soul --lines 50

# 确认进程状态
pm2 status

预期输出

┌─────┬────────┬─────────┬──────┬─────┬──────────┐
│ id  │ name   │ status  │ ↺    │ cpu │ memory   │
├─────┼────────┼─────────┼──────┼─────┼──────────┤
│ 0   │ soul   │ online  │ 0    │ 0%  │ 100.0mb  │
└─────┴────────┴─────────┴──────┴─────┴──────────┘

Step 4: 配置定时任务

宝塔面板配置

  1. 登录宝塔面板
  2. 进入"计划任务"
  3. 添加 Shell 脚本任务

任务配置

  • 任务名称:自动解绑过期推荐关系
  • 执行周期:每天 02:00
  • 脚本内容
    cd /www/wwwroot/soul && node scripts/auto-unbind-expired-simple.js >> /www/wwwroot/soul/logs/auto-unbind.log 2>&1
    

手动测试定时任务

# 进入项目目录
cd /www/wwwroot/soul

# 创建日志目录
mkdir -p logs

# 手动执行一次
node scripts/auto-unbind-expired-simple.js

# 查看日志
cat logs/auto-unbind.log

预期输出(如果有过期记录):

============================================================
自动解绑定时任务
执行时间: 2026/2/5 02:00:00
============================================================

✅ 已连接到数据库: mycontent_db

步骤 1: 查询需要解绑的记录...
------------------------------------------------------------
找到 3 条需要解绑的记录

步骤 2: 解绑明细
------------------------------------------------------------
1. 用户 user_abc123
   推荐人: user_xyz789
   绑定时间: 2026/1/5
   过期时间: 2026/2/4 (已过期 1 天)
   购买次数: 0
   累计佣金: ¥0.00

...

步骤 3: 执行解绑操作...
------------------------------------------------------------
✅ 已成功解绑 3 条记录

步骤 4: 更新推荐人统计...
------------------------------------------------------------
  - user_xyz789: -2 个绑定
  - user_def456: -1 个绑定
✅ 已更新 2 个推荐人的统计数据

============================================================
✅ 任务完成
   - 解绑记录数: 3
   - 受影响推荐人: 2
============================================================

🧪 功能测试

测试用例1立即切换绑定

准备工作

# 创建测试用户 A、B、C
# A 推荐 B
# C 也想抢 B

测试步骤

# 1. A 推荐 B新绑定
curl -X POST http://localhost:3006/api/referral/bind \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "test_user_b",
    "referralCode": "SOULA001",
    "source": "miniprogram"
  }'

# 预期返回:
# {
#   "success": true,
#   "message": "绑定成功",
#   "action": "new",
#   "expiryDate": "2026-03-07T...",
#   "referrer": { "id": "test_user_a", "nickname": "用户A" }
# }

# 2. B 点击 C 的链接(立即切换)
curl -X POST http://localhost:3006/api/referral/bind \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "test_user_b",
    "referralCode": "SOULC001",
    "source": "miniprogram"
  }'

# 预期返回:
# {
#   "success": true,
#   "message": "已切换推荐人",
#   "action": "switch",
#   "expiryDate": "2026-03-07T...",
#   "referrer": { "id": "test_user_c", "nickname": "用户C" },
#   "oldReferrerId": "test_user_a"
# }

# 3. 验证数据库
mysql -u root -p mycontent_db -e "
  SELECT referee_id, referrer_id, status, binding_date, expiry_date 
  FROM referral_bindings 
  WHERE referee_id = 'test_user_b' 
  ORDER BY binding_date DESC LIMIT 2;
"

# 预期结果:
# 记录1: referee=B, referrer=C, status=active (最新)
# 记录2: referee=B, referrer=A, status=cancelled (旧)

测试用例2购买分佣累加

测试步骤

# 1. B 购买第1次1元
# 触发支付回调 -> /api/miniprogram/pay/notify

# 2. 查询分佣结果
mysql -u root -p mycontent_db -e "
  SELECT 
    rb.referrer_id,
    rb.purchase_count,
    rb.total_commission,
    u.pending_earnings
  FROM referral_bindings rb
  JOIN users u ON rb.referrer_id = u.id
  WHERE rb.referee_id = 'test_user_b' AND rb.status = 'active';
"

# 预期结果:
# referrer_id: test_user_c
# purchase_count: 1
# total_commission: 0.90 (假设90%分成)
# pending_earnings: 0.90

# 3. B 购买第2次1元
# 再次触发支付回调

# 4. 再次查询
# 预期结果:
# purchase_count: 2
# total_commission: 1.80
# pending_earnings: 1.80

测试用例330天自动解绑

模拟测试(修改过期时间)

# 1. 手动修改绑定的过期时间(测试用)
mysql -u root -p mycontent_db -e "
  UPDATE referral_bindings 
  SET expiry_date = '2026-02-04 00:00:00' 
  WHERE referee_id = 'test_user_x' AND referrer_id = 'test_user_y';
"

# 2. 执行定时任务
node scripts/auto-unbind-expired-simple.js

# 3. 验证解绑
mysql -u root -p mycontent_db -e "
  SELECT referee_id, referrer_id, status, expiry_date, purchase_count
  FROM referral_bindings 
  WHERE referee_id = 'test_user_x';
"

# 预期结果:
# status: expired如果 purchase_count = 0
# status: active如果 purchase_count > 0

🔍 监控与日志

查看绑定切换日志

# PM2 日志
pm2 logs soul | grep "Referral Bind"

# 查找"立即切换"记录
pm2 logs soul | grep "立即切换"

查看分佣日志

# 查看分佣成功记录
pm2 logs soul | grep "分佣完成"

# 查看累加情况
pm2 logs soul | grep "purchaseCount"

定时任务日志

# 查看定时任务执行记录
cat /www/wwwroot/soul/logs/auto-unbind.log

# 实时监控
tail -f /www/wwwroot/soul/logs/auto-unbind.log

📊 数据统计

查看当前绑定状态分布

SELECT 
  status,
  COUNT(*) as count,
  SUM(purchase_count) as total_purchases,
  SUM(total_commission) as total_commission
FROM referral_bindings
GROUP BY status;

查看切换频率最高的用户

SELECT 
  referee_id,
  COUNT(*) as binding_count,
  GROUP_CONCAT(referrer_id ORDER BY binding_date DESC) as referrer_history
FROM referral_bindings
WHERE status IN ('active', 'cancelled')
GROUP BY referee_id
HAVING COUNT(*) > 1
ORDER BY binding_count DESC
LIMIT 10;

查看30天内即将过期的绑定

SELECT 
  referee_id,
  referrer_id,
  binding_date,
  expiry_date,
  DATEDIFF(expiry_date, NOW()) as days_left,
  purchase_count
FROM referral_bindings
WHERE status = 'active'
  AND expiry_date > NOW()
  AND DATEDIFF(expiry_date, NOW()) <= 7
ORDER BY days_left ASC;

⚠️ 回滚方案

如果需要回滚到旧逻辑

1. 恢复数据库

# 停止服务
pm2 stop soul

# 恢复备份
mysql -u root -p mycontent_db < backup_before_referral_20260205.sql

# 重启服务
pm2 start soul

2. 恢复代码

# 方式1Git回滚
cd /www/wwwroot/soul
git reset --hard <上一个commit>

# 方式2恢复备份
tar -xzf backup_code_20260205.tar.gz

# 重启
pm2 restart soul

3. 停用定时任务

# 宝塔面板 -> 计划任务 -> 停用或删除"自动解绑"任务

📝 常见问题

Q1: 定时任务没有执行?

检查步骤

  1. 确认宝塔计划任务状态为"启用"
  2. 查看宝塔计划任务日志
  3. 手动执行测试:node scripts/auto-unbind-expired-simple.js
  4. 检查脚本权限:chmod +x scripts/auto-unbind-expired-simple.js

Q2: 绑定切换后,旧推荐人还能收到佣金?

原因:可能是购买时的绑定查询逻辑有问题

检查

-- 查看 B 当前的绑定
SELECT * FROM referral_bindings 
WHERE referee_id = 'test_user_b' AND status = 'active';

-- 应该只有1条 active 记录(最新的推荐人)

Q3: purchase_count 字段不存在?

原因:数据库迁移未成功

解决

# 重新执行迁移
python3 scripts/migrate_binding_fields.py

# 或手动添加
mysql -u root -p mycontent_db -e "
  ALTER TABLE referral_bindings 
  ADD COLUMN purchase_count INT DEFAULT 0;
"

Q4: 如何验证新逻辑是否生效?

验证清单

  • 数据库有 last_purchase_datepurchase_counttotal_commission 字段
  • 点击不同推荐链接会立即切换(无报错)
  • 购买后 purchase_count 会累加
  • 定时任务能正常执行

部署完成检查表

  • 数据库迁移成功
  • 代码部署完成
  • PM2 服务正常运行
  • 定时任务已配置
  • 测试用例1通过立即切换
  • 测试用例2通过购买累加
  • 日志正常输出
  • 备份文件已保存

📞 问题反馈

如有问题,请提供:

  1. 错误日志PM2日志或定时任务日志
  2. 数据库状态(相关表的查询结果)
  3. 复现步骤

日志收集命令

# PM2日志
pm2 logs soul --lines 100 > soul_logs.txt

# 定时任务日志
cat /www/wwwroot/soul/logs/auto-unbind.log > auto_unbind.log

# 数据库状态
mysql -u root -p mycontent_db -e "
  SELECT * FROM referral_bindings LIMIT 10;
  SHOW COLUMNS FROM referral_bindings;
" > db_status.txt