diff --git a/src/features/script-tokens/TokenUsagePage.tsx b/src/features/script-tokens/TokenUsagePage.tsx index 8cf5578..9aa5646 100644 --- a/src/features/script-tokens/TokenUsagePage.tsx +++ b/src/features/script-tokens/TokenUsagePage.tsx @@ -230,25 +230,35 @@ function TokenUsagePage({ { label: "账户类型", value: isEnterpriseAccount ? "企业账户" : "个人账户", tone: "good" }, { label: "企业空间", value: enterpriseUsage?.enterpriseName || session?.user.enterpriseName || "-" }, ]; + const pageStatusClass = enterpriseUsageLoading + ? "is-syncing" + : enterpriseUsageError + ? "has-sync-error" + : isLowBalance + ? "has-low-balance" + : "is-healthy"; return ( -
+
- 管理中心 + + 管理中心 + 用量、成员与模型调用监控 +
- + {enterpriseUsageLoading ? "正在同步企业用量" : enterpriseUsageError || "服务器已连接"} - - @@ -267,8 +277,9 @@ function TokenUsagePage({ ) : null}
- {metricCards.map((card) => ( + {metricCards.map((card, index) => (
+ {String(index + 1).padStart(2, "0")} {card.label} {card.value} {card.hint} @@ -283,7 +294,7 @@ function TokenUsagePage({ 模型消耗分布 - {modelBreakdown.length ? `${modelBreakdown.length} 个模型` : "LIVE"} + {enterpriseUsageLoading ? "SYNC" : modelBreakdown.length ? `${modelBreakdown.length} 个模型` : "LIVE"} {modelBreakdown.length ? (
@@ -310,7 +321,10 @@ function TokenUsagePage({
-

系统状态

+

+ + 系统状态 +

{systemStatus.map((item) => ( @@ -364,7 +378,10 @@ function TokenUsagePage({
-

调用记录

+

+ + 调用记录 +

{records.length} 条记录
diff --git a/src/styles/pages/script-tokens.css b/src/styles/pages/script-tokens.css index 3784a48..a1f59de 100644 --- a/src/styles/pages/script-tokens.css +++ b/src/styles/pages/script-tokens.css @@ -5377,3 +5377,559 @@ flex-shrink: 0; font-size: 16px; } + +/* ===== Token usage commercial SaaS polish ===== */ +.token-usage-page.management-center-page { + --usage-panel: rgba(17, 21, 21, 0.96); + --usage-panel-strong: rgba(21, 26, 25, 0.98); + --usage-inset: rgba(255, 255, 255, 0.035); + --usage-inset-strong: rgba(255, 255, 255, 0.055); + --usage-line: rgba(255, 255, 255, 0.08); + --usage-line-strong: rgba(var(--accent-rgb), 0.28); + --usage-muted: rgba(232, 240, 235, 0.66); + --usage-soft: rgba(232, 240, 235, 0.44); + --usage-card-shadow: 0 18px 46px rgba(0, 0, 0, 0.22); + background: + radial-gradient(circle at 18% 0%, rgba(var(--accent-rgb), 0.06), transparent 34%), + linear-gradient(180deg, rgba(255, 255, 255, 0.022), transparent 220px), + var(--bg-base); +} + +.token-usage-page .management-center-shell { + gap: 16px; + padding: 0 30px 42px; +} + +.token-usage-page .management-center-toolbar { + position: sticky; + top: 0; + z-index: 8; + min-height: 64px; + border-bottom-color: var(--usage-line); + border-bottom-left-radius: 18px; + background: rgba(14, 17, 17, 0.88); + backdrop-filter: blur(18px); + box-shadow: 0 14px 30px rgba(0, 0, 0, 0.16); +} + +.token-usage-page .management-center-toolbar__title { + gap: 10px; +} + +.token-usage-page .management-center-toolbar__title > span { + display: grid; + gap: 3px; + min-width: 0; +} + +.token-usage-page .management-center-toolbar__title strong { + color: #f2f8f5; + font-size: 15px; + letter-spacing: 0; +} + +.token-usage-page .management-center-toolbar__title small { + overflow: hidden; + color: var(--usage-soft); + font-size: 11px; + font-weight: 700; + line-height: 1.2; + text-overflow: ellipsis; + white-space: nowrap; +} + +.token-usage-page .management-center-toolbar button, +.token-usage-page .management-card__head button, +.token-usage-page .management-center-status-pill { + border-color: var(--usage-line); + border-radius: 10px; + background: var(--usage-inset); + color: var(--usage-muted); + transition: border-color 160ms ease, background 160ms ease, color 160ms ease, transform 160ms ease, opacity 160ms ease; +} + +.token-usage-page .management-center-toolbar button:hover:not(:disabled), +.token-usage-page .management-card__head button:hover { + border-color: var(--usage-line-strong); + background: rgba(var(--accent-rgb), 0.08); + color: var(--fg-body); + transform: translateY(-1px); +} + +.token-usage-page .management-center-toolbar button:disabled { + opacity: 0.52; + cursor: wait; +} + +.token-usage-page .management-center-toolbar__back { + border-radius: 999px !important; +} + +.token-usage-page .management-center-toolbar button.is-muted-action { + color: var(--usage-soft); +} + +.token-usage-page .management-center-toolbar button.is-primary { + border-color: rgba(var(--accent-rgb), 0.72); + background: linear-gradient(180deg, #2fffa5, var(--accent)); + color: rgb(5, 15, 11); + box-shadow: 0 12px 26px rgba(var(--accent-rgb), 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.3); +} + +.token-usage-page .management-center-status-pill { + position: relative; + gap: 7px; + border-radius: 999px; + padding-inline: 12px; +} + +.token-usage-page .management-center-status-pill::before { + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--accent); + box-shadow: 0 0 14px rgba(var(--accent-rgb), 0.45); + content: ""; +} + +.token-usage-page .management-center-status-pill.is-loading::before { + animation: token-usage-pulse 1.2s ease infinite; +} + +.token-usage-page .management-center-status-pill.is-error { + border-color: rgba(245, 158, 11, 0.42); + background: rgba(245, 158, 11, 0.1); + color: #f7ca73; +} + +.token-usage-page .management-center-status-pill.is-error::before { + background: #f59e0b; + box-shadow: 0 0 14px rgba(245, 158, 11, 0.4); +} + +@keyframes token-usage-pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.42; transform: scale(0.76); } +} + +.token-usage-page .management-balance-alert { + margin: 2px 0 0; + border-color: rgba(245, 158, 11, 0.34); + border-radius: 14px; + background: + linear-gradient(90deg, rgba(245, 158, 11, 0.14), rgba(245, 158, 11, 0.045)), + var(--usage-panel); + box-shadow: var(--usage-card-shadow); +} + +.token-usage-page .management-balance-alert button { + border: 0; + border-radius: 999px; +} + +.token-usage-page .management-metric-cards { + gap: 12px; + margin: 0; +} + +.token-usage-page .management-metric-card { + position: relative; + min-height: 132px; + overflow: hidden; + gap: 8px; + padding: 18px; + border-color: var(--usage-line); + border-radius: 18px; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.048), transparent 70%), + var(--usage-panel-strong); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.035); +} + +.token-usage-page .management-metric-card::before { + position: absolute; + inset: 0 auto 0 0; + width: 3px; + border-radius: 999px; + background: rgba(255, 255, 255, 0.12); + content: ""; +} + +.token-usage-page .management-metric-card.is-accent { + border-color: rgba(var(--accent-rgb), 0.32); + background: + radial-gradient(circle at 88% 16%, rgba(var(--accent-rgb), 0.18), transparent 38%), + linear-gradient(180deg, rgba(255, 255, 255, 0.052), transparent 72%), + var(--usage-panel-strong); +} + +.token-usage-page .management-metric-card.is-accent::before { + background: var(--accent); + box-shadow: 0 0 18px rgba(var(--accent-rgb), 0.44); +} + +.token-usage-page .management-metric-card.is-warn::before { + background: #f59e0b; + box-shadow: 0 0 18px rgba(245, 158, 11, 0.32); +} + +.token-usage-page .management-metric-card__index { + position: absolute; + top: 14px; + right: 16px; + color: rgba(255, 255, 255, 0.14); + font-size: 22px; + font-weight: 950; + line-height: 1; +} + +.token-usage-page .management-metric-card__label { + color: var(--usage-muted); + font-size: 12px; + font-weight: 800; +} + +.token-usage-page .management-metric-card__value { + color: #f6fbf8; + font-size: clamp(24px, 2.5vw, 34px); + font-weight: 920; + letter-spacing: 0; +} + +.token-usage-page .management-metric-card__hint { + color: var(--usage-soft); + font-size: 12px; + font-weight: 700; +} + +.token-usage-page .management-center-overview { + gap: 14px; +} + +.token-usage-page .management-card { + border-color: var(--usage-line); + border-radius: 18px; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.035), transparent 64%), + var(--usage-panel); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.026); +} + +.token-usage-page .management-card__head { + min-height: 50px; + border-bottom-color: var(--usage-line); + padding-inline: 18px; +} + +.token-usage-page .management-card__head h2 { + color: #ecf5f0; + font-size: 14px; + letter-spacing: 0; +} + +.token-usage-page .management-card__head h2 .anticon { + color: var(--accent); +} + +.token-usage-page .management-card__head > span, +.token-usage-page .management-card__head button { + border-color: var(--usage-line); + border-radius: 999px; + background: var(--usage-inset); + color: var(--usage-muted); +} + +.token-usage-page .management-card--chart { + height: clamp(390px, 50vh, 580px); +} + +.token-usage-page .management-empty-chart, +.token-usage-page .management-record-empty, +.token-usage-page .management-status-trend__empty { + border: 1px dashed var(--usage-line); + border-radius: 14px; + background: rgba(255, 255, 255, 0.024); +} + +.token-usage-page .management-model-list { + gap: 10px; + padding: 14px 18px 18px; +} + +.token-usage-page .management-model-bar { + gap: 8px; + padding: 12px 14px; + border: 1px solid rgba(255, 255, 255, 0.045); + border-radius: 14px; + background: var(--usage-inset); + transition: border-color 160ms ease, background 160ms ease, transform 160ms ease; +} + +.token-usage-page .management-model-bar:hover { + border-color: var(--usage-line-strong); + background: rgba(var(--accent-rgb), 0.052); + transform: translateY(-1px); +} + +.token-usage-page .management-model-bar__top strong { + color: #eef6f2; + font-size: 13px; +} + +.token-usage-page .management-model-bar__track { + height: 7px; + background: rgba(255, 255, 255, 0.07); +} + +.token-usage-page .management-status-card dl { + padding: 14px 18px 10px; +} + +.token-usage-page .management-status-card div { + min-height: 38px; + border-bottom: 1px solid rgba(255, 255, 255, 0.045); +} + +.token-usage-page .management-status-card div:last-child { + border-bottom: 0; +} + +.token-usage-page .management-status-card dt { + color: var(--usage-soft); + font-weight: 780; +} + +.token-usage-page .management-status-trend { + padding: 14px 18px 18px; + border-top-color: var(--usage-line); +} + +.token-usage-page .management-status-trend__title { + margin-bottom: 8px; + color: var(--usage-muted); + font-weight: 820; +} + +.token-usage-page .usage-trend__svg { + min-height: 160px; +} + +.token-usage-page .usage-trend__line { + filter: drop-shadow(0 0 8px rgba(var(--accent-rgb), 0.22)); +} + +.token-usage-page .usage-trend__dot { + transition: r 160ms ease; +} + +.token-usage-page .usage-trend__meta { + border-top-color: var(--usage-line); + color: var(--usage-soft); +} + +.token-usage-page .management-members, +.token-usage-page .management-records { + padding-bottom: 14px; +} + +.token-usage-page .management-member-list { + gap: 10px; + padding: 12px 18px 2px; +} + +.token-usage-page .management-member-row { + min-height: 64px; + border: 1px solid rgba(255, 255, 255, 0.045); + border-radius: 14px; + background: var(--usage-inset); + transition: border-color 160ms ease, background 160ms ease, transform 160ms ease; +} + +.token-usage-page .management-member-row:hover { + border-color: var(--usage-line-strong); + background: rgba(var(--accent-rgb), 0.052); + transform: translateY(-1px); +} + +.token-usage-page .management-member-avatar { + color: rgb(5, 15, 11); + box-shadow: 0 8px 20px rgba(var(--accent-rgb), 0.16); +} + +.token-usage-page .management-member-role { + border-color: var(--usage-line); + border-radius: 999px; + background: rgba(255, 255, 255, 0.035); +} + +.token-usage-page .management-record-table { + min-width: 0; + padding: 14px 18px 0; + overflow-x: auto; +} + +.token-usage-page .management-record-table__head, +.token-usage-page .management-record-table__row { + min-width: 880px; + border: 1px solid transparent; + border-radius: 12px; +} + +.token-usage-page .management-record-table__head { + min-height: 38px; + background: rgba(255, 255, 255, 0.045); + color: var(--usage-muted); +} + +.token-usage-page .management-record-table__row { + min-height: 46px; + background: var(--usage-inset); + transition: border-color 160ms ease, background 160ms ease; +} + +.token-usage-page .management-record-table__row:hover { + border-color: rgba(255, 255, 255, 0.065); + background: rgba(255, 255, 255, 0.052); +} + +.token-usage-page .management-record-table__row span.is-good, +.token-usage-page .management-record-table__row span.is-error { + display: inline-flex; + align-items: center; + justify-content: center; + width: max-content; + min-width: 44px; + min-height: 24px; + border-radius: 999px; + padding: 0 9px; + font-size: 11px; + font-weight: 850; +} + +.token-usage-page .management-record-table__row span.is-good { + background: rgba(var(--accent-rgb), 0.1); +} + +.token-usage-page .management-record-table__row span.is-error { + background: rgba(239, 68, 68, 0.1); +} + +.token-usage-page .management-record-pagination { + border-top-color: var(--usage-line); +} + +.token-usage-page .management-record-pagination button { + border-color: var(--usage-line); + border-radius: 9px; + background: var(--usage-inset); + color: var(--usage-muted); +} + +.token-usage-page .management-record-pagination button:hover:not(:disabled) { + background: var(--accent); + border-color: var(--accent); + color: rgb(5, 15, 11); +} + +@media (max-width: 1180px) { + .token-usage-page.management-center-page { + padding-left: 20px; + } + + .token-usage-page .management-center-shell { + padding-inline: 22px; + } +} + +@media (min-width: 901px) and (max-width: 1180px) { + .token-usage-page.management-center-page { + padding-left: 82px; + } +} + +@media (max-width: 900px) { + .token-usage-page.management-center-page { + padding-top: 74px; + padding-left: 0; + } + + .token-usage-page .management-center-shell { + padding: 0 16px 34px; + } + + .token-usage-page .management-center-toolbar { + top: 0; + align-items: stretch; + margin: 0 -16px; + padding: 12px 16px; + border-radius: 0 0 18px 18px; + } + + .token-usage-page .management-center-toolbar__title { + width: 100%; + } + + .token-usage-page .management-center-status-pill { + order: 2; + } + + .token-usage-page .management-metric-cards { + grid-template-columns: minmax(0, 1fr); + } + + .token-usage-page .management-center-overview { + grid-template-columns: minmax(0, 1fr); + } + + .token-usage-page .management-card--chart { + height: auto; + min-height: 360px; + } + + .token-usage-page .management-member-row { + grid-template-columns: auto minmax(0, 1fr); + align-items: start; + gap: 10px 12px; + padding: 14px; + } + + .token-usage-page .management-member-role, + .token-usage-page .management-member-row > span:not(.management-member-avatar):not(.management-member-role):not(.management-member-meter), + .token-usage-page .management-member-meter, + .token-usage-page .management-member-row > .anticon { + grid-column: 2; + justify-self: start; + } +} + +@media (max-width: 560px) { + .token-usage-page .management-center-toolbar button:not(.management-center-toolbar__back) { + flex: 1 1 calc(50% - 6px); + padding-inline: 10px; + } + + .token-usage-page .management-center-status-pill { + flex: 1 1 100%; + justify-content: flex-start; + } + + .token-usage-page .management-metric-card { + min-height: 118px; + padding: 16px; + } + + .token-usage-page .management-metric-card__value { + font-size: 24px; + } + + .token-usage-page .management-card__head { + min-height: 46px; + padding-inline: 14px; + } + + .token-usage-page .management-model-list, + .token-usage-page .management-member-list, + .token-usage-page .management-record-table { + padding-inline: 14px; + } +}