# 管理后台：在线汇总 & 注册/域名统计 API

> 基础路径：`/admin`  
> 鉴权：请求头携带管理员 JWT（`admin.jwt` 中间件）  
> 统一响应：

```json
{
  "code": 0,
  "timestamp": 1785900000,
  "msg": "OK",
  "data": {}
}
```

`code !== 0` 时 `msg` 为错误信息，`data` 可能为空。

---

## 一、在线汇总（菜单 uri：`onlineSummary`）

前端两个 Tab 对应两个接口（**后端无 tab 参数**，由前端 Tab 切换调用不同 URL）。平台人数用专用接口轮询，**不要**挂在 `paymentOrder/unProcessed` 上。

| 前端 Tab | 建议 tab 值（前端自用） | 接口 |
|----------|-------------------------|------|
| 在线用户 | `online` | `GET /admin/online/users` |
| 新用户汇总 | `newUser` | `GET /admin/online/newUserSummary` |
| （计数 / 角标） | - | `GET /admin/online/platformCount` |

---

### 1.1 在线用户

**URL**

```http
GET /admin/online/users
```

**说明**

当前在线会员列表。在线判定满足其一即可：

1. 存在未过期 `user_session`（`expire_time > 当前 unix 时间`）
2. `last_active_time` 为有效 unix 时间戳，且在最近 **30 分钟** 内

排除虚拟游客（`from = 2`）。  
关联该用户最近一次成功登录日志，填充 IP、位置、登录网站、平台、浏览器、系统、登入时间。

**请求参数（Query）**

| 参数 | 类型 | 必填 | 默认 | 说明 |
|------|------|------|------|------|
| `page` | int | 否 | `1` | 页码，≥1 |
| `limit` | int | 否 | `15` | 每页条数，1～200 |
| `member_id` | string | 否 | - | 会员 ID（匹配 `member_id` 或 `user_id`） |
| `first_name` | string | 否 | - | 会员昵称，模糊匹配 |
| `login_ip` | string | 否 | - | IP，模糊匹配最近登录 IP |
| `platform` | string | 否 | - | 平台：`PC` / `Android` / `iOS` / `H5` / `WeChat`；空或「全部」表示不限 |

**请求示例**

```http
GET /admin/online/users?page=1&limit=15&member_id=&first_name=&login_ip=&platform=
```

**返回 `data`**

| 字段 | 类型 | 说明 |
|------|------|------|
| `total` | int | 总条数 |
| `data` | array | 列表 |

**`data[]` 列表项**

| 字段 | 类型 | 前端列名 | 说明 |
|------|------|----------|------|
| `member_id` | string | 会员ID | 优先 `member_id`，否则 `user_id` |
| `first_name` | string | 会员昵称 | |
| `available_balance` | number | 账户余额 | 主钱包可用余额 |
| `login_ip` | string | IP地址 | 最近一次成功登录 IP |
| `location` | string | 位置 | 登录时写入的国家/地区（`country`） |
| `login_domain` | string | 登录网站 | 登录时 Referer/Origin 主机 |
| `platform` | string | 平台 | `PC`（电脑）/ `iOS`（苹果APP）/ `Android`（安卓APP）/ `H5`（手机H5）/ `WeChat`（微信） |
| `browser` | string | 浏览器 | |
| `os` | string | 操作系统 | |
| `login_time` | string | 登入时间 | `Y-m-d H:i:s`，最近一次成功登录时间 |
| `last_active_time` | string | （扩展） | 最后活跃时间 `Y-m-d H:i:s` |

**返回示例**

```json
{
  "code": 0,
  "timestamp": 1785900000,
  "msg": "OK",
  "data": {
    "total": 2,
    "data": [
      {
        "member_id": "10001",
        "first_name": "test01",
        "available_balance": 1250.5,
        "login_ip": "1.2.3.4",
        "location": "中国 广东 深圳",
        "login_domain": "www.example.com",
        "platform": "PC",
        "browser": "Chrome(120.0.0)",
        "os": "Windows 10/11",
        "login_time": "2026-08-05 10:20:30",
        "last_active_time": "2026-08-05 10:20:30"
      }
    ]
  }
}
```

