# analytics_event — 客户端埋点事件流 > 模型 `app/models/analytics_event.py` · 仓库 `app/repositories/analytics.py` · 接口 C 端 `POST /api/v1/analytics/events`([analytics-events](../api/other/analytics-events.md),批量,不强制登录);admin `GET /admin/api/event-logs`(`app/admin/routers/event_logs.py`) · [← 索引](./README.md) · [总览](./OVERVIEW.md) 客户端行为埋点的落地表,**一事件一行**(append-only)。客户端攒批上报(每批 ≤200 条),服务端展开逐条插入;`props` 装事件自带的任意维度。当前主要供 admin「埋点日志」检索与手工分析,无自动聚合任务。#83 新增(2026-06-27)。 ## 用在哪 / 增删改查 - **C(插入)**:`POST /api/v1/analytics/events`(不强制登录:带 JWT 则记 `user_id`,匿名只记 `device_id`)。服务端补 `client_ip`。 - **U / D**:无。只追加。 - **R**:admin `GET /admin/api/event-logs`(游标分页,可按 `event`/`device_id`/`user_id` 筛)。 ## 字段 | 列 | 类型 | 约束 / 默认 | 说明 | |---|---|---|---| | `id` | Integer | PK, autoincrement | | | `event` | String(64) | index, NOT NULL | 事件名(客户端约定,如页面曝光/点击类事件名) | | `props` | JSON | nullable | 事件属性(任意维度,客户端原样传) | | `device_id` | String(64) | index, NOT NULL | 客户端 per-install id(匿名也有) | | `user_id` | Integer | index, nullable | 登录态才有。**无硬 FK** | | `session_id` | String(64) | index, nullable | 客户端会话 id(一次冷启动一个) | | `client_ts` | BigInteger | NOT NULL | 事件发生时间(客户端 epoch ms) | | `sent_at` | BigInteger | nullable | 客户端上报时间(epoch ms);与 `client_ts` 差 = 攒批延迟 | | `page` | String(64) | nullable | 事件所在页面 | | `client_ip` | String(64) | nullable | 服务端从请求头取 | | `oem` / `os` / `model` | String | nullable | 厂商 / 系统版本 / 机型 | | `app_ver` | String(32) | nullable | App versionName | | `network` | String(16) | nullable | 网络类型(wifi/cellular) | | `channel` | String(32) | nullable | 分发渠道 | | `created_at` | DateTime(tz) | server_default now() | 入库时间 | ## 关系 / Join Key - `user_id` 软指 `user.id`、`device_id` 与其他表的 per-install id 同源——均无硬 FK(埋点不鉴权、匿名也收,不能被外键约束卡住)。 ## 索引与约束 - PK `id`;index `event`、`device_id`、`user_id`、`session_id`。 ## 注意 - 每批最多 200 条,超出整批 422;单条字段超长按模型截断口径处理。 - 时间轴分析用 `client_ts`(事件真实发生时刻),`created_at` 只是入库时刻(受攒批影响)。