Skip to content

Commit 28ca7df

Browse files
author
QTom
committed
feat: add RPM display to AccountCapacityCell
1 parent 856c955 commit 28ca7df

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

frontend/src/components/account/AccountCapacityCell.vue

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,24 @@
5252
<span class="font-mono">{{ account.max_sessions }}</span>
5353
</span>
5454
</div>
55+
56+
<!-- RPM 限制(仅 Anthropic OAuth/SetupToken 且启用时显示) -->
57+
<div v-if="showRpmLimit" class="flex items-center gap-1">
58+
<span
59+
:class="[
60+
'inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[10px] font-medium',
61+
rpmClass
62+
]"
63+
:title="rpmTooltip"
64+
>
65+
<svg class="h-2.5 w-2.5" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
66+
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
67+
</svg>
68+
<span class="font-mono">{{ currentRPM }}</span>
69+
<span class="text-gray-400 dark:text-gray-500">/</span>
70+
<span class="font-mono">{{ account.base_rpm }}</span>
71+
</span>
72+
</div>
5573
</div>
5674
</template>
5775

@@ -191,6 +209,50 @@ const sessionLimitTooltip = computed(() => {
191209
return t('admin.accounts.capacity.sessions.normal', { idle })
192210
})
193211
212+
// 是否显示 RPM 限制
213+
const showRpmLimit = computed(() => {
214+
return (
215+
isAnthropicOAuthOrSetupToken.value &&
216+
props.account.base_rpm !== undefined &&
217+
props.account.base_rpm !== null &&
218+
props.account.base_rpm > 0
219+
)
220+
})
221+
222+
// 当前 RPM 计数
223+
const currentRPM = computed(() => props.account.current_rpm ?? 0)
224+
225+
// RPM 状态样式
226+
const rpmClass = computed(() => {
227+
if (!showRpmLimit.value) return ''
228+
229+
const current = currentRPM.value
230+
const base = props.account.base_rpm ?? 0
231+
if (base <= 0) return 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400'
232+
233+
const strategy = props.account.rpm_strategy || 'tiered'
234+
if (strategy === 'tiered') {
235+
const buffer = props.account.rpm_sticky_buffer ?? Math.max(1, Math.floor(base / 5))
236+
if (current >= base + buffer) return 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'
237+
if (current >= base) return 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400'
238+
} else {
239+
if (current >= base) return 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400'
240+
}
241+
if (current >= base * 0.8) return 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400'
242+
return 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400'
243+
})
244+
245+
// RPM 提示文字
246+
const rpmTooltip = computed(() => {
247+
if (!showRpmLimit.value) return ''
248+
249+
const current = currentRPM.value
250+
const base = props.account.base_rpm ?? 0
251+
if (current >= base) return t('admin.accounts.capacity.rpm.full')
252+
if (current >= base * 0.8) return t('admin.accounts.capacity.rpm.warning')
253+
return t('admin.accounts.capacity.rpm.normal')
254+
})
255+
194256
// 格式化费用显示
195257
const formatCost = (value: number | null | undefined) => {
196258
if (value === null || value === undefined) return '0'

0 commit comments

Comments
 (0)