---

### 1.1.1 在线平台人数（唯一在线人数接口）

**URL**

```http
GET /admin/online/platformCount
```

**说明**

当前在线会员按**端**汇总。在线判定与「在线用户」列表相同。

**设计**：登录写入侧（melbet `ClientPlatformDetector`）一次性写定 `user_login.platform`；后台只做 `GROUP BY platform` + 映射，**不再**用 `login_domain` / OS 二次推断。

写入规则摘要：

| platform 入库值 | 含义 | 判定 |
|-----------------|------|------|
| `iOS` | 苹果 APP | 包名域名 + iOS（`Sec-CH-UA-Platform` / UA） |
| `Android` | 安卓 APP | 包名域名 + Android |
| `PC` | 电脑 | 桌面 OS |
| `H5` | **手机 H5** | 非 APP 的手机浏览器 |
| `WeChat` | 微信 | UA 含 MicroMessenger（统计并入 mobile） |
| `''` | 未知 | 无法判断，不强行归类 |

| 字段 | 含义 | 映射 |
|------|------|------|
| `apple` | 苹果 APP | `iOS` |
| `android` | 安卓 APP | `Android` |
| `pc` | PC | `PC` |
| `mobile` | **手机 H5** | `H5` + `WeChat` |
| `wechat` | 微信（明细，已计入 mobile） | `WeChat` |
| `unknown` | 未知 | 空 / 未识别 |
| `total` | 总在线 | 以上合计 |

> `mobile` 专指 **手机浏览器 H5**，与原生 APP 互斥，**不是** 苹果+安卓合计。  
> `GET /admin/paymentOrder/unProcessed` **只**返回待处理订单角标，不含在线人数。

**返回示例**

```json
{
  "code": 0,
  "msg": "OK",
  "data": {
    "total": 128,
    "apple": 35,
    "android": 62,
    "pc": 28,
    "mobile": 100,
    "wechat": 3,
    "unknown": 0
  }
}
```

---

### 1.2 新用户汇总

**URL**

```http
GET /admin/online/newUserSummary
```

**说明**

按「注册日」汇总新用户指标。区间内集合查询，按天返回。

**业务口径**

| 指标 | 规则 |
|------|------|
| H5 / APP 注册 | 按 `register_domain`：包名风格（如 `com.xxx.yyy`）计 APP，否则 H5 |
| H5/APP 首存次数 | 该日新注册用户中，**历史首次正充值**发生在注册当日的人数 |
| 活跃会员 | 该日新注册，且**注册当日**下注合计 ≥ ¥50 的人数 |
| 有效会员 | 该日新注册，且**注册当日**存款合计 ≥ ¥50 的人数 |
| 存款总额 | 该日新注册用户在注册当日的充值合计 |
| 下注总数 | 该日新注册用户在注册当日的投注合计（绝对值） |
| 公司盈利 | 该日新注册用户当日：投注额 − 派奖（中奖） |

**请求参数（Query）**

| 参数 | 类型 | 必填 | 默认 | 说明 |
|------|------|------|------|------|
| `start_time` | string | 否 | 结束日往前 6 天 | 开始日期 `Y-m-d` |
| `end_time` | string | 否 | 今天 | 结束日期 `Y-m-d`，≥ start_time |

**请求示例**

```http
GET /admin/online/newUserSummary?start_time=2026-08-01&end_time=2026-08-05
```

**返回 `data`**

| 字段 | 类型 | 说明 |
|------|------|------|
| `start_time` | string | 实际查询开始日 |
| `end_time` | string | 实际查询结束日 |
| `rules` | object | 规则文案 |
| `rules.active_member` | string | 活跃会员说明 |
| `rules.valid_member` | string | 有效会员说明 |
| `data` | array | 按天列表（含区间内无数据的日期，值为 0） |

**`data[]` 列表项**

