# 邀请新人系统文档

## 功能概述

用户可以通过分享邀请链接或小程序码邀请新用户注册，新用户注册后会自动绑定邀请关系，邀请人可获得佣金奖励。

## 完整流程

```
邀请者分享 → 新用户点击/扫码 → 进入小程序 → 保存邀请码 → 登录注册 → 绑定邀请关系
```

## 分享方式

### 1. 分享给微信好友
- 入口：邀请奖励页面 → 分享给好友按钮
- 实现：`onShareAppMessage()`
- 链接格式：`/pages/index/index?inviteCode=XXXXXX`

### 2. 分享到朋友圈
- 入口：邀请奖励页面 → 右上角分享
- 实现：`onShareTimeline()`
- 参数格式：`inviteCode=XXXXXX`

### 3. 小程序码
- 入口：邀请奖励页面 → 生成二维码按钮
- 实现：调用后端 `/api/v1/qrcode/miniprogram` 接口
- 参数格式：`scene=inviteCode=XXXXXX`

## 技术实现

### 前端文件

| 文件 | 功能 |
|------|------|
| `App.vue` | 定义 `globalData.inviteCode` 存储邀请码 |
| `pages/index/index.vue` | 接收并保存邀请码 |
| `pages/login/login-page.vue` | 登录时传递邀请码 |
| `pages/me/invite-reward-page.vue` | 邀请奖励页面，分享功能 |
| `modules/api/AppServer.js` | API调用，`WechatLogin(code, invitationCode)` |

### 后端文件

| 文件 | 功能 |
|------|------|
| `services/authService.js` | 微信登录，处理邀请码绑定 |
| `routes/qrcodeRoutes.js` | 生成小程序码 |
| `models/User.js` | 用户模型，`invitedBy` 字段 |
| `models/Invitation.js` | 邀请关系模型 |

### 邀请码接收逻辑 (index.vue)

```javascript
onLoad(options) {
  let inviteCode = ''
  
  // 方式1：普通分享链接
  if (options && options.inviteCode) {
    inviteCode = options.inviteCode
  }
  
  // 方式2：小程序码扫码（scene参数）
  if (options && options.scene) {
    const scene = decodeURIComponent(options.scene)
    const params = {}
    scene.split('&').forEach(item => {
      const [key, value] = item.split('=')
      if (key && value) params[key] = value
    })
    if (params.inviteCode) inviteCode = params.inviteCode
  }
  
  // 保存邀请码
  if (inviteCode) {
    getApp().globalData.inviteCode = inviteCode
    uni.setStorageSync('inviteCode', inviteCode)
  }
}
```

### 登录绑定逻辑 (login-page.vue)

```javascript
async handleWechatLogin() {
  // 获取邀请码
  let invitationCode = ''
  const app = getApp()
  if (app?.globalData?.inviteCode) {
    invitationCode = app.globalData.inviteCode
  } else {
    invitationCode = uni.getStorageSync('inviteCode') || ''
  }
  
  // 调用登录接口（带邀请码）
  const data = await appserver.WechatLogin(loginRes.code, invitationCode)
  
  // 登录成功后清除邀请码
  if (invitationCode) {
    app.globalData.inviteCode = ''
    uni.removeStorageSync('inviteCode')
  }
}
```

### 后端绑定逻辑 (authService.js)

```javascript
const wechatLogin = async (code, userInfo, invitationCode, deviceInfo) => {
  // ... 获取openId
  
  let user = await User.findOne({ where: { wechatOpenId: openId } })
  
  if (!user) {
    // 新用户注册
    const userData = {
      wechatOpenId: openId,
      invitationCode: await generateUniqueInvitationCode(),
    }
    
    // 处理邀请关系
    if (invitationCode) {
      const inviter = await User.findOne({ where: { invitationCode } })
      if (inviter) {
        userData.invitedBy = inviter.id
        // 创建邀请记录
        await Invitation.create({
          inviterId: inviter.id,
          inviteeId: user.id,
          invitationCode,
          registeredAt: new Date(),
          rewardStatus: 'pending',
        })
      }
    }
    
    user = await User.create(userData)
  }
  // ... 返回token
}
```

## 数据模型

### User 表
- `invitationCode`: 用户的邀请码（唯一）
- `invitedBy`: 邀请人ID

### Invitation 表
- `inviterId`: 邀请人ID
- `inviteeId`: 被邀请人ID
- `invitationCode`: 使用的邀请码
- `registeredAt`: 注册时间
- `firstPaymentAt`: 首次付款时间
- `rewardAmount`: 奖励金额
- `rewardStatus`: 奖励状态 (pending/credited/cancelled)

## 注意事项

1. **小程序码限制**：`page` 参数必须是已发布的小程序页面
2. **开发环境**：开发版/体验版扫码可能无法正常跳转
3. **邀请码有效性**：只对新用户有效，老用户登录不会重复绑定
4. **scene参数限制**：最长32字符，格式为 `inviteCode=XXXXXX`

## API接口

### 生成小程序码
```
POST /api/v1/qrcode/miniprogram
Authorization: Bearer {token}
Body: { width: 430 }
Response: { code: 0, data: { invitationCode, qrcodeUrl } }
```

### 微信登录（带邀请码）
```
POST /api/v1/auth/wechat-login
Body: { code, invitationCode }
Response: { code: 0, data: { token, user } }
```
