# 轮询配置二维条件重构计划

## 背景

当前轮询配置使用 `card_condition` 单字段表达卡的轮询条件，但业务上实际存在两个独立维度：

- 实名状态：未实名、已实名
- 卡状态：开机、停机

单字段枚举会把两个维度压成互斥状态，导致“未实名 + 停机”这类卡只能命中一个条件，配置语义不直观，也容易出现高低频策略互相覆盖。

## 目标

将轮询配置从单一 `card_condition` 改为二维条件匹配：

- `realname_condition`：`any`、`not_real_name`、`real_name`
- `network_condition`：`any`、`online`、`offline`

配置匹配规则调整为：

```text
实名条件匹配 AND 卡状态条件匹配 AND 卡类型/运营商等条件匹配
```

一张卡允许同时命中多条配置；每个任务类型仍按现有 `priority ASC` 选择第一条非空 interval。

## 推荐语义

| 条件字段 | 值 | 语义 |
| --- | --- | --- |
| `realname_condition` | `any` | 不限制实名状态 |
| `realname_condition` | `not_real_name` | `real_name_status != 1` |
| `realname_condition` | `real_name` | `real_name_status = 1` |
| `network_condition` | `any` | 不限制开停机状态 |
| `network_condition` | `online` | `network_status = 1` |
| `network_condition` | `offline` | `network_status = 0` |

## 迁移映射

为了平滑迁移旧配置，可按以下规则回填新字段：

| 旧 `card_condition` | 新 `realname_condition` | 新 `network_condition` |
| --- | --- | --- |
| 空 | `any` | `any` |
| `not_real_name` | `not_real_name` | `online` |
| `real_name` | `real_name` | `any` |
| `suspended` | `any` | `offline` |
| `activated` | `real_name` | `online` |

## 示例配置

未实名卡高频实名：

```text
realname_condition = not_real_name
network_condition = any
realname_check_interval = 120
其他 interval = NULL
```

停机卡高频套餐和卡状态：

```text
realname_condition = any
network_condition = offline
package_check_interval = 120
card_status_check_interval = 120
其他 interval = NULL
```

已实名开机卡低频实名、常规套餐和卡状态：

```text
realname_condition = real_name
network_condition = online
realname_check_interval = 86400
package_check_interval = 300
card_status_check_interval = 3600
```

## 实施步骤

1. 新增数据库字段 `realname_condition` 和 `network_condition`，保留旧字段用于迁移兼容。
2. 回填历史配置的新字段值。
3. 调整 DTO、Handler、Service、文档生成器和 OpenAPI 描述。
4. 调整 `PollingConfigManager` 的匹配逻辑，按二维条件筛选配置。
5. 验证典型组合：未实名开机、未实名停机、已实名开机、已实名停机。
6. 确认线上配置完成迁移后，再考虑废弃旧 `card_condition` 字段。

## 风险

- `real_name` 条件生效后，现有灰度配置可能覆盖大量已实名卡，需要上线前确认优先级和 interval。
- 多条配置同时命中是预期行为，但需要用 priority 明确每个任务类型的最终 interval。
- 迁移期间需要保持旧配置兼容，避免配置未更新时轮询队列为空。