| 字段 | 类型 | 前端列名 | 说明 |
|------|------|----------|------|
| `date` | string | 时间 | 日期 `Y-m-d` |
| `h5_register` | int | H5注册 | |
| `app_register` | int | APP注册 | |
| `h5_first_deposit` | int | H5首存次数 | |
| `app_first_deposit` | int | APP首存次数 | |
| `active_member` | int | 活跃会员 | |
| `deposit_total` | number | 存款总额 | |
| `bet_total` | number | 下注总数 | |
| `company_profit` | number | 公司盈利 | 投注 − 派奖 |
| `valid_member` | int | 有效会员 | |

**返回示例**

```json
{
  "code": 0,
  "data": {
    "start_time": "2026-08-01",
    "end_time": "2026-08-05",
    "rules": {
      "active_member": "新注册会员当日下注>=¥50",
      "valid_member": "新注册会员当日存款>=¥50"
    },
    "data": [
      {
        "date": "2026-08-01",
        "h5_register": 45,
        "app_register": 32,
        "h5_first_deposit": 28,
        "app_first_deposit": 20,
        "active_member": 35,
        "deposit_total": 28500,
        "bet_total": 156000,
        "company_profit": 8200,
        "valid_member": 30
      }
    ]
  }
}
```

---

## 二、注册/域名统计（菜单 uri：`registerDomain`）

前端两个 Tab 对应两个接口（**后端无 tab 参数**）。

| 前端 Tab | 建议 tab 值（前端自用） | 接口 |
|----------|-------------------------|------|
| 走势图 | `trend` | `GET /admin/user/registerTrend` |
| 域名统计 | `domain` | `GET /admin/user/registerDomain` |

---

### 2.1 会员注册走势图

**URL**

```http
GET /admin/user/registerTrend
```

**说明**

- `type=today`：按**小时**统计指定日（默认今天）注册量  
- `type=all`：按**天**统计区间内注册量  

两条序列：

- **正式会员**：`from != 2`  
- **虚拟会员**：`from = 2`（游客等）

**请求参数（Query）**

| 参数 | 类型 | 必填 | 默认 | 说明 |
|------|------|------|------|------|
| `type` | string | 否 | `today` | `today`：按小时；`all`：按天 |
| `start_time` | string | 否 | 今天 | `Y-m-d`。`today` 时表示统计哪一天；`all` 时为区间起点 |
| `end_time` | string | 否 | 今天 | `Y-m-d`，仅 `type=all` 时有效，须 ≥ start_time |

**请求示例**

```http
# 今日（按小时）
GET /admin/user/registerTrend?type=today

# 指定日按小时
GET /admin/user/registerTrend?type=today&start_time=2026-08-04

# 区间按天
GET /admin/user/registerTrend?type=all&start_time=2026-08-01&end_time=2026-08-05
```

**返回 `data`（type=today）**

| 字段 | 类型 | 说明 |
|------|------|------|
| `type` | string | `today` |
| `date` | string | 统计日 |
| `times` | string[] | 时间轴，`00:00`～`23:00` 共 24 点 |
| `member` | int[] | 与 times 对齐的正式会员新增 |
| `virtual` | int[] | 与 times 对齐的虚拟会员新增 |
| `member_total` | int | 当日正式会员合计 |
| `virtual_total` | int | 当日虚拟会员合计 |

**返回 `data`（type=all）**

| 字段 | 类型 | 说明 |
|------|------|------|
| `type` | string | `all` |
| `start_time` | string | 区间开始 |
| `end_time` | string | 区间结束 |
| `times` | string[] | 日期轴 `Y-m-d` |
| `member` | int[] | 正式会员每日新增 |
| `virtual` | int[] | 虚拟会员每日新增 |
| `member_total` | int | 区间正式会员合计 |
| `virtual_total` | int | 区间虚拟会员合计 |

**返回示例（今日）**

```json
{
  "code": 0,
  "data": {
    "type": "today",
    "date": "2026-08-05",
    "times": ["00:00", "01:00", "02:00"],
    "member": [3, 1, 0],
    "virtual": [0, 0, 1],
    "member_total": 120,
    "virtual_total": 30
  }
}
```

