diff --git a/f/web-kboss/src/api/model/model.js b/f/web-kboss/src/api/model/model.js index 65e0b79..226e457 100644 --- a/f/web-kboss/src/api/model/model.js +++ b/f/web-kboss/src/api/model/model.js @@ -149,4 +149,13 @@ export const reqModelInfoConfigList = (params = {}) => { method: 'get', params }) +} + +// 运营报表 +export const reqOperationReport = (params = {}) => { + return request({ + url: '/cntoai/model_usage_admin_report.dspy', + method: 'post', + params + }) } \ No newline at end of file diff --git a/f/web-kboss/src/router/index.js b/f/web-kboss/src/router/index.js index c3f628c..dafc74d 100644 --- a/f/web-kboss/src/router/index.js +++ b/f/web-kboss/src/router/index.js @@ -539,29 +539,29 @@ export const asyncRoutes = [ ] }, // Token用量 - 一级菜单(所有登录用户都能看到) - // { - // path: "/tokenUsage", - // component: Layout, - // meta: { - // title: "Token用量", - // fullPath: "/tokenUsage", - // noCache: true, - // icon: "el-icon-data-line" - // }, - // children: [ - // { - // path: "", - // component: () => import('@/views/tokenUsage/index.vue'), - // name: 'TokenUsage', - // meta: { - // title: "Token用量", - // fullPath: "/tokenUsage", - // noCache: true, - // icon: "el-icon-data-line" - // } - // }, - // ] - // }, + { + path: "/tokenUsage", + component: Layout, + meta: { + title: "Token用量", + fullPath: "/tokenUsage", + noCache: true, + icon: "el-icon-data-line" + }, + children: [ + { + path: "", + component: () => import('@/views/tokenUsage/index.vue'), + name: 'TokenUsage', + meta: { + title: "Token用量", + fullPath: "/tokenUsage", + noCache: true, + icon: "el-icon-data-line" + } + }, + ] + }, // 模型体验 { path: "/modelExperience", diff --git a/f/web-kboss/src/views/operation/operationReport/index.vue b/f/web-kboss/src/views/operation/operationReport/index.vue index 688f2c8..924e650 100644 --- a/f/web-kboss/src/views/operation/operationReport/index.vue +++ b/f/web-kboss/src/views/operation/operationReport/index.vue @@ -2,196 +2,529 @@
-

运营报表

-

模型使用与计费数据概览

+
+ + + +

运营报表

+
+

查看机构下模型调用次数、Token 消耗和费用统计。

+
+
+ {{ filterTimeText }} + + 刷新 +
- 导出报表
-
-
活跃用户
-
{{ statCards.activeUsers }}
-
-
-
Token消耗
-
{{ statCards.tokenUsage }}
-
-
-
Tokens总费用
-
¥{{ statCards.totalFee }}
+
+
+
{{ item.label }}
+ +
+
{{ item.value }}
+
{{ item.desc }}
- - - - - - - +
+
+

筛选条件

+

按模型和时间范围查询运营用量。

+
+ + + + + - - - - - - - - - - - - 查询 - 重置 - - + + + + 查询 + 重置 + +
- - - - - +
+
+

用量明细

+

共 {{ total }} 条记录

