Ver código fonte

设计文档:按用户调整中转站映射口径,新增token统计导出接口

lh 1 mês atrás
pai
commit
496b6b129c

+ 75 - 39
docs/superpowers/specs/2026-08-19-points-usage-stats-design.md

@@ -28,28 +28,28 @@
 
 用途:维护模型名与中转站的对应关系,统计任务按模型名关联出中转站。
 
-| 字段 | 类型 | 说明 |
-|---|---|---|
-| id | bigint unsigned PK AI | |
-| model | varchar(255) NOT NULL UNIQUE | 模型名 |
-| relay_name | varchar(100) NOT NULL | 中转站名称 |
-| remark | varchar(255) NULL | 备注 |
-| created_at / updated_at | timestamp | |
+| 字段                    | 类型                         | 说明       |
+| ----------------------- | ---------------------------- | ---------- |
+| id                      | bigint unsigned PK AI        |            |
+| model                   | varchar(255) NOT NULL UNIQUE | 模型名     |
+| relay_name              | varchar(100) NOT NULL        | 中转站名称 |
+| remark                  | varchar(255) NULL            | 备注       |
+| created_at / updated_at | timestamp                    |            |
 
 migration 中初始化以下映射(智能分析所得,后续可人工增改):
 
-| 模型 | 中转站 |
-|---|---|
-| deepseek-chat / deepseek-reasoner / deepseek-v4-flash / deepseek-v4-pro | DeepSeek 官方 |
-| deepseek-v3-2-251201 | 火山方舟 |
-| doubao-seed-2-0-mini/lite/pro-260215 | 火山方舟 |
-| doubao-seedream-4-5-251128 / doubao-seedream-5-0-260128 / doubao-seedream-5-0-lite-260128 | 火山方舟 |
-| doubao-seedance-1-5-pro-251215 / doubao-seedance-2-0-260128 / doubao-seedance-2-0-fast-260128 | 火山方舟 |
-| doubao-seedance-2.0 | 百度 |
-| zhizhen-20 / zhizhen-20-fast / zhizhen-20-mini | 智帧 |
-| gpt-5.4 / gpt-5.6-terra / gpt-5.6-sol / gpt-5.6-luna / gpt-image-2 / GptImage2 | GPT 中转站 |
-| gemini-3-pro-preview / gemini-3-flash-preview / gemini-3.1-pro-preview / gemini-3.1-flash-image-preview-t / gemini-3.6-flash | Gemini 中转站 |
-| NanoBanana2 / NanoBananaPro | NanoBanana |
+| 模型                                                                                                                         | 中转站        |
+| ---------------------------------------------------------------------------------------------------------------------------- | ------------- |
+| deepseek-chat / deepseek-reasoner / deepseek-v4-flash / deepseek-v4-pro                                                      | DeepSeek 官方 |
+| deepseek-v3-2-251201                                                                                                         | 火山方舟      |
+| doubao-seed-2-0-mini/lite/pro-260215                                                                                         | 火山方舟      |
+| doubao-seedream-4-5-251128 / doubao-seedream-5-0-260128 / doubao-seedream-5-0-lite-260128                                    | 火山方舟      |
+| doubao-seedance-1-5-pro-251215 / doubao-seedance-2-0-260128 / doubao-seedance-2-0-fast-260128                                | 火山方舟      |
+| doubao-seedance-2.0                                                                                                          | 百度          |
+| zhizhen-20 / zhizhen-20-fast / zhizhen-20-mini                                                                               | 智帧          |
+| gpt-5.4 / gpt-5.6-terra / gpt-5.6-sol / gpt-5.6-luna / gpt-image-2 / GptImage2                                               | 快快AI        |
+| gemini-3-pro-preview / gemini-3-flash-preview / gemini-3.1-pro-preview / gemini-3.1-flash-image-preview-t / gemini-3.6-flash | 快快AI        |
+| NanoBanana2 / NanoBananaPro                                                                                                  | 速创API       |
 
 未命中映射的模型在统计中归为 `unknown`。
 