前端图表：

- X 轴：`times`  
- 系列「今日会员新增」：`member`  
- 系列「今日虚拟会员新增」：`virtual`  

---

### 2.2 注册域名统计

**URL**

```http
GET /admin/user/registerDomain
```

**说明**

按注册时写入的 `register_domain`（Referer/Origin 主机）聚合**注册人数**（不是登录人数）。  
空域名归为「未知」。

**请求参数（Query）**

| 参数 | 类型 | 必填 | 默认 | 说明 |
|------|------|------|------|------|
| `start_time` | string | 否 | - | 注册开始日 `Y-m-d` 00:00:00 |
| `end_time` | string | 否 | - | 注册结束日 `Y-m-d` 23:59:59 |
| `page` | int | 否 | `1` | 页码 |
| `limit` | int | 否 | `50` | 每页条数，1～200 |

**请求示例**

```http
GET /admin/user/registerDomain?start_time=2026-07-06&end_time=2026-08-04&page=1&limit=50
```

**返回 `data`**

| 字段 | 类型 | 说明 |
|------|------|------|
| `total` | int | 域名分组总数 |
| `data` | array | 当前页列表，按注册人数降序 |

**`data[]` 列表项**

| 字段 | 类型 | 前端列名 | 说明 |
|------|------|----------|------|
| `register_url` | string | 注册网址 | 域名主机；空为「未知」 |
| `register_count` | int | 注册人数 | 该域名下注册用户数 |

**返回示例**

```json
{
  "code": 0,
  "data": {
    "total": 6,
    "data": [
      { "register_url": "www.example.com", "register_count": 156 },
      { "register_url": "com.example.app", "register_count": 89 },
      { "register_url": "未知", "register_count": 12 }
    ]
  }
}
```

---

## 三、前端 Tab 与接口对照（汇总）

### 在线汇总页 `onlineSummary`

| tab（前端） | 文案 | Method | Path |
|-------------|------|--------|------|
| `online` | 在线用户 | GET | `/admin/online/users` |
| `newUser` | 新用户汇总 | GET | `/admin/online/newUserSummary` |
| - | 平台在线人数（角标可轮询） | GET | `/admin/online/platformCount` |

### 注册/域名统计页 `registerDomain`

| tab（前端） | 文案 | Method | Path |
|-------------|------|--------|------|
| `trend` | 走势图 | GET | `/admin/user/registerTrend` |
| `domain` | 域名统计 | GET | `/admin/user/registerDomain` |

> 说明：`tab` 仅建议前端路由/状态使用，**后端接口不接收、也不校验 `tab` 参数**。

---

## 四、数据依赖说明（联调注意）

| 数据 | 来源 | 说明 |
|------|------|------|
| 登录 IP / 浏览器 / 系统 / 平台 / 登录网站 / 位置 | 登录时写入 `user_login` | 需 melbet `ClientPlatformDetector` 已发布；历史 platform 可能为空或旧口径 |
| 平台（platform） | 写入一次：`Sec-CH-UA-Platform` + 包名域；读侧只映射 | `PC` / `iOS` / `Android` / `H5` / `WeChat` / 空 |
| 注册域名 | 注册时写入 `users.register_domain` | 来自 Referer/Origin；历史用户多为「未知」 |
| 在线状态 | `user_session` + `last_active_time` | 以有效 session 为主，30 分钟活跃为辅 |
| 首存 / 下注 / 存款 | `balance_logs` | 依赖 `change_type` 文案匹配（充值/投注/中奖等） |

---

## 五、菜单与权限 uri

| 菜单 | 前端 uri | 按钮/接口权限 uri |
|------|----------|-------------------|
| 在线汇总 | `onlineSummary` | `admin/online/users`、`admin/online/newUserSummary`、`admin/online/platformCount`（无菜单按钮时默认放行） |
| 注册/域名统计 | `registerDomain` | `admin/user/registerTrend`、`admin/user/registerDomain` |
