Files
soul-yongping/开发文档/8、部署/新分销逻辑-部署步骤.md

538 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 新分销逻辑 - 部署步骤
## 📋 部署前检查
### 确认新逻辑
- ✅ 点击谁的链接,立即绑定谁(无条件切换)
- ✅ 购买时,佣金给当前推荐人
- ✅ 30天内无购买 → 自动解绑
- ✅ 方案A购买后不重置30天
### 备份数据
```bash
# 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 脚本(推荐)
```bash
# 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
```bash
# 连接数据库
mysql -u root -p mycontent_db
# 执行迁移SQL
source scripts/migration-add-binding-fields.sql;
# 验证字段
SHOW COLUMNS FROM referral_bindings;
```
---
### Step 2: 部署代码
#### 本地构建
```bash
# 在本地项目目录
cd e:\Gongsi\Mycontent
# 构建
pnpm build
# 确认构建产物
ls -la .next/standalone
```
#### 上传到服务器
```bash
# 使用 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: 重启服务
```bash
# 重启 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
- **脚本内容**
```bash
cd /www/wwwroot/soul && node scripts/auto-unbind-expired-simple.js >> /www/wwwroot/soul/logs/auto-unbind.log 2>&1
```
#### 手动测试定时任务
```bash
# 进入项目目录
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立即切换绑定
#### 准备工作
```bash
# 创建测试用户 A、B、C
# A 推荐 B
# C 也想抢 B
```
#### 测试步骤
```bash
# 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购买分佣累加
#### 测试步骤
```bash
# 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天自动解绑
#### 模拟测试(修改过期时间)
```bash
# 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
```
---
## 🔍 监控与日志
### 查看绑定切换日志
```bash
# PM2 日志
pm2 logs soul | grep "Referral Bind"
# 查找"立即切换"记录
pm2 logs soul | grep "立即切换"
```
### 查看分佣日志
```bash
# 查看分佣成功记录
pm2 logs soul | grep "分佣完成"
# 查看累加情况
pm2 logs soul | grep "purchaseCount"
```
### 定时任务日志
```bash
# 查看定时任务执行记录
cat /www/wwwroot/soul/logs/auto-unbind.log
# 实时监控
tail -f /www/wwwroot/soul/logs/auto-unbind.log
```
---
## 📊 数据统计
### 查看当前绑定状态分布
```sql
SELECT
status,
COUNT(*) as count,
SUM(purchase_count) as total_purchases,
SUM(total_commission) as total_commission
FROM referral_bindings
GROUP BY status;
```
### 查看切换频率最高的用户
```sql
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天内即将过期的绑定
```sql
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. 恢复数据库
```bash
# 停止服务
pm2 stop soul
# 恢复备份
mysql -u root -p mycontent_db < backup_before_referral_20260205.sql
# 重启服务
pm2 start soul
```
#### 2. 恢复代码
```bash
# 方式1Git回滚
cd /www/wwwroot/soul
git reset --hard <上一个commit>
# 方式2恢复备份
tar -xzf backup_code_20260205.tar.gz
# 重启
pm2 restart soul
```
#### 3. 停用定时任务
```bash
# 宝塔面板 -> 计划任务 -> 停用或删除"自动解绑"任务
```
---
## 📝 常见问题
### Q1: 定时任务没有执行?
**检查步骤**
1. 确认宝塔计划任务状态为"启用"
2. 查看宝塔计划任务日志
3. 手动执行测试:`node scripts/auto-unbind-expired-simple.js`
4. 检查脚本权限:`chmod +x scripts/auto-unbind-expired-simple.js`
### Q2: 绑定切换后,旧推荐人还能收到佣金?
**原因**:可能是购买时的绑定查询逻辑有问题
**检查**
```sql
-- 查看 B 当前的绑定
SELECT * FROM referral_bindings
WHERE referee_id = 'test_user_b' AND status = 'active';
-- 应该只有1条 active 记录(最新的推荐人)
```
### Q3: purchase_count 字段不存在?
**原因**:数据库迁移未成功
**解决**
```bash
# 重新执行迁移
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_date`、`purchase_count`、`total_commission` 字段
- [ ] 点击不同推荐链接会立即切换(无报错)
- [ ] 购买后 `purchase_count` 会累加
- [ ] 定时任务能正常执行
---
## ✅ 部署完成检查表
- [ ] 数据库迁移成功
- [ ] 代码部署完成
- [ ] PM2 服务正常运行
- [ ] 定时任务已配置
- [ ] 测试用例1通过立即切换
- [ ] 测试用例2通过购买累加
- [ ] 日志正常输出
- [ ] 备份文件已保存
---
## 📞 问题反馈
如有问题,请提供:
1. 错误日志PM2日志或定时任务日志
2. 数据库状态(相关表的查询结果)
3. 复现步骤
**日志收集命令**
```bash
# 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
```