# vala_user — 用户 & 角色数据字典

> MySQL 线上数据库，存储账号和角色信息。

## 连接信息

所有凭证存储在 `~/.hermes/.env` 中（MySQL 线上 → `VALA_MYSQL_ONLINE_*`，MySQL 测试 → `VALA_MYSQL_TEST_*`）。

## 实体关系图

```
vala_app_account (账号)           vala_app_character (角色)
┌─────────────────────┐          ┌──────────────────────────┐
│ id (PK)             │◄─────────│ account_id (FK)          │
│ tel                 │  1:N     │ id (PK)                  │
│ tel_encrypt         │          │ nickname                 │
└─────────────────────┘          │ gender                   │
                                 │ birthday                 │
                                 │ purchase_season_package  │
                                 │ created_at               │
                                 └──────────────────────────┘
```

- 一个账号可以有多个角色（例如：一个孩子一个角色）
- 关联字段：`vala_app_character.account_id = vala_app_account.id`

## 表结构

### vala_app_account（账号表）

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint | 账号ID（主键） |
| `tel` | varchar(20) | 手机号（脱敏显示，如 `158****7007`） |
| `tel_encrypt` | varchar(100) | 手机号密文（XXTEA + Base64 URL-safe） |

### vala_app_character（角色表）

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | bigint | 角色ID（主键） |
| `account_id` | bigint | 所属账号ID（FK → vala_app_account.id） |
| `nickname` | varchar(20) | 角色昵称 |
| `gender` | tinyint(1) | 性别 |
| `birthday` | varchar(50) | 生日 |
| `purchase_season_package` | text | 已购赛季包 |
| `created_at` | datetime | 创建时间 |

## 手机号加密

- **算法**: XXTEA
- **密钥**: 存储在 `~/.hermes/.env` → `VALA_PHONE_XXTEA_KEY`
- **编码**: Base64 URL-safe（`+`→`-`, `/`→`_`, `=`→`.`）
- **工具脚本**: `business_knowledge/scripts/phone_encrypt.py`

### 加密流程

```
明文手机号 → XXTEA加密 → Base64 → URL-safe替换 → tel_encrypt 密文
```

### 查询流程

1. 用 `phone_encrypt.py` 将手机号加密为密文
2. 用密文在 `vala_app_account.tel_encrypt` 精确匹配
3. JOIN `vala_app_character` 获取角色列表

```sql
SELECT
    a.id AS account_id,
    a.tel,
    c.id AS character_id,
    c.nickname,
    c.gender,
    c.birthday,
    c.purchase_season_package
FROM vala_app_account a
LEFT JOIN vala_app_character c ON c.account_id = a.id
WHERE a.tel_encrypt = '<密文>';
```

## 注意事项

1. **tel 字段是脱敏的**（如 `158****7007`），不能用于精确匹配
2. **必须用 tel_encrypt 密文匹配**
3. **一个账号可以有多个角色**，查询结果可能返回多行
4. 测试环境和线上环境的 `tel_encrypt` 值相同（加密算法一致）
