# 管理后台用户列表会员类型过滤功能

## 问题描述
原有的 `/admin/users/list` 接口在查询VIP用户时，没有区分付费VIP和兑换码VIP，导致查询付费用户时包含了使用兑换码的用户，数据混乱。

## 解决方案
在用户列表查询接口中添加了 `membershipType` 参数，用于过滤不同类型的会员用户。

## 会员类型说明

### 会员类型分类

#### 当前有效会员（需要检查会员到期时间）
1. **paid（当前付费会员）**：通过支付获得VIP会员的用户，有成功的订单记录，且会员未过期
2. **exchange（当前兑换会员）**：使用兑换码获得会员的用户，有兑换记录，且会员未过期  
3. **gift（赠送会员）**：注册2天内的VIP用户，且没有付费记录和兑换记录，且会员未过期

#### 过期会员
4. **expired（过期会员）**：VIP用户但会员已过期（不区分付费还是兑换）
5. **paidExpired（付费过期会员）**：有付费记录但会员已过期
6. **exchangeExpired（兑换过期会员）**：有兑换记录但会员已过期

#### 全部用户
7. **all（全部用户）**：所有用户，不进行会员类型过滤（默认行为）

## API使用说明

### 1. 原有接口增强

**接口地址**：`GET /admin/users/list`

**新增参数**：
- `membershipType`：会员类型筛选，可选值：`paid`、`exchange`、`gift`、`expired`、`paidExpired`、`exchangeExpired`、`all`（可选）

**使用示例**：

```bash
# 查询当前付费会员（有效期内）
GET /admin/users/list?page=1&size=20&membershipType=paid&sortField=createTime&sortOrder=desc

# 查询当前兑换会员（有效期内）
GET /admin/users/list?page=1&size=20&membershipType=exchange

# 查询赠送会员（有效期内）
GET /admin/users/list?page=1&size=20&membershipType=gift

# 查询过期会员
GET /admin/users/list?page=1&size=20&membershipType=expired

# 查询付费过期会员
GET /admin/users/list?page=1&size=20&membershipType=paidExpired

# 查询兑换过期会员
GET /admin/users/list?page=1&size=20&membershipType=exchangeExpired

# 查询所有用户（默认行为，保持向后兼容）
GET /admin/users/list?page=1&size=20
```

### 2. 新增专用付费用户接口

**接口地址**：`GET /admin/users/paid-users`

**功能说明**：专门用于查询付费用户，自动过滤掉兑换码用户和赠送用户

**参数说明**：
- `page`：页码（默认1）
- `size`：每页大小（默认20）
- `keyword`：搜索关键词（用户名、手机号）（可选）
- `createTimeStart`：注册时间开始（格式：YYYY-MM-DD）（可选）
- `createTimeEnd`：注册时间结束（格式：YYYY-MM-DD）（可选）
- `sortField`：排序字段（默认createTime）（可选）
- `sortOrder`：排序方向（默认desc）（可选）

**使用示例**：

```bash
# 查询当前有效的付费用户
GET /admin/users/paid-users?page=1&size=20

# 查询当前有效的付费用户，按关键词搜索
GET /admin/users/paid-users?page=1&size=20&keyword=张三

# 查询指定时间范围的当前有效付费用户
GET /admin/users/paid-users?page=1&size=20&createTimeStart=2024-01-01&createTimeEnd=2024-01-31
```

## 实现原理

### SQL过滤逻辑

#### 当前有效会员（会员未过期）

1. **当前付费会员（paid）**：
   ```sql
   AND u.role > 1
   AND u.membership_expires_at IS NOT NULL 
   AND u.membership_expires_at > NOW()
   AND EXISTS (
       SELECT 1 FROM `order` o 
       WHERE o.user_id = u.id 
       AND o.status = 1 
       AND o.is_deleted = 0
   )
   ```

2. **当前兑换会员（exchange）**：
   ```sql
   AND u.role > 1
   AND u.membership_expires_at IS NOT NULL 
   AND u.membership_expires_at > NOW()
   AND EXISTS (
       SELECT 1 FROM gift_code_usage gcu 
       WHERE gcu.user_id = u.id 
       AND gcu.type = 2 
       AND gcu.status = 1 
       AND gcu.is_deleted = 0
   )
   ```

