# 变更提案: admin-frontend-user-activity-status-filter

## 元信息
```yaml
类型: 功能开发
方案类型: implementation
优先级: P1
状态: 已完成
创建: 2026-04-25
```

---

## 1. 需求

### 背景
用户要求在 `admin-frontend` 的用户管理“高级筛选”中新增“活跃用户”判断，并明确选择扩展为“三态筛选”：支持按“全部 / 活跃 / 非活跃”理解筛选范围。当前高级筛选仅支持单字段条件组合，前端无法直接表达“有任意订阅 + 剩余流量 > 0 + 最后在线时间在半年内”这类跨字段复合判断，因此需要补齐前后端联动能力。

### 目标
- 在用户管理高级筛选弹窗中新增“活跃状态”条件，允许按活跃 / 非活跃筛选用户。
- 将“全部”保持为默认无筛选状态，不破坏现有高级筛选工作流。
- 后端 `user/fetch` 支持识别复合过滤字段，并按“任意订阅 + 流量未用完 + 最后在线时间在半年内”为活跃规则返回结果。

### 约束条件
```yaml
范围约束: 仅调整用户管理高级筛选相关前后端逻辑，不改动列表主结构和其他筛选能力
技术约束: 前端继续使用 Vue3 + TypeScript + Element Plus；后端继续沿用现有 UserController 过滤协议
业务约束: 活跃规则严格以用户本轮指令为准，不额外叠加封禁/到期等隐式条件
视觉约束: 延续 apple/DESIGN.md 与 .helloagents/DESIGN.md 的 Apple 风格后台样式，只做增量字段扩展
```

### 验收标准
- [ ] 高级筛选弹窗新增“活跃状态”字段，并可选择“活跃 / 非活跃”。
- [ ] “全部”状态下不额外发送活跃过滤条件，现有筛选行为保持不变。
- [ ] `user/fetch` 支持 `activity_status` 复合过滤，活跃判断规则为：`plan_id` 非空、`transfer_enable > u + d`、`last_online_at >= 近半年阈值`。
- [ ] 非活跃筛选返回活跃条件的反向集合。
- [ ] 至少完成一次后端单元验证与一次 `admin-frontend` 构建验证。

---

## 2. 方案

### 页面与交互
1. 延续现有高级筛选弹窗结构，不新增新的工具条入口。
2. 在字段列表中新增“活跃状态”，值选择使用枚举下拉，保持与“账号状态”一致的轻量操作方式。
3. “全部”继续通过“不添加该条件 / 清空该条件”表达，不在 UI 中额外堆叠冗余控件。

### 前端实现策略
1. 在 `admin-frontend/src/utils/users.ts` 中新增活跃状态字段定义、值选项、摘要格式化与过滤载荷映射。
2. 在 `admin-frontend/src/views/users/UserAdvancedFilterDialog.vue` 中补齐对应下拉输入分支。
3. 保持 `useUsersManagement.ts` 与现有 `buildUserFilters()` 聚合方式不变，由工具层输出新过滤项。

### 后端实现策略
1. 在 `app/Http/Controllers/V2/Admin/UserController.php` 中为 `activity_status` 增加专用解析逻辑。
2. 活跃条件由后端统一拼装，避免前端伪造多列比较表达式。
3. 非活跃条件按活跃规则的反向集合构造，保证“三态”中的“非活跃”可直接使用。

### 风险评估
| 风险 | 等级 | 应对 |
|------|------|------|
| 现有通用过滤协议只支持单字段比较 | 中 | 通过 `activity_status` 专用分支下沉复合查询 |
| `last_online_at` 为可空字段，非活跃定义容易遗漏 null | 中 | 在后端反向条件中显式纳入 `whereNull(last_online_at)` |
| 前端筛选摘要文案与实际规则不一致 | 低 | 统一在 `users.ts` 中维护字段标签和值文案 |

---

## 3. 技术决策

### admin-frontend-user-activity-status-filter#D001: 活跃判断作为高级筛选枚举字段而不是快捷工具条
**日期**: 2026-04-25  
**状态**: ✅采纳  
**背景**: 用户明确要求“给用户管理的高级筛选加个活跃用户的判断”。  
**决策**: 在高级筛选弹窗中新增“活跃状态”字段，维持原有筛选弹窗交互，不额外扩展快捷筛选区。  
**理由**: 最贴合用户点名的入口，也能避免在工具条中引入新的视觉噪音。

### admin-frontend-user-activity-status-filter#D002: 复合活跃规则统一由后端 `activity_status` 字段承接
**日期**: 2026-04-25  
**状态**: ✅采纳  
**背景**: 活跃规则包含“订阅存在 + 剩余流量比较 + 半年在线阈值”三段条件，前端现有过滤协议无法安全表达列与列比较。  
**决策**: 前端仅发送 `activity_status=eq:1|0`，具体 SQL 条件由 `UserController` 后端专用逻辑生成。  
**理由**: 能保证筛选规则唯一、可维护，也避免前端为了复合判断扩展非标准过滤语法。

### admin-frontend-user-activity-status-filter#D003: “全部”状态继续由无条件表达，不引入伪过滤值
**日期**: 2026-04-25  
**状态**: ✅采纳  
**背景**: 用户选择了“三态筛选”，但当前高级筛选系统本质上以“有条件 / 无条件”表达是否筛选。  
**决策**: “活跃 / 非活跃”作为显式值；“全部”保持为未添加该条件或清空该条件。  
**理由**: 既满足三态语义，又不破坏现有高级筛选的组合式模型。