@@ -57,18 +57,18 @@ migration 中初始化以下映射(智能分析所得,后续可人工增改
 
 用途:按 `(stat_date, uid, model, relay)` 维度预聚合的日粒度统计。
 
-| 字段 | 类型 | 说明 |
-|---|---|---|
-| id | bigint unsigned PK AI | |
-| stat_date | date NOT NULL | 统计日期(按明细 created_at 归属) |
-| uid | bigint unsigned NOT NULL | 用户 ID |
-| cpid | bigint NOT NULL DEFAULT 0 | 用户所属组织(组织管理员过滤用) |
-| model | varchar(255) NOT NULL | 模型名 |
-| relay | varchar(100) NOT NULL DEFAULT 'unknown' | 中转站名称 |
-| call_count | int unsigned NOT NULL DEFAULT 0 | 调用次数 |
-| tokens_consumed | bigint NOT NULL DEFAULT 0 | token 消耗合计(核心指标) |
-| points_consumed | decimal(13,1) NOT NULL DEFAULT 0 | 积分消耗合计(附带指标) |
-| created_at / updated_at | timestamp | |
+| 字段                    | 类型                                    | 说明                               |
+| ----------------------- | --------------------------------------- | ---------------------------------- |
+| id                      | bigint unsigned PK AI                   |                                    |
+| stat_date               | date NOT NULL                           | 统计日期(按明细 created_at 归属) |
+| uid                     | bigint unsigned NOT NULL                | 用户 ID                            |
+| cpid                    | bigint NOT NULL DEFAULT 0               | 用户所属组织(组织管理员过滤用)   |
+| model                   | varchar(255) NOT NULL                   | 模型名                             |
+| relay                   | varchar(100) NOT NULL DEFAULT 'unknown' | 中转站名称                         |
+| call_count              | int unsigned NOT NULL DEFAULT 0         | 调用次数                           |
+| tokens_consumed         | bigint NOT NULL DEFAULT 0               | token 消耗合计(核心指标)         |
+| points_consumed         | decimal(13,1) NOT NULL DEFAULT 0        | 积分消耗合计(附带指标)           |
+| created_at / updated_at | timestamp                               |                                    |
 
 索引:
 
@@ -111,14 +111,14 @@ migration 中初始化以下映射(智能分析所得,后续可人工增改
 
 请求参数:
 
-| 参数 | 必填 | 说明 |
-|---|---|---|
-| start_date / end_date | 否 | 日期范围,默认近 30 天 |
-| uid | 否 | 用户 ID,支持逗号分隔多个 |
-| model | 否 | 模型名 |
-| relay | 否 | 中转站名称 |
-| group_by | 否 | 聚合维度,`date/uid/model/relay` 任意组合(如 `date,model`),默认四维全部分组 |
-| page / page_size | 否 | 分页,默认 15,最大 100 |
+| 参数                  | 必填 | 说明                                                                               |
+| --------------------- | ---- | ---------------------------------------------------------------------------------- |
+| start_date / end_date | 否   | 日期范围,默认近 30 天                                                             |
+| uid                   | 否   | 用户 ID,支持逗号分隔多个                                                          |
+| model                 | 否   | 模型名                                                                             |
+| relay                 | 否   | 中转站名称                                                                         |
+| group_by              | 否   | 聚合维度,`date/uid/model/relay` 任意组合(如 `date,model`),默认四维全部分组 |
+| page / page_size      | 否   | 分页,默认 15,最大 100                                                            |
 
 响应(沿用现有 ApiResponse 风格):
 
@@ -162,6 +162,39 @@ migration 中初始化以下映射(智能分析所得,后续可人工增改
 - 中转站列表
 - 可统计日期范围(最早/最晚 stat_date)
 
+### 3. 导出统计 `GET /api/points/stats/export`
+
+导出当前筛选条件下的 token 统计为 CSV 文件,筛选条件与列表接口完全一致。
+
+权限:
+
+- 与列表接口一致:`superadmin` 全量,`admin` 限定本组织,其他角色拒绝。
+
+请求参数(与列表一致,无分页参数):
+
+| 参数 | 必填 | 说明 |
+|---|---|---|
+| start_date / end_date | 否 | 日期范围,默认近 30 天 |
+| uid | 否 | 用户 ID,支持逗号分隔多个 |
+| model | 否 | 模型名 |
+| relay | 否 | 中转站名称 |
+| group_by | 否 | 聚合维度,`date/uid/model/relay` 任意组合,默认四维全部分组 |
+
+输出:
+
+- 复用 `exportCsv` 辅助函数,UTF-8 编码 CSV。
+- 文件名:`points_stats_YYYYMMDD_YYYYMMDD.csv`(按所选日期范围,未指定则为近 30 天范围)。
+- 列结构随 `group_by` 动态变化:先输出选中的维度列(日期/用户ID/用户昵称或账号/模型/中转站),再输出指标列(调用次数、token 消耗、积分消耗);最后追加一行合计(维度列为空,指标列为当前筛选条件下汇总值)。
+
+示例(按 `date,model` 分组):
+
+```csv
+统计日期,模型,调用次数,token消耗,积分消耗
+2026-08-18,zhizhen-20,10,1309900,840.0
+2026-08-18,gpt-5.4,5,120000,50.0
+合计,,,,1429900,890.0
+```
+
 ## 目录与文件规划
 
 - `database/migrations/xxxx_create_mp_model_relay_map_table.php`
@@ -172,9 +205,12 @@ migration 中初始化以下映射(智能分析所得,后续可人工增改
 - `app/Transformer/Points/PointsStatsTransformer.php`(如有需要)
 - `routes/api.php` 新增路由
 
+导出接口复用 `app/Libs/Helpers.php` 中的 `exportCsv()`,不新增第三方依赖。
+
 ## 测试计划
 
 - 定时任务:手动执行 `--date` 统计结果与明细表 SQL 对账一致。
 - 权限:superadmin 可见全部、admin 仅本组织、其他角色拒绝。
 - 筛选:日期、用户、模型、中转站、group_by 组合。
+- 导出:与列表相同筛选条件下,CSV 行数与列表汇总一致,合计行正确。
 - 幂等:重复执行同一日期统计不产生脏数据。