3. **赠送会员（gift）**：
   ```sql
   AND u.role > 1
   AND u.membership_expires_at IS NOT NULL 
   AND u.membership_expires_at > NOW()
   AND u.create_time >= DATE_SUB(NOW(), INTERVAL 2 DAY)
   AND NOT EXISTS (
       SELECT 1 FROM `order` o 
       WHERE o.user_id = u.id 
       AND o.status = 1 
       AND o.is_deleted = 0
   )
   AND NOT EXISTS (
       SELECT 1 FROM gift_code_usage gcu 
       WHERE gcu.user_id = u.id 
       AND gcu.type = 2 
       AND gcu.status = 1 
       AND gcu.is_deleted = 0
   )
   ```

#### 过期会员

4. **过期会员（expired）**：
   ```sql
   AND u.role > 1
   AND (u.membership_expires_at IS NULL OR u.membership_expires_at <= NOW())
   ```

5. **付费过期会员（paidExpired）**：
   ```sql
   AND u.role > 1
   AND (u.membership_expires_at IS NULL OR u.membership_expires_at <= NOW())
   AND EXISTS (
       SELECT 1 FROM `order` o 
       WHERE o.user_id = u.id 
       AND o.status = 1 
       AND o.is_deleted = 0
   )
   ```

6. **兑换过期会员（exchangeExpired）**：
   ```sql
   AND u.role > 1
   AND (u.membership_expires_at IS NULL OR u.membership_expires_at <= NOW())
   AND EXISTS (
       SELECT 1 FROM gift_code_usage gcu 
       WHERE gcu.user_id = u.id 
       AND gcu.type = 2 
       AND gcu.status = 1 
       AND gcu.is_deleted = 0
   )
   ```

## 修改文件列表

1. `src/main/java/com/dora/dto/AdminUserDto.java` - 添加membershipType参数
2. `src/main/java/com/dora/mapper/UserMapper.java` - 更新Mapper接口
3. `src/main/resources/mapper/UserMapper.xml` - 添加SQL过滤逻辑
4. `src/main/java/com/dora/service/impl/AdminUserServiceImpl.java` - 传递新参数
5. `src/main/java/com/dora/controller/AdminUserController.java` - 更新控制器和文档

## 向后兼容性
- 原有的API调用方式保持不变
- 不传递 `membershipType` 参数时，行为与之前完全一致
- 所有现有功能都正常工作

## 使用建议

1. **查询当前有效付费用户统计时**，推荐使用：
   ```bash
   GET /admin/users/list?membershipType=paid
   ```
   或者使用专用接口：
   ```bash
   GET /admin/users/paid-users
   ```

2. **分析用户结构时**，可以分别查询不同类型：
   - 当前付费会员：`membershipType=paid`
   - 当前兑换会员：`membershipType=exchange`
   - 赠送会员：`membershipType=gift`
   - 过期会员：`membershipType=expired`
   - 付费过期会员：`membershipType=paidExpired`
   - 兑换过期会员：`membershipType=exchangeExpired`

3. **原有查询保持不变**，确保系统的向后兼容性

## 注意事项

### 重要变更：会员有效期检查

**⚠️ 关键改进**：现在所有会员类型查询都会检查 `membership_expires_at` 字段，确保只查询到当前有效的会员。

### 会员分类说明

1. **当前付费会员（paid）**包括：
   - 纯付费用户（只通过支付获得会员，且会员未过期）
   - 兑换后付费用户（先使用兑换码，后又付费购买，且会员未过期）

2. **当前兑换会员（exchange）**包括：
   - 纯兑换用户（只使用兑换码，从未付费，且会员未过期）
   - 兑换后付费用户（会在两个类型中都出现，且会员未过期）

3. **赠送会员（gift）**是指：
   - 注册2天内成为VIP但没有任何付费或兑换记录的用户
   - 且会员仍在有效期内

4. **过期会员系列**：
   - `expired`：所有过期的VIP用户
   - `paidExpired`：有付费记录但会员已过期
   - `exchangeExpired`：有兑换记录但会员已过期

### 查询策略建议

- **查询真正的付费用户**：使用 `membershipType=paid`
- **查询所有当前有效VIP**：使用 `paid` + `exchange` + `gift`
- **查询过期用户进行清理**：使用 `expired` 系列
- **历史数据分析**：使用 `paidExpired` 和 `exchangeExpired`