+
+ {{ timeText }} +
+ + + + + + - - - - - - + + + - + + + + + + + + + + +
+ >
diff --git a/f/web-kboss/src/views/tokenUsage/index.vue b/f/web-kboss/src/views/tokenUsage/index.vue index bf7ea06..e4dcfe9 100644 --- a/f/web-kboss/src/views/tokenUsage/index.vue +++ b/f/web-kboss/src/views/tokenUsage/index.vue @@ -1,7 +1,7 @@ @@ -92,13 +408,15 @@ export default { .token-usage-page { min-height: 100vh; padding: 24px; - background: linear-gradient(180deg, #f3f7ff 0%, #f7f9fc 48%, #ffffff 100%); + background: + radial-gradient(circle at top left, rgba(64, 158, 255, 0.16), transparent 34%), + linear-gradient(180deg, #f3f7ff 0%, #f7f9fc 48%, #ffffff 100%); } .usage-shell { min-height: calc(100vh - 48px); padding: 24px; - background: #ffffff; + background: rgba(255, 255, 255, 0.92); border: 1px solid #edf1f7; border-radius: 18px; box-shadow: 0 12px 30px rgba(31, 45, 61, 0.06); @@ -113,7 +431,18 @@ export default { } .page-header { - margin-bottom: 24px; + align-items: center; + padding: 20px 22px; + margin-bottom: 20px; + overflow: hidden; + color: #ffffff; + background: linear-gradient(135deg, #1e6fff 0%, #409eff 48%, #7c3aed 100%); + border-radius: 18px; + box-shadow: 0 14px 34px rgba(64, 158, 255, 0.22); + + p { + color: rgba(255, 255, 255, 0.82); + } } .title-line { @@ -124,7 +453,7 @@ export default { h2 { margin: 0; - color: #1f2d3d; + color: #ffffff; font-size: 24px; } } @@ -135,9 +464,9 @@ export default { justify-content: center; width: 36px; height: 36px; - color: #409eff; + color: #ffffff; font-size: 18px; - background: #eef5ff; + background: rgba(255, 255, 255, 0.18); border-radius: 12px; } @@ -149,9 +478,26 @@ export default { } .refresh-btn { + color: #1e6fff; + border: none; border-radius: 10px; } +.header-actions { + display: flex; + align-items: center; + gap: 12px; +} + +.range-badge { + padding: 7px 12px; + color: #ffffff; + font-size: 12px; + background: rgba(255, 255, 255, 0.16); + border: 1px solid rgba(255, 255, 255, 0.24); + border-radius: 999px; +} + .stat-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); @@ -160,10 +506,19 @@ export default { } .stat-card { + position: relative; + overflow: hidden; padding: 20px; border-radius: 16px; border: 1px solid #edf1f7; background: #ffffff; + box-shadow: 0 8px 24px rgba(31, 45, 61, 0.04); + transition: transform 0.2s ease, box-shadow 0.2s ease; + + &:hover { + transform: translateY(-2px); + box-shadow: 0 12px 28px rgba(31, 45, 61, 0.08); + } span, em { @@ -180,20 +535,130 @@ export default { font-size: 26px; } + &:before { + position: absolute; + top: 0; + right: 0; + width: 86px; + height: 86px; + content: ''; + background: rgba(255, 255, 255, 0.52); + border-radius: 0 0 0 86px; + } + &.primary { - background: #eef5ff; + background: linear-gradient(135deg, #eef5ff 0%, #ffffff 100%); } &.success { - background: #f0fdf4; + background: linear-gradient(135deg, #f0fdf4 0%, #ffffff 100%); } &.warning { - background: #fff7ed; + background: linear-gradient(135deg, #fff7ed 0%, #ffffff 100%); } &.purple { - background: #f5f3ff; + background: linear-gradient(135deg, #f5f3ff 0%, #ffffff 100%); + } +} + +.stat-card-head { + position: relative; + z-index: 1; + display: flex; + align-items: center; + justify-content: space-between; + + i { + display: flex; + align-items: center; + justify-content: center; + width: 34px; + height: 34px; + color: #409eff; + font-size: 18px; + background: rgba(64, 158, 255, 0.12); + border-radius: 12px; + } +} + +.usage-dashboard { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); + gap: 16px; + margin-bottom: 20px; +} + +.dashboard-card { + padding: 22px; + border: 1px solid #edf1f7; + border-radius: 16px; + background: #ffffff; + box-shadow: 0 10px 26px rgba(31, 45, 61, 0.05); +} + +.dashboard-title { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 16px; + + h3 { + margin: 0; + color: #1f2d3d; + font-size: 16px; + } + + span { + color: #909399; + font-size: 12px; + } +} + +.token-total { + color: #1f2d3d; + font-size: 34px; + font-weight: 700; + line-height: 1.2; +} + +.token-ratio-card { + p { + margin: 6px 0 18px; + color: #909399; + font-size: 13px; + } +} + +.chart-box { + width: 100%; + height: 240px; +} + +.model-rank-chart { + height: 300px; +} + +.ratio-list, +.rank-list { + display: flex; + flex-direction: column; + gap: 14px; +} + +.ratio-label, +.rank-info { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; + color: #606266; + font-size: 13px; + + strong { + color: #1f2d3d; + font-weight: 700; } } @@ -201,6 +666,8 @@ export default { padding: 22px; border: 1px solid #edf1f7; border-radius: 16px; + background: #ffffff; + box-shadow: 0 10px 26px rgba(31, 45, 61, 0.05); } .card-header { @@ -212,15 +679,57 @@ export default { } } +.filter-actions { + display: flex; + align-items: center; + gap: 10px; + padding: 8px; + background: #f6f8fb; + border: 1px solid #edf1f7; + border-radius: 12px; + + /deep/ .el-select { + width: 110px; + } + + /deep/ .el-input { + width: 160px; + } + + /deep/ .el-input__inner { + border-color: transparent; + } +} + .usage-table { border-radius: 12px; overflow: hidden; + + /deep/ .el-table__header th { + color: #475467; + font-weight: 700; + background: #f8fafc; + } + + /deep/ .el-table__row:hover > td { + background: #f6faff; + } +} + +.table-pagination { + display: flex; + justify-content: flex-end; + margin-top: 16px; } @media (max-width: 1100px) { .stat-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } + + .usage-dashboard { + grid-template-columns: 1fr; + } } @media (max-width: 700px) { @@ -232,5 +741,15 @@ export default { .card-header { flex-direction: column; } + + .filter-actions { + align-items: flex-start; + flex-direction: column; + width: 100%; + + /deep/ .el-date-editor { + width: 100%; + } + } }