feat(platform): 首页门面三统计 + 运营后台展示模式配置
- 新表 platform_stat_display:每个指标可选 real/manual/random 三种 展示模式,含建表 + anchor_minutes 两个 alembic migration - 公开接口 GET /api/v1/platform/stats(无鉴权门面数字,登录前可读) - 运营后台 GET/PATCH /admin/api/dashboard-display 配置展示模式 - 配套 model/repository/schema,注册 router(app/main+admin/main), 导出 model,补 docs(api/database 索引及 3 篇详情) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,8 @@
|
||||
| 37 | `DELETE /api/v1/user` | Bearer | [详情](./user-delete.md) |
|
||||
| **帮助与反馈**(前缀 `/api/v1/feedback`) |||
|
||||
| 38 | `POST /api/v1/feedback` | Bearer | [详情](./feedback.md) |
|
||||
| **首页门面数据**(前缀 `/api/v1/platform`;全平台展示数字,登录前可读) |||
|
||||
| 39 | `GET /api/v1/platform/stats` | 无 | [详情](./platform-stats.md) |
|
||||
| **静态资源**(StaticFiles 挂载,见下方 `/media` 静态服务) |||
|
||||
| - | `GET /media/avatars/<file>` | 无 | 用户头像;返回二进制图片 |
|
||||
| - | `GET /media/feedback/<file>` | 无 | 反馈截图;返回二进制图片 |
|
||||
@@ -88,6 +90,8 @@
|
||||
| A16 | `POST /admin/api/admins` | super_admin | [详情](./admin-admin-create.md) |
|
||||
| A17 | `PATCH /admin/api/admins/{admin_id}` | super_admin | [详情](./admin-admin-update.md) |
|
||||
| A18 | `GET /admin/api/audit-logs` | admin | [详情](./admin-audit-logs.md) |
|
||||
| A19 | `GET /admin/api/dashboard-display` | admin | [详情](./admin-dashboard-display.md) |
|
||||
| A20 | `PATCH /admin/api/dashboard-display/{metric}` | operator | [详情](./admin-dashboard-display.md) |
|
||||
| - | `GET /admin/api/health` | 无 | admin 健康检查(无单独文档) |
|
||||
|
||||
> ⚠️ 美团三个接口当前**无鉴权**,且 `referral-link` 的 `sid` 允许客户端传值覆盖默认渠道——见各接口"备注"。
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Admin 首页数据配置 — 三统计展示模式
|
||||
|
||||
> 所属:Admin 组(前缀 `/admin/api/dashboard-display`) | 鉴权:Admin Bearer(改需 operator/super) | [← 返回 API 索引](./README.md)
|
||||
|
||||
配置客户端首页三个门面数字(帮助用户 / 完成比价 / 累计节省)的展示模式。每个指标可独立选 real/manual/random。用户侧读取见 [platform-stats](./platform-stats.md);表见 [platform_stat_display](../database/platform_stat_display.md)。
|
||||
|
||||
> **单位约定**:倍率用**千分比整数**(1.000→`1000`、1.100→`1100`)。`total_saved` 的 `manual_value` / `random_current` / `random_initial` 单位是**分**(前端展示时 ÷100 取元)。
|
||||
|
||||
---
|
||||
|
||||
## GET /admin/api/dashboard-display — 三指标配置 + 真实值预览
|
||||
|
||||
### 出参
|
||||
响应 `200`:`list[PlatformStatItemOut]`(按 help_users / total_compares / total_saved 顺序)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `metric` | string | `help_users` / `total_compares` / `total_saved` |
|
||||
| `label` | string | 帮助用户 / 完成比价 / 累计节省 |
|
||||
| `unit` | string | 人 / 次 / 分 |
|
||||
| `mode` | string | `real` / `manual` / `random` |
|
||||
| `manual_value` | int \| null | manual 固定值(基础单位) |
|
||||
| `random_mult_min` | int | 倍率下限(千分比,≥1000) |
|
||||
| `random_mult_max` | int | 倍率上限(千分比) |
|
||||
| `random_tick_seconds` | int | 更新间隔(秒,默认 86400=1 天) |
|
||||
| `random_anchor_minutes` | int | 触发时刻对齐偏移(距北京 0 点分钟数:天=每日时刻、小时=每小时第几分、分钟=0) |
|
||||
| `random_current` | int \| null | random 当前累积值(基础单位) |
|
||||
| `random_last_tick_at` | string \| null | 上次 tick 时刻(ISO) |
|
||||
| `real_value` | int | 当前真实值(给运营对比参考,基础单位) |
|
||||
| `updated_at` | string \| null | 上次修改时间 |
|
||||
|
||||
---
|
||||
|
||||
## PATCH /admin/api/dashboard-display/{metric} — 改某指标(带审计)
|
||||
|
||||
`metric` 路径参数取 `help_users` / `total_compares` / `total_saved`。
|
||||
|
||||
### 入参 `PlatformStatUpdateRequest`(字段均可选,只改传了的)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `mode` | string | `real` / `manual` / `random` |
|
||||
| `manual_value` | int | manual 固定值(基础单位,≥0) |
|
||||
| `random_mult_min` | int | 倍率下限(千分比,1000~5000) |
|
||||
| `random_mult_max` | int | 倍率上限(千分比,≥下限) |
|
||||
| `random_tick_seconds` | int | 更新间隔(秒,≥60) |
|
||||
| `random_anchor_minutes` | int | 触发时刻对齐偏移(分钟,需 `*60 < 更新间隔`) |
|
||||
| `random_initial` | int | 切 random 的初始基数(基础单位);**留空则用当前真实值播种** |
|
||||
|
||||
### 出参
|
||||
响应 `200`:更新后的 `PlatformStatItemOut`(同上)。
|
||||
|
||||
### 错误
|
||||
- `400`:mode 非法 / 倍率越界(<1000 或 >5000)/ 上限<下限 / tick<60 / 负值。
|
||||
- `403`:角色不足(需 operator 或 super_admin)。
|
||||
- `404`:无效 metric(不在三指标内,作为 400 文案返回)。
|
||||
|
||||
### 说明
|
||||
- **统一定时刷新**:三模式的展示值(`random_current`)只在「更新时间(按更新间隔)」对齐的北京钟点刷新一次——real 快照查库 / manual 取固定值 / random ×倍率。`random_tick_seconds`+`random_anchor_minutes` 三模式通用。
|
||||
- 改 mode/manual/倍率等到**下个更新钟点**才在客户端生效(展示值不立即变);`random_initial` 例外:立即设为该值并重置(自增长设起点)。首次无展示值时按当前模式播种。
|
||||
- 每次改动写 `admin_audit_log`(action=`dashboard_display.set`,detail 含改前/改后快照)。
|
||||
- 客户端在**进首页 / 回前台时**重拉 `/stats` 取最新展示值。
|
||||
@@ -0,0 +1,27 @@
|
||||
# GET /api/v1/platform/stats — 首页三统计(全平台门面数字)
|
||||
|
||||
> 所属:Platform 组(前缀 `/api/v1/platform`) | 鉴权:**无**(登录前首页也要展示) | [← 返回 API 索引](./README.md)
|
||||
|
||||
客户端首页顶部「帮助用户 / 完成比价 / 累计节省」三个平台级数字。每个指标的展示模式由运营后台配(见 [admin-dashboard-display](./admin-dashboard-display.md)),本接口只返回算好的结果值。
|
||||
|
||||
## 入参
|
||||
无。
|
||||
|
||||
## 出参
|
||||
响应 `200`:`PlatformStatsOut`
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|---|---|---|
|
||||
| `help_users` | int | 帮助用户(人) |
|
||||
| `total_compares` | int | 完成比价(次) |
|
||||
| `total_saved_cents` | int | 累计节省(**分**),客户端 ÷100 显示「元」 |
|
||||
|
||||
## 说明
|
||||
三指标各自独立选模式,且**统一「定时刷新」**:客户端看到的展示值只在「更新时间(按更新间隔)」对齐的北京钟点(`anchor + k*间隔`)刷新一次,平时不变。每次刷新按模式算新值:
|
||||
- **real**:重新快照查库。`help_users`=有过 `status='success'` 比价记录的去重用户数;`total_compares`=成功比价记录数;`total_saved_cents`=成功记录 `saved_amount_cents` 求和。
|
||||
- **manual**:取运营当前手填的固定值(改值到下个更新钟点生效)。
|
||||
- **random**:在上次展示值上 ×一个 [min,max](≥1.0)的随机倍率,只增不减(跨几个钟点乘几次)。
|
||||
|
||||
计算逻辑见 `app/repositories/platform_stat.py`,模型见 `app/models/platform_stat.py`(表 [platform_stat_display](../database/platform_stat_display.md))。
|
||||
|
||||
上线初始播种为 manual + 客户端原写死门面值(12847 / 86532 / 37621.40 元),保证前后展示一致。
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
---
|
||||
|
||||
## 表总览(19 张业务表 + `alembic_version` 框架表)
|
||||
## 表总览(20 张业务表 + `alembic_version` 框架表)
|
||||
|
||||
### 账号 / 反馈
|
||||
| 表 | 用途 | 模型 | 文档 |
|
||||
@@ -39,6 +39,11 @@
|
||||
| `savings_record` | 省钱记录(profile 省钱战绩源;真实下单归因 + demo) | `models/savings.py` | [详情](./savings_record.md) |
|
||||
| `price_report` | 上报更低价(众包纠偏,人工审核发奖) | `models/price_report.py` | [详情](./price_report.md) |
|
||||
|
||||
### 首页门面数据
|
||||
| 表 | 用途 | 模型 | 文档 |
|
||||
|---|---|---|---|
|
||||
| `platform_stat_display` | 首页三统计展示配置(real/manual/random) | `models/platform_stat.py` | [详情](./platform_stat_display.md) |
|
||||
|
||||
### 运营后台 admin(独立子应用 `app/admin/`,独立鉴权)
|
||||
| 表 | 用途 | 模型 | 文档 |
|
||||
|---|---|---|---|
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# platform_stat_display — 首页三统计展示配置
|
||||
|
||||
> 模型 `app/models/platform_stat.py` | 关联接口 [platform-stats](../api/platform-stats.md) / [admin-dashboard-display](../api/admin-dashboard-display.md) | [← 表索引](./README.md)
|
||||
|
||||
客户端首页三个门面数字(帮助用户 / 完成比价 / 累计节省)的展示配置。一行一指标(主键=`metric`),每指标可独立选 real/manual/random 三种模式。计算逻辑见 `app/repositories/platform_stat.py`。
|
||||
|
||||
> **单位**:倍率用**千分比整数**(1.000→`1000`);`total_saved` 指标的 `manual_value` / `random_current` 单位是**分**,两个计数指标是**个数**。
|
||||
|
||||
## 字段
|
||||
| 列 | 类型 | 约束 / 默认 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `metric` | String(32) | PK | `help_users` / `total_compares` / `total_saved` |
|
||||
| `mode` | String(16) | NOT NULL, default `real` | `real` 查库 / `manual` 手填 / `random` 随机增长 |
|
||||
| `manual_value` | Integer | nullable | manual 模式固定值(基础单位) |
|
||||
| `random_mult_min` | Integer | NOT NULL, default 1000 | 倍率下限(千分比,≥1000 保证只增不减) |
|
||||
| `random_mult_max` | Integer | NOT NULL, default 1100 | 倍率上限(千分比) |
|
||||
| `random_tick_seconds` | Integer | NOT NULL, default 86400 | 更新间隔(秒) |
|
||||
| `random_anchor_minutes` | Integer | NOT NULL, default 0 | 触发时刻对齐偏移(距北京 0 点分钟数):天=每日时刻 h*60+m、小时=每小时第几分、分钟=0 |
|
||||
| `random_current` | Integer | nullable | random 当前累积值(基础单位);惰性 tick 改写 |
|
||||
| `random_last_tick_at` | DateTime(tz) | nullable | 上次 tick 时刻 |
|
||||
| `updated_by_admin_id` | Integer | nullable | 最后修改的管理员 |
|
||||
| `updated_at` | DateTime(tz) | server_default now(), onupdate now() | 更新时间 |
|
||||
|
||||
## 初始数据(migration 播种)
|
||||
三行,默认 `mode='manual'` + 客户端原写死门面值,保证上线前后展示一致:
|
||||
|
||||
| metric | manual_value | 含义 |
|
||||
|---|---|---|
|
||||
| `help_users` | 12847 | 12847 人 |
|
||||
| `total_compares` | 86532 | 86532 次 |
|
||||
| `total_saved` | 3762140 | 37621.40 元 |
|
||||
|
||||
## 统一「定时刷新」(北京钟点对齐)
|
||||
`random_current` 现是**所有模式**的「当前展示值」(不止 random),用户侧 `/stats` 直接返回它。
|
||||
- 触发边界 = 北京时间 `anchor + k*interval`(interval=`random_tick_seconds`,anchor=`random_anchor_minutes*60`,sub-day 间隔取 `anchor % interval` 作相位)。例:每天 09:00 / 每小时 :30 / 每 5 分刻度。
|
||||
- 读取(`get_display_values`/`get_config`)时跑 `_refresh`:统计 `random_last_tick_at`→`now` 跨过几个边界 N,N≥1 才刷新:
|
||||
- **real** → `random_current` = 重新查库的真实值(跨多少边界都只取最新)。
|
||||
- **manual** → `random_current` = 当前 `manual_value`。
|
||||
- **random** → `random_current` 连乘 N 次随机倍率(`randint(min,max)/1000`,恒 ≥1.0 只增不减)。
|
||||
- 用边界索引比较,`random_last_tick_at` 直接记 `now`,不重复计。
|
||||
- ⚠️ **接受刷新时刻的微小并发竞态**(不加行锁):纯门面数字,无业务后果。
|
||||
- `random_current` 首次为空时按当前模式播种(`update_config` 或 `_refresh` 兜底);`random_initial` 可立即设起点。
|
||||
|
||||
## 说明
|
||||
- real 口径仅统计 `comparison_record` 中 `status='success'` 的记录(去重用户数 / 记录数 / `saved_amount_cents` 求和)。
|
||||
- 改配置走 admin `PATCH /admin/api/dashboard-display/{metric}`,带审计。
|
||||
Reference in New Issue
Block a user