v0.0.17 — 管理员运营仪表盘与图表数据统一重构
为管理员引入全新的「数据」运营仪表盘:全站 KPI(用户/资源/营收/配额/收入)+ 7 日请求量/额度/Token 三张趋势折线 + 模型用量分布堆叠柱图 + 使用明细表 + 活跃用户排行榜;图表数据统一由
/api/admin/dashboard/charts一份接口驱动,结构与/api/user/dashboard完全一致([]LogStatistic),方便前后端共享聚合逻辑。同时修复/api/*未匹配路由误返回 OpenAI 风格错误的问题。
中文
✨ 新增功能
后端(Go)
- 新增管理员仪表盘聚合层(
model/admin_dashboard.go,issue #15):GetAdminDashboardOverview(rawRange):一次性聚合 KPI — 用户(总数/今日新增/7 日/30 日/活跃/禁用/已删/今日占比)、资源(令牌/渠道/套餐/兑换码/订阅 各自总数 + 启用/活跃)、配额(今日/7 日/30 日/总)、收入(总营收/充值/订阅/退款),6 段聚合单次往返,每段单条 SQL 避免 N+1。GetAdminTopUsers(rawRange, limit):活跃用户排行榜(近 range 内有 consume 日志 +request_count > 0,按请求数 desc、quota desc 排序),一次性WHERE IN批量补齐当前套餐名(batchTopActivePlanNames)。GetAdminModelDistribution(rawRange, topN)+AdminModelDistribution:全站按 quota 降序的 Top N 模型 + 7 日 day 序列,供堆叠柱图渲染(此接口随后被/charts取代,详见 🔧 重构)。GetAdminUsageDetails(rawRange, topN)+AdminUsageDetails:Top N 模型 × 每日的「透视前」明细行,供「使用明细」表渲染(此接口随后被/charts取代)。ParseAdminDashboardRange/ParseAdminChartsRange:统一的range预设解析(today/7d/30d/all),后者输出 day 对齐的窗口(all收敛为近 30 天避免全量响应过大)。SearchAdminLogsByDayAndModel(start, end):全站day × model聚合,结构与model.SearchLogsByDayAndModel(api/user/dashboard用)完全一致,但不过滤user_id;前端可直接复用同一套图表构建逻辑。
- 新增
/api/admin/dashboard/charts接口(controller/admin/dashboard.go::GetCharts,router/api.go,AdminAuth):- 返回
[]*model.LogStatistic,字段Day / ModelName / RequestCount / Quota / PromptTokens / CompletionTokens,与/api/user/dashboard完全一致。 - 一份数据驱动前端全部图表:请求量/额度/Token 三张折线 + 模型分布堆叠柱 + 使用明细表。
- 返回
- 运营仪表盘配套测试(
model/admin_dashboard_test.go):TestParseAdminDashboardRange:覆盖 4 种 range 边界。TestParseAdminChartsRange:验证 day 对齐窗口与天数。TestGetAdminDashboardOverview_Smoke:覆盖 6 段聚合与 active_7d。TestGetAdminTopUsers:覆盖request_count > 0过滤 + 排序 + 套餐名嵌入。TestSearchAdminLogsByDayAndModel:覆盖[]LogStatistic结构 + 多用户合并 + 字段齐全。- 早期
TestGetAdminModelDistribution/TestGetAdminUsageDetails随 API 重构移除。
前端(web/default-pro/)
- 新增管理员仪表盘页面
views/admin/AdminDashboard.vue(issue #15):- 顶部欢迎条:标题「运营数据」+ 副标题「全站 KPI · 趋势 · 排行 — YYYY-MM-DD」+ 右侧 range 单选(今日/7 日/30 日/全部)+ 最后刷新时间 + 刷新按钮。
- 左侧 16/24 主栏(6 个 panel):
- 用户 KPI:8 张统计卡(总用户/今日新增/7 日/30 日/7 日活跃/禁用/已删/今日占比),带 arco icon + 调色板。
- 营收:总营收/充值/订阅/退款 4 张卡(带「营收」脚注),移至资源上方。
- 资源 / 用量:令牌/渠道/套餐(→/setting/plan)/兑换码(→/redemption)/订阅 5 张可点击卡。
- Token / 请求消耗 + 三张折线:4 张配额卡 + 分隔条 + 请求量/额度/Token 三张 160px 折线图(vue-echarts),样式与仪表盘一致。
- 模型分布(近 7 日):独立全宽 panel,堆叠柱图(Top 8 模型 × 7 天),legend 底部滚动。
- 使用明细:表格分页 8 行(日期 / 模型 / 请求数 / 消耗 / Token),dash-table 样式与仪表盘一致。
- 右侧 8/24 栏:
- 广告位占位:渐变蓝紫 AD 卡片。
- 用户排行:卡片式(rank 徽章 + 用户名/邮箱 + 请求/消耗双列 + 套餐 tag),radio 切换今日/本周/本月。
- 系统公告:3 条公告列表。
- 更新日志:3 条 changelog 条目。
- 资源:官方文档 + GitHub 外链。
- 样式:所有 panel/grid/trend-cell/dash-table 样式与 Dashboard.vue 同构(行高/间距/字号一致)。
- 新增侧边栏「数据」菜单(
layouts/AdminLayout.vue,admin only):- 位置:渠道之上,icon
icon-bar-chart,与「渠道/订单/兑换码/用户/订阅/设置」并列。 - 路由
/admin/dashboard由router/index.js注册,isAdminRouteallow-list 加入AdminDashboard,非管理员访问被重定向到/dashboard。
- 位置:渠道之上,icon
- 新增前端 API 模块
src/api/admin.js:adminApi.overview(range)→GET /api/admin/dashboard/overview。adminApi.topUsers(range, limit)→GET /api/admin/dashboard/top-users。adminApi.charts(range)→GET /api/admin/dashboard/charts(统一图表接口)。adminApi.modelDistribution/adminApi.usageDetails在重构后移除(被charts取代)。
- 新增 i18n 文案(zh/en,
src/i18n/locales.js,admin.*命名空间):- 页面标题
pageTitle: '运营数据' / 'Overview'。 - 5 个分区标题:
sectionUsers / sectionRevenue / sectionResources / sectionQuota / sectionLeaderboard。 - 卡片 label:用户 KPI、营收、资源、Token/请求消耗 等约 40 个 key。
- 时间筛选 label:
todayLabel: '今日' / 'Today'、weekLabel: '本周' / 'This Week'、monthLabel: '本月' / 'This Month'、rangeToday/7d/30d/all。 - 排行榜 tag:
sectionLeaderboard: '用户排行'、列名colUsername/colRequestCount/colQuota/colBalance/colPlan。 - 图表标题精简:
chartRequests: '请求量'、chartQuota: '额度'、chartTokens: 'Token'、chartModelDist: '模型分布(近 7 日)'。 - 公告/更新日志/资源/广告位等辅助文案。
- 页面标题
- 网页 Title 动态化:
- 落地页默认 Title 改为
ONE-API-PRO—企业级AI API 网关(web/default-pro/index.html)。 - 路由切换时
router.afterEach钩子按meta.title拼接{菜单名}—ONE-API-PRO,如「控制台—ONE-API-PRO」。
- 落地页默认 Title 改为
🐛 问题修复
- 修复
/api/*未匹配路由误返回 OpenAI 风格invalid_request_error误导排查(router/web.go):- 原来
NoRoute对/v1/*与/api/*都返回RelayNotFound(OpenAIinvalid_request_error),导致缺失的管理接口被误判为 relay 路由问题。 - 现仅
/v1/*保留 OpenAI 错误(relay 客户端需要兼容),/api/*未匹配返回标准{success:false, message:"接口不存在: METHOD PATH"}404 信封,便于定位路由缺失。
- 原来
- 修复 admin_dashboard 结构体 GORM column 推断错位(
model/admin_dashboard.go):AdminDashboardUsers/AdminDashboardResources/AdminDashboardTopUserRow等聚合行结构体默认按 GORM 字段名 snake_case 推断列名(New7d→new7d),与 SQL 别名new_7d不匹配,导致聚合全部填充 0。- 显式补齐
gorm:"column:..."标签后正常。 - 由
TestGetAdminDashboardOverview_Smoke触发并修复。
- 修复 Vue
<style scoped>跨组件不生效:AdminDashboard 引用的.panel / .stat-grid / .trend-cell / .dash-table等与 Dashboard.vue 同名样式,因 scoped hash 不同不会跨文件共享;将 AdminDashboard 实际用到的样式全部内联到本组件的<style scoped>,并去除.admin-dashboard容器多余 padding,改用.dashboard { display: flex; flex-direction: column; gap: 16px }与 Dashboard.vue 布局一致。 - 修复 admin 折线图无数据时全 0 看不见线:
yAxis.min = 0+max = maxV > 0 ? undefined : 1(旧版在 0 数据时max = undefined导致 auto-scale 把线压成一条不可见线);areaStyle透明度由02提到30;symbolSize = 6+itemStyle.borderWidth = 2强化折线点。 - 修复 admin 折线图「9-11 标签被右边界裁切」:
grid.right: 16+xAxis.axisLabel.margin: 8+hideOverlap: false,确保最新日期可见。 - 修复 admin 折线图缺今日:
AdminTrendPoint/aggregateTrends在某日无数据时只回{day}(因omitempty)导致前端undefined;改用[]LogStatistic一致结构 + 前端本地补全 N 天日期序列(含今天),彻底解决「9-11 今天的没显示」。 - 修复 AdminDashboard 残留
IconHistogram/IconRollback引用:npm run build不报错(运行时才崩),统一替换为 arco icon set 内可用名称IconBarChart/IconArrowFall。 - 修复 9-11 类型 UTC 对齐:Go
todayStart = now - (now%daySec)按 UTC 边界 + SQLitestrftimeUTC + CST 本地 9:00 之间偏差 1 天的隐患,统一在测试日志时间戳 +100s 保证 UTC 与本地对齐。
🔧 重构
后端(Go)
- 图表数据从 overview 拆分独立:
- 移除
AdminTrendPoint/AdminDashboardTrends/aggregateTrends三个旧结构/函数。 AdminDashboardOverview移除Trends字段,专注 KPI。- 移除
AdminModelDistribution*/GetAdminModelDistribution与AdminUsageDetails*/GetAdminUsageDetails,由/charts统一驱动。 - 移除对应 controller handlers + router 路由(
/api/admin/dashboard/model-distribution、/api/admin/dashboard/usage-details)。 model/admin_dashboard.go总行数减少 ~320 行;删除sort/time等不再需要的 import。
- 移除
- 响应结构统一:单一
/charts接口返回与/api/user/dashboard同构的[]LogStatistic,前端无需分别请求 3 个端点拼装数据。
前端
- AdminDashboard 全面重构:从 trend row 内嵌模型分布改为独立全宽模型分布 panel;折线图数量从「请求量/Quota/模型分布」改为「请求量/额度/Token」3 张折线(与 Dashboard.vue 一致)。
adminApi.modelDistribution/adminApi.usageDetails移除,统一为adminApi.charts一份接口。AdminDashboard.vue新增chartData / daySeries / distModels / usageRows四个 computed,本地构建日期序列 + 客户端聚合 Top 8 模型,避免依赖后端预聚合。lineOption从overview.trends改读chartData([{date, value}])。modelBarOption从distDays + distItems改读distModels(前端 Top N 排序)。- 使用明细表从
usageDetails改读usageRows(扁平 day×model,日期 desc + 消耗 desc 排序)。
🚀 性能
- 修复 release-docker workflow arm64 emulated
npm install触发 SIGILL(Dockerfile+.github/workflows/release-docker.yml):- 改为在 release-docker job 中预构建
web/build,docker build 不再npm install,避免 QEMU 模拟的 Node.js 二进制崩溃。 - 详见
ci(release-docker): 预构建 web/build,避免 arm64 emulated npm install 触发 SIGILL。
- 改为在 release-docker job 中预构建
⚠️ 升级注意事项
- 零数据库迁移:所有 admin dashboard 新增字段都是聚合响应或新接口,无表结构变更。
- 后端路由变更(
router/api.go,admin 路由组):- 新增
GET /api/admin/dashboard/charts(AdminAuth)。 - 移除
GET /api/admin/dashboard/model-distribution、GET /api/admin/dashboard/usage-details(被/charts取代)。 - 如有外部监控/脚本调用旧路由,请改用
/charts+ 前端聚合逻辑(或直接用/api/admin/dashboard/overview)。
- 新增
- 后端二进制必须重启:
/charts是新路由,编译进二进制后才生效。升级后必须重启one-api-pro进程。 - 前端 chunk 缓存:浏览器需要硬刷(Cmd+Shift+R)以加载新
AdminDashboardchunk;旧的AdminDashboard-*.jschunk 仍可能引用/usage-details导致 404。 - 未匹配
/api/*错误格式变化:升级后若遗漏注册路由,前端会收到{success:false, message:"接口不存在: GET /api/..."}(HTTP 404)而非 OpenAI 风格错误,更易定位。 - 后端构建与测试:
go build ./...通过。go test ./model/ ./controller/ ./middleware/全绿(含 3 个新增 admin_dashboard 测试 + 已有测试)。- 前端:
cd web/default-pro && npm run build通过。
- 页面标题变更:浏览器 tab 标题从「One Api Pro——企业级 API 网关」变为
ONE-API-PRO—企业级AI API 网关,后台路由切换时动态显示「{菜单名}—ONE-API-PRO」。如有外部监控依赖旧标题文案请知悉。