mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-06 08:06:19 +00:00
refactor(web): consolidate the font-weight scale to four semantic tiers
Replace the nine ad-hoc arbitrary font weights (620-820, 208 usages) with a four-tier scale: font-emphasis (650) and font-heavy (760) as new theme tokens, plus the standard font-bold (700) and font-extrabold (800). Every merge moves a weight by at most 30 units, below the perceptible threshold for UI text sizes. The SystemUpdateModal release-notes scoped styles reference the same tokens. Arbitrary font-[N] classes are now zero across the codebase; the scale is documented in the theme block. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -47,7 +47,7 @@ const authenticationLabel = computed(() => {
|
||||
>
|
||||
<Openai v-if="normalizedProvider === 'openai'" :class="iconClass" aria-hidden="true" />
|
||||
<Xai v-else-if="normalizedProvider === 'xai'" :class="iconClass" aria-hidden="true" />
|
||||
<span v-else class="text-[10px] font-[760] text-(--cp-text-muted)">?</span>
|
||||
<span v-else class="text-[10px] font-heavy text-(--cp-text-muted)">?</span>
|
||||
</span>
|
||||
|
||||
<span
|
||||
@@ -66,7 +66,7 @@ const authenticationLabel = computed(() => {
|
||||
:class="iconClass"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span v-else class="text-[10px] font-[760] text-(--cp-text-muted)">?</span>
|
||||
<span v-else class="text-[10px] font-heavy text-(--cp-text-muted)">?</span>
|
||||
</span>
|
||||
|
||||
<span class="sr-only">
|
||||
|
||||
@@ -70,7 +70,7 @@ const loadingIconSize: Record<ButtonSize, number> = {
|
||||
}
|
||||
|
||||
const classes = computed(() => [
|
||||
'inline-flex items-center justify-center border-0 font-[720] leading-[1.15] transition-[background-color,box-shadow,color,opacity,transform] duration-150 cursor-pointer outline-none motion-safe:active:translate-y-px motion-safe:active:scale-[0.985]',
|
||||
'inline-flex items-center justify-center border-0 font-bold leading-[1.15] transition-[background-color,box-shadow,color,opacity,transform] duration-150 cursor-pointer outline-none motion-safe:active:translate-y-px motion-safe:active:scale-[0.985]',
|
||||
props.iconOnly ? iconOnlySizeClasses[props.size] : sizeClasses[props.size],
|
||||
props.iconOnly ? '' : 'rounded-(--cp-button-radius-base)',
|
||||
'focus-visible:ring-2 focus-visible:ring-(--cp-info-border) focus-visible:ring-offset-2 focus-visible:ring-offset-(--cp-bg-surface)',
|
||||
|
||||
@@ -82,7 +82,7 @@ const managedHeaderLayoutClasses = computed(() => {
|
||||
<div class="min-w-0 pt-0.5">
|
||||
<h2
|
||||
v-if="props.title || $slots.title"
|
||||
class="m-0 text-xl leading-[1.15] font-[760] text-(--cp-text-primary)"
|
||||
class="m-0 text-xl leading-[1.15] font-heavy text-(--cp-text-primary)"
|
||||
>
|
||||
<slot name="title">
|
||||
{{ props.title }}
|
||||
@@ -90,7 +90,7 @@ const managedHeaderLayoutClasses = computed(() => {
|
||||
</h2>
|
||||
<p
|
||||
v-if="props.description || $slots.description"
|
||||
class="mt-1.75 mb-0 text-[13px] leading-[1.15] font-[650] text-(--cp-text-secondary)"
|
||||
class="mt-1.75 mb-0 text-[13px] leading-[1.15] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
<slot name="description">
|
||||
{{ props.description }}
|
||||
|
||||
@@ -40,7 +40,7 @@ function toggle() {
|
||||
<template>
|
||||
<button
|
||||
type="button"
|
||||
class="group inline-flex min-h-4 min-w-4 appearance-none items-center gap-2.5 border-0 bg-transparent p-0 text-[13px] leading-none font-[650] transition-opacity outline-none focus-visible:ring-2 focus-visible:ring-(--cp-info-border) focus-visible:ring-offset-2 focus-visible:ring-offset-(--cp-bg-surface)"
|
||||
class="group inline-flex min-h-4 min-w-4 appearance-none items-center gap-2.5 border-0 bg-transparent p-0 text-[13px] leading-none font-emphasis transition-opacity outline-none focus-visible:ring-2 focus-visible:ring-(--cp-info-border) focus-visible:ring-offset-2 focus-visible:ring-offset-(--cp-bg-surface)"
|
||||
:class="disabled ? 'cursor-not-allowed opacity-55' : 'cursor-pointer'"
|
||||
role="checkbox"
|
||||
:aria-checked="indeterminate ? 'mixed' : model"
|
||||
|
||||
@@ -63,7 +63,7 @@ function handleConfirm() {
|
||||
>
|
||||
<div
|
||||
v-if="$slots.default"
|
||||
class="text-[14px] leading-[1.55] font-[620] text-(--cp-text-secondary)"
|
||||
class="text-[14px] leading-[1.55] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@ const resolvedIcon = computed(() => props.icon ?? Inbox)
|
||||
>
|
||||
<component :is="resolvedIcon" :size="compact ? 16 : 18" />
|
||||
</span>
|
||||
<p class="m-0 text-[13px] leading-[1.15] font-[760] text-(--cp-text-primary)">
|
||||
<p class="m-0 text-[13px] leading-[1.15] font-heavy text-(--cp-text-primary)">
|
||||
{{ resolvedTitle }}
|
||||
</p>
|
||||
<p
|
||||
|
||||
@@ -40,14 +40,14 @@ withDefaults(
|
||||
</div>
|
||||
<p
|
||||
v-if="description"
|
||||
class="mt-0 mb-2 text-xs leading-[1.35] font-[650] text-(--cp-text-muted)"
|
||||
class="mt-0 mb-2 text-xs leading-[1.35] font-emphasis text-(--cp-text-muted)"
|
||||
>
|
||||
{{ description }}
|
||||
</p>
|
||||
<div class="min-w-0">
|
||||
<slot />
|
||||
</div>
|
||||
<p v-if="error" class="mt-2 mb-0 text-xs leading-[1.35] font-[650] text-(--cp-danger-text)">
|
||||
<p v-if="error" class="mt-2 mb-0 text-xs leading-[1.35] font-emphasis text-(--cp-danger-text)">
|
||||
{{ error }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -52,7 +52,7 @@ const iconClasses = computed(() => [
|
||||
])
|
||||
|
||||
const inputClasses = computed(() => [
|
||||
'h-full min-w-0 flex-1 border-0 bg-transparent text-[13px] font-[650] leading-[1.15] outline-0',
|
||||
'h-full min-w-0 flex-1 border-0 bg-transparent text-[13px] font-emphasis leading-[1.15] outline-0',
|
||||
'placeholder:text-(--cp-text-muted) disabled:cursor-not-allowed disabled:text-(--cp-disabled-text)',
|
||||
props.error
|
||||
? 'text-(--cp-danger-text)'
|
||||
@@ -85,7 +85,7 @@ const inputClasses = computed(() => [
|
||||
<slot name="suffix" />
|
||||
</span>
|
||||
</span>
|
||||
<span v-if="error" class="text-xs font-[650] leading-[1.15] text-(--cp-danger-text)">{{
|
||||
<span v-if="error" class="text-xs font-emphasis leading-[1.15] text-(--cp-danger-text)">{{
|
||||
error
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
@@ -212,7 +212,7 @@ onBeforeUnmount(() => {
|
||||
</slot>
|
||||
</span>
|
||||
<div class="min-w-0" :class="variant === 'default' ? 'col-span-2' : ''">
|
||||
<h2 class="m-0 text-lg leading-[1.15] font-[760] text-(--cp-text-primary)">
|
||||
<h2 class="m-0 text-lg leading-[1.15] font-heavy text-(--cp-text-primary)">
|
||||
{{ title }}
|
||||
</h2>
|
||||
<p
|
||||
|
||||
@@ -64,7 +64,7 @@ function selectOption(value: string) {
|
||||
<button
|
||||
v-for="option in options"
|
||||
:key="option.value"
|
||||
class="relative z-10 inline-flex min-w-0 items-center justify-center gap-1.5 rounded-(--cp-input-radius-base) border-0 bg-transparent px-3 text-xs leading-none font-[650] transition-colors duration-150 outline-none focus-visible:ring-2 focus-visible:ring-(--cp-info-border)"
|
||||
class="relative z-10 inline-flex min-w-0 items-center justify-center gap-1.5 rounded-(--cp-input-radius-base) border-0 bg-transparent px-3 text-xs leading-none font-emphasis transition-colors duration-150 outline-none focus-visible:ring-2 focus-visible:ring-(--cp-info-border)"
|
||||
:class="[
|
||||
size === 'input' ? 'h-8' : 'h-7',
|
||||
model === option.value
|
||||
|
||||
@@ -70,7 +70,7 @@ const sizeConfig: Record<
|
||||
const selectedOption = computed(() => props.options.find(option => option.value === model.value))
|
||||
|
||||
const triggerClasses = computed(() => [
|
||||
'relative inline-flex w-full min-w-0 items-center gap-2 overflow-visible border-0 text-left font-[650] leading-none shadow-(--cp-shadow-input) outline-none transition-[background-color,box-shadow,color] duration-[160ms]',
|
||||
'relative inline-flex w-full min-w-0 items-center gap-2 overflow-visible border-0 text-left font-emphasis leading-none shadow-(--cp-shadow-input) outline-none transition-[background-color,box-shadow,color] duration-[160ms]',
|
||||
sizeConfig[props.size].trigger,
|
||||
props.disabled
|
||||
? 'cursor-not-allowed bg-(--cp-disabled-bg) text-(--cp-disabled-text) shadow-none'
|
||||
@@ -228,7 +228,7 @@ function handleTriggerKeydown(event: KeyboardEvent) {
|
||||
|
||||
function optionClasses(option: SelectOption, index: number) {
|
||||
return [
|
||||
'flex w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 px-3 text-left font-[650] leading-none outline-none transition-colors',
|
||||
'flex w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 px-3 text-left font-emphasis leading-none outline-none transition-colors',
|
||||
sizeConfig[props.size].option,
|
||||
option.disabled
|
||||
? 'cursor-not-allowed bg-transparent text-(--cp-disabled-text)'
|
||||
@@ -315,7 +315,7 @@ useEventListener(window, 'scroll', updatePopoverPositionThrottled, { capture: tr
|
||||
>
|
||||
<div
|
||||
v-if="options.length === 0"
|
||||
class="flex h-8.5 items-center rounded-(--cp-input-radius-small) px-3 text-[13px] leading-none font-[650] text-(--cp-text-muted)"
|
||||
class="flex h-8.5 items-center rounded-(--cp-input-radius-small) px-3 text-[13px] leading-none font-emphasis text-(--cp-text-muted)"
|
||||
>
|
||||
{{ emptyText }}
|
||||
</div>
|
||||
|
||||
@@ -60,7 +60,7 @@ function paginationButtonClass(disabled: boolean) {
|
||||
|
||||
function paginationPageClass(page: number) {
|
||||
return [
|
||||
'inline-flex size-8 items-center justify-center rounded-(--cp-input-radius-base) border-0 text-xs font-[720] leading-none transition-colors duration-150 outline-none',
|
||||
'inline-flex size-8 items-center justify-center rounded-(--cp-input-radius-base) border-0 text-xs font-bold leading-none transition-colors duration-150 outline-none',
|
||||
page === currentPage.value
|
||||
? 'cursor-default bg-(--cp-info) text-(--cp-info-on)'
|
||||
: 'cursor-pointer bg-(--cp-bg-subtle) text-(--cp-text-primary) hover:bg-(--cp-default-bg-hover) focus-visible:ring-2 focus-visible:ring-(--cp-info-border) focus-visible:ring-offset-2 focus-visible:ring-offset-(--cp-bg-surface)',
|
||||
@@ -73,7 +73,7 @@ function paginationPageClass(page: number) {
|
||||
class="mt-2 flex min-h-10 shrink-0 flex-wrap items-center justify-between gap-3 px-0 py-1"
|
||||
>
|
||||
<div
|
||||
class="flex min-w-0 items-center gap-2.5 text-[12px] font-[650] text-(--cp-text-secondary)"
|
||||
class="flex min-w-0 items-center gap-2.5 text-[12px] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
<span class="whitespace-nowrap">共 {{ pagination.total }} 条</span>
|
||||
</div>
|
||||
@@ -103,7 +103,7 @@ function paginationPageClass(page: number) {
|
||||
<template v-for="(item, index) in pagerItems" :key="`${item}-${index}`">
|
||||
<span
|
||||
v-if="item === 'ellipsis'"
|
||||
class="inline-flex size-8 items-center justify-center text-xs font-[720] text-(--cp-text-muted)"
|
||||
class="inline-flex size-8 items-center justify-center text-xs font-bold text-(--cp-text-muted)"
|
||||
>
|
||||
...
|
||||
</span>
|
||||
|
||||
@@ -35,7 +35,7 @@ const textareaClasses = computed(() => [
|
||||
'hover:bg-[var(--cp-input-current-bg-hover,var(--cp-input-context-bg-hover))] hover:shadow-(--cp-shadow-input-hover) focus:bg-(--cp-input-soft-bg-focus) focus:shadow-(--cp-shadow-input-focus)',
|
||||
'disabled:cursor-not-allowed disabled:bg-(--cp-disabled-bg) disabled:text-(--cp-disabled-text) disabled:shadow-none',
|
||||
sizeClasses[props.size],
|
||||
'text-[13px] leading-[1.55] font-[650]',
|
||||
'text-[13px] leading-[1.55] font-emphasis',
|
||||
props.error ? 'bg-(--cp-input-error-soft-bg) shadow-(--cp-shadow-input-error)' : undefined,
|
||||
])
|
||||
</script>
|
||||
@@ -51,7 +51,7 @@ const textareaClasses = computed(() => [
|
||||
:aria-label="ariaLabel"
|
||||
:aria-invalid="error ? 'true' : undefined"
|
||||
/>
|
||||
<span v-if="error" class="text-xs leading-[1.15] font-[650] text-(--cp-danger-text)">
|
||||
<span v-if="error" class="text-xs leading-[1.15] font-emphasis text-(--cp-danger-text)">
|
||||
{{ error }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,7 @@ const PANEL_CLASS = [
|
||||
'pl-3',
|
||||
'text-xs',
|
||||
'leading-[1.15]',
|
||||
'font-[760]',
|
||||
'font-heavy',
|
||||
'text-(--cp-text-secondary)',
|
||||
].join(' ')
|
||||
const MARK_CLASS = [
|
||||
|
||||
@@ -53,15 +53,15 @@ const linkItems = [
|
||||
<div class="grid gap-5">
|
||||
<section class="flex min-w-0 items-center gap-3">
|
||||
<span
|
||||
class="inline-flex size-9 shrink-0 items-center justify-center rounded-(--cp-icon-button-radius) bg-(--cp-bg-subtle) font-mono text-[15px] leading-none font-[820] text-(--cp-text-primary)"
|
||||
class="inline-flex size-9 shrink-0 items-center justify-center rounded-(--cp-icon-button-radius) bg-(--cp-bg-subtle) font-mono text-[15px] leading-none font-extrabold text-(--cp-text-primary)"
|
||||
>
|
||||
Z
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
<p class="m-0 truncate text-[15px] leading-none font-[780] text-(--cp-text-primary)">
|
||||
<p class="m-0 truncate text-[15px] leading-none font-heavy text-(--cp-text-primary)">
|
||||
{{ author }}
|
||||
</p>
|
||||
<p class="mt-1.5 mb-0 text-[12px] leading-none font-[650] text-(--cp-text-secondary)">
|
||||
<p class="mt-1.5 mb-0 text-[12px] leading-none font-emphasis text-(--cp-text-secondary)">
|
||||
Built by Zyy · Codex Proxy RS
|
||||
</p>
|
||||
</div>
|
||||
@@ -80,11 +80,11 @@ const linkItems = [
|
||||
<component :is="item.icon" class="size-5" />
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
<p class="m-0 text-[11px] leading-none font-[760] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[11px] leading-none font-heavy text-(--cp-text-muted)">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<p
|
||||
class="mt-2 mb-0 truncate font-mono text-[12px] leading-none font-[720] text-(--cp-text-primary)"
|
||||
class="mt-2 mb-0 truncate font-mono text-[12px] leading-none font-bold text-(--cp-text-primary)"
|
||||
:title="item.value"
|
||||
>
|
||||
{{ item.value }}
|
||||
@@ -104,7 +104,7 @@ const linkItems = [
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p class="m-0 font-mono text-[11px] leading-none font-[650] text-(--cp-text-muted)">
|
||||
<p class="m-0 font-mono text-[11px] leading-none font-emphasis text-(--cp-text-muted)">
|
||||
{{ versionLine }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -353,17 +353,17 @@ onBeforeUnmount(() => {
|
||||
ref="brandLabelEl"
|
||||
class="grid min-w-33 content-center overflow-hidden"
|
||||
>
|
||||
<strong class="text-base leading-[1.1] font-[760] text-(--cp-text-primary)">
|
||||
<strong class="text-base leading-[1.1] font-heavy text-(--cp-text-primary)">
|
||||
Codex Proxy
|
||||
</strong>
|
||||
<span class="mt-1.5 flex h-4.5 min-w-0 items-center gap-2">
|
||||
<span class="shrink-0 text-xs leading-none font-[650] text-(--cp-text-secondary)">
|
||||
<span class="shrink-0 text-xs leading-none font-emphasis text-(--cp-text-secondary)">
|
||||
Rust build
|
||||
</span>
|
||||
<button
|
||||
v-if="hasVersionLabel"
|
||||
type="button"
|
||||
class="inline-flex h-4.5 min-w-0 cursor-pointer items-center gap-1 rounded-(--cp-input-radius-small) border-0 px-1.5 font-mono text-[10px] leading-none font-[720] transition-colors outline-none focus-visible:ring-2 focus-visible:ring-(--cp-info-border) focus-visible:ring-offset-2 focus-visible:ring-offset-(--cp-bg-surface)"
|
||||
class="inline-flex h-4.5 min-w-0 cursor-pointer items-center gap-1 rounded-(--cp-input-radius-small) border-0 px-1.5 font-mono text-[10px] leading-none font-bold transition-colors outline-none focus-visible:ring-2 focus-visible:ring-(--cp-info-border) focus-visible:ring-offset-2 focus-visible:ring-offset-(--cp-bg-surface)"
|
||||
:class="[
|
||||
hasUpdate
|
||||
? 'bg-(--cp-success-bg) text-(--cp-success-text) hover:bg-(--cp-success-bg-hover)'
|
||||
@@ -427,7 +427,7 @@ onBeforeUnmount(() => {
|
||||
>
|
||||
<span
|
||||
v-if="!isCollapsed"
|
||||
class="inline-flex whitespace-nowrap h-7 items-center gap-1.5 rounded-lg bg-(--cp-success-bg) px-2.5 text-xs leading-none font-[650] text-(--cp-success-text)"
|
||||
class="inline-flex whitespace-nowrap h-7 items-center gap-1.5 rounded-lg bg-(--cp-success-bg) px-2.5 text-xs leading-none font-emphasis text-(--cp-success-text)"
|
||||
>
|
||||
<i class="size-1.5 rounded-full bg-(--cp-success)" />
|
||||
在线
|
||||
|
||||
@@ -328,15 +328,15 @@ watch(
|
||||
<section class="grid gap-4 rounded-(--cp-card-radius) bg-(--cp-bg-subtle) px-4 py-4">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<div class="min-w-0">
|
||||
<p class="m-0 text-[11px] leading-none font-[760] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[11px] leading-none font-heavy text-(--cp-text-muted)">
|
||||
Codex Proxy RS
|
||||
</p>
|
||||
<p class="mt-2 mb-0 text-lg leading-none font-[780] text-(--cp-text-primary)">
|
||||
<p class="mt-2 mb-0 text-lg leading-none font-heavy text-(--cp-text-primary)">
|
||||
应用包更新
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
class="inline-flex h-7 shrink-0 items-center gap-1.5 rounded-full px-2.5 text-[12px] font-[760]"
|
||||
class="inline-flex h-7 shrink-0 items-center gap-1.5 rounded-full px-2.5 text-[12px] font-heavy"
|
||||
:class="statusView.badge"
|
||||
>
|
||||
<component :is="statusView.icon" class="size-3.5" :class="statusView.iconClass" />
|
||||
@@ -351,7 +351,7 @@ watch(
|
||||
class="min-w-0 rounded-(--cp-input-radius-base) bg-(--cp-bg-surface) px-3 py-2.5"
|
||||
>
|
||||
<div class="flex min-w-0 items-center justify-between gap-2">
|
||||
<p class="m-0 truncate text-[11px] leading-none font-[760] text-(--cp-text-muted)">
|
||||
<p class="m-0 truncate text-[11px] leading-none font-heavy text-(--cp-text-muted)">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<a
|
||||
@@ -359,14 +359,14 @@ watch(
|
||||
:href="item.releaseUrl"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
class="inline-flex shrink-0 items-center gap-1 text-[11px] leading-none font-[720] text-(--cp-info-text) transition-colors hover:text-(--cp-info)"
|
||||
class="inline-flex shrink-0 items-center gap-1 text-[11px] leading-none font-bold text-(--cp-info-text) transition-colors hover:text-(--cp-info)"
|
||||
>
|
||||
发布页
|
||||
<ExternalLink class="size-3" />
|
||||
</a>
|
||||
</div>
|
||||
<p
|
||||
class="mt-2 mb-0 truncate font-mono text-[13px] leading-none font-[720] text-(--cp-text-primary)"
|
||||
class="mt-2 mb-0 truncate font-mono text-[13px] leading-none font-bold text-(--cp-text-primary)"
|
||||
:title="item.title || item.value"
|
||||
>
|
||||
{{ item.value }}
|
||||
@@ -376,7 +376,7 @@ watch(
|
||||
|
||||
<p
|
||||
v-if="updateError || updateInfo?.warning"
|
||||
class="m-0 rounded-(--cp-input-radius-base) bg-(--cp-danger-bg) px-3 py-2 text-[12px] leading-normal font-[720] text-(--cp-danger-text)"
|
||||
class="m-0 rounded-(--cp-input-radius-base) bg-(--cp-danger-bg) px-3 py-2 text-[12px] leading-normal font-bold text-(--cp-danger-text)"
|
||||
>
|
||||
{{ updateError || updateInfo?.warning }}
|
||||
</p>
|
||||
@@ -387,10 +387,10 @@ watch(
|
||||
class="grid gap-2 rounded-(--cp-card-radius) bg-(--cp-bg-subtle) px-4 py-3.5"
|
||||
>
|
||||
<div class="flex items-center justify-between gap-3">
|
||||
<p class="m-0 text-[13px] font-[760] text-(--cp-text-primary)">
|
||||
<p class="m-0 text-[13px] font-heavy text-(--cp-text-primary)">
|
||||
发布说明
|
||||
</p>
|
||||
<span class="font-mono text-[11px] font-[650] text-(--cp-text-muted)">
|
||||
<span class="font-mono text-[11px] font-emphasis text-(--cp-text-muted)">
|
||||
{{ displayValue(updateInfo?.latestVersion) }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -406,12 +406,12 @@ watch(
|
||||
<header class="flex items-center justify-between gap-3 px-4 pt-3.5 pb-2.5">
|
||||
<div class="flex min-w-0 items-center gap-2">
|
||||
<Terminal class="size-4 shrink-0 text-(--cp-success)" />
|
||||
<p class="m-0 text-[13px] leading-none font-[760] text-(--cp-text-primary)">
|
||||
<p class="m-0 text-[13px] leading-none font-heavy text-(--cp-text-primary)">
|
||||
更新进度
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
class="inline-flex h-6 items-center gap-1.5 rounded-full bg-(--cp-bg-subtle) px-2 text-[11px] leading-none font-[720] text-(--cp-text-secondary)"
|
||||
class="inline-flex h-6 items-center gap-1.5 rounded-full bg-(--cp-bg-subtle) px-2 text-[11px] leading-none font-bold text-(--cp-text-secondary)"
|
||||
:title="updateStreamError || streamStatusLabel"
|
||||
>
|
||||
<i
|
||||
@@ -509,17 +509,17 @@ watch(
|
||||
:key="item.key"
|
||||
class="flex min-w-0 items-center justify-between gap-3"
|
||||
>
|
||||
<span class="text-[12px] leading-none font-[720] text-(--cp-text-muted)">
|
||||
<span class="text-[12px] leading-none font-bold text-(--cp-text-muted)">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
<span
|
||||
class="truncate font-mono text-[13px] leading-none font-[760] text-(--cp-text-primary)"
|
||||
class="truncate font-mono text-[13px] leading-none font-heavy text-(--cp-text-primary)"
|
||||
>
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="m-0 text-[12px] leading-relaxed font-[650] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[12px] leading-relaxed font-emphasis text-(--cp-text-muted)">
|
||||
点击确认后弹窗会关闭,并按远端最新目标版本开始更新
|
||||
</p>
|
||||
</div>
|
||||
@@ -530,7 +530,7 @@ watch(
|
||||
.release-notes {
|
||||
color: var(--cp-text-primary);
|
||||
font-size: 12px;
|
||||
font-weight: 620;
|
||||
font-weight: var(--font-weight-emphasis);
|
||||
line-height: 1.65;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
@@ -554,7 +554,7 @@ watch(
|
||||
margin: 12px 0 6px;
|
||||
color: var(--cp-text-primary);
|
||||
font-size: 12px;
|
||||
font-weight: 780;
|
||||
font-weight: var(--font-weight-heavy);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
@@ -574,7 +574,7 @@ watch(
|
||||
|
||||
.release-notes :deep(a) {
|
||||
color: var(--cp-info-text);
|
||||
font-weight: 720;
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
--font-sans:
|
||||
'Inter Variable', Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
--font-mono: 'JetBrains Mono Variable', 'JetBrains Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', monospace;
|
||||
/* 界面字重刻度:正文强调 650 / 加粗 700(font-bold) / 重标题 760 / 极重 800(font-extrabold)。
|
||||
新代码从这四档取值,不再使用任意字重。 */
|
||||
--font-weight-emphasis: 650;
|
||||
--font-weight-heavy: 760;
|
||||
--color-cp-page: var(--cp-bg-page);
|
||||
--color-cp-surface: var(--cp-bg-surface);
|
||||
--color-cp-subtle: var(--cp-bg-subtle);
|
||||
|
||||
@@ -63,7 +63,7 @@ function connectionLogClass(tone: string) {
|
||||
<section class="rounded-(--cp-card-radius) bg-(--cp-bg-subtle) px-4 py-3">
|
||||
<div class="grid gap-2">
|
||||
<div class="flex min-h-8 items-center justify-between gap-3">
|
||||
<span class="text-[12px] font-[760] text-(--cp-text-muted)">
|
||||
<span class="text-[12px] font-heavy text-(--cp-text-muted)">
|
||||
测试模型
|
||||
</span>
|
||||
<BaseButton
|
||||
@@ -105,18 +105,18 @@ function connectionLogClass(tone: string) {
|
||||
/>
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
<p class="m-0 text-[16px] font-[780] text-(--cp-text-primary)">
|
||||
<p class="m-0 text-[16px] font-heavy text-(--cp-text-primary)">
|
||||
{{ statusView.label }}
|
||||
</p>
|
||||
<p
|
||||
class="mt-1.5 mb-0 text-[13px] leading-normal font-[650] text-(--cp-text-secondary)"
|
||||
class="mt-1.5 mb-0 text-[13px] leading-normal font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
{{ statusView.description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="inline-flex h-7 shrink-0 items-center rounded-full px-2.5 text-[12px] font-[760]"
|
||||
class="inline-flex h-7 shrink-0 items-center rounded-full px-2.5 text-[12px] font-heavy"
|
||||
:class="statusView.badge"
|
||||
>
|
||||
{{ status === 'running' ? '检测中' : statusView.label }}
|
||||
@@ -125,37 +125,37 @@ function connectionLogClass(tone: string) {
|
||||
|
||||
<div class="mt-4 grid gap-3 sm:grid-cols-3">
|
||||
<div class="rounded-lg bg-(--cp-bg-surface) px-3 py-2.5">
|
||||
<p class="m-0 text-[11px] font-[760] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[11px] font-heavy text-(--cp-text-muted)">
|
||||
开始时间
|
||||
</p>
|
||||
<p class="mt-1.5 mb-0 font-mono text-[12px] font-[650] text-(--cp-text-primary)">
|
||||
<p class="mt-1.5 mb-0 font-mono text-[12px] font-emphasis text-(--cp-text-primary)">
|
||||
{{ startedAt || '-' }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded-lg bg-(--cp-bg-surface) px-3 py-2.5">
|
||||
<p class="m-0 text-[11px] font-[760] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[11px] font-heavy text-(--cp-text-muted)">
|
||||
完成时间
|
||||
</p>
|
||||
<p class="mt-1.5 mb-0 font-mono text-[12px] font-[650] text-(--cp-text-primary)">
|
||||
<p class="mt-1.5 mb-0 font-mono text-[12px] font-emphasis text-(--cp-text-primary)">
|
||||
{{ finishedAt || '-' }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="rounded-lg bg-(--cp-bg-surface) px-3 py-2.5">
|
||||
<p class="m-0 text-[11px] font-[760] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[11px] font-heavy text-(--cp-text-muted)">
|
||||
响应耗时
|
||||
</p>
|
||||
<p class="mt-1.5 mb-0 font-mono text-[12px] font-[650] text-(--cp-text-primary)">
|
||||
<p class="mt-1.5 mb-0 font-mono text-[12px] font-emphasis text-(--cp-text-primary)">
|
||||
{{ durationMs !== null ? `${durationMs}ms` : '-' }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 rounded-lg bg-(--cp-bg-surface) px-3 py-2.5">
|
||||
<p class="m-0 text-[11px] font-[760] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[11px] font-heavy text-(--cp-text-muted)">
|
||||
测试模型
|
||||
</p>
|
||||
<p
|
||||
class="mt-1.5 mb-0 truncate font-mono text-[12px] font-[650] text-(--cp-text-primary)"
|
||||
class="mt-1.5 mb-0 truncate font-mono text-[12px] font-emphasis text-(--cp-text-primary)"
|
||||
:title="model || '-'"
|
||||
>
|
||||
{{ model || '-' }}
|
||||
@@ -163,18 +163,18 @@ function connectionLogClass(tone: string) {
|
||||
</div>
|
||||
|
||||
<div class="mt-3 rounded-lg bg-(--cp-bg-surface) px-3 py-2.5">
|
||||
<p class="m-0 text-[11px] font-[760] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[11px] font-heavy text-(--cp-text-muted)">
|
||||
事件轨迹
|
||||
</p>
|
||||
<BaseScrollbar max-height="260px" view-class="pt-2 pr-2">
|
||||
<div v-if="logs.length === 0" class="text-[12px] font-[650] text-(--cp-text-muted)">
|
||||
<div v-if="logs.length === 0" class="text-[12px] font-emphasis text-(--cp-text-muted)">
|
||||
-
|
||||
</div>
|
||||
<div v-else class="flex flex-col gap-1.5">
|
||||
<div
|
||||
v-for="item in logs"
|
||||
:key="item.key"
|
||||
class="grid grid-cols-[54px_minmax(0,1fr)] gap-2 text-[12px] leading-[1.45] font-[650]"
|
||||
class="grid grid-cols-[54px_minmax(0,1fr)] gap-2 text-[12px] leading-[1.45] font-emphasis"
|
||||
>
|
||||
<span class="font-mono text-(--cp-text-muted)">{{ item.time }}</span>
|
||||
<div class="min-w-0">
|
||||
@@ -184,7 +184,7 @@ function connectionLogClass(tone: string) {
|
||||
<div v-if="item.detail" class="mt-2 rounded-lg bg-(--cp-bg-subtle) px-3 py-2">
|
||||
<BaseScrollbar max-height="138px" view-class="pr-2">
|
||||
<pre
|
||||
class="m-0 whitespace-pre-wrap wrap-break-word font-mono text-[11px] leading-[1.6] font-[620] text-(--cp-text-primary)"
|
||||
class="m-0 whitespace-pre-wrap wrap-break-word font-mono text-[11px] leading-[1.6] font-emphasis text-(--cp-text-primary)"
|
||||
>{{ item.detail }}</pre>
|
||||
</BaseScrollbar>
|
||||
</div>
|
||||
@@ -195,12 +195,12 @@ function connectionLogClass(tone: string) {
|
||||
</div>
|
||||
|
||||
<div v-if="error" class="mt-3 rounded-lg bg-(--cp-danger-bg) px-3 py-2.5">
|
||||
<p class="m-0 text-[11px] font-[760] text-(--cp-danger-text)">
|
||||
<p class="m-0 text-[11px] font-heavy text-(--cp-danger-text)">
|
||||
错误信息
|
||||
</p>
|
||||
<BaseScrollbar max-height="118px" view-class="pt-1.5 pr-2">
|
||||
<p
|
||||
class="m-0 wrap-break-word text-[12px] leading-[1.55] font-[650] text-(--cp-danger-text)"
|
||||
class="m-0 wrap-break-word text-[12px] leading-[1.55] font-emphasis text-(--cp-danger-text)"
|
||||
>
|
||||
{{ error }}
|
||||
</p>
|
||||
|
||||
@@ -227,7 +227,7 @@ async function copyText(value: string, successText: string) {
|
||||
<KeyRound class="size-4" />
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<p class="m-0 text-[13px] font-[720] text-(--cp-text-primary)">
|
||||
<p class="m-0 text-[13px] font-bold text-(--cp-text-primary)">
|
||||
{{ oauthPanelTitle }}
|
||||
</p>
|
||||
<p class="m-0 mt-1 text-[12px] leading-[1.55] font-medium text-(--cp-text-secondary)">
|
||||
@@ -268,7 +268,7 @@ async function copyText(value: string, successText: string) {
|
||||
view-class="rounded-(--cp-input-radius-base) bg-(--cp-input-current-bg,var(--cp-input-context-bg)) px-3.5 py-3 shadow-(--cp-shadow-input)"
|
||||
>
|
||||
<pre
|
||||
class="m-0 whitespace-pre-wrap wrap-break-word font-mono text-[12px] leading-[1.6] font-[650] text-(--cp-text-secondary)"
|
||||
class="m-0 whitespace-pre-wrap wrap-break-word font-mono text-[12px] leading-[1.6] font-emphasis text-(--cp-text-secondary)"
|
||||
>{{ oauthAuthUrl }}</pre>
|
||||
</BaseScrollbar>
|
||||
</BaseFormItem>
|
||||
|
||||
@@ -70,14 +70,14 @@ const avatarClass = computed(() => {
|
||||
<template>
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<span
|
||||
class="inline-flex shrink-0 items-center justify-center rounded-lg font-[820]"
|
||||
class="inline-flex shrink-0 items-center justify-center rounded-lg font-extrabold"
|
||||
:class="[avatarSizeClass, avatarClass]"
|
||||
>
|
||||
{{ initial }}
|
||||
</span>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex min-w-0 items-center gap-2">
|
||||
<span class="min-w-0 flex-1 truncate text-[14px] font-[760] text-(--cp-text-primary)">
|
||||
<span class="min-w-0 flex-1 truncate text-[14px] font-heavy text-(--cp-text-primary)">
|
||||
{{ displayTitle }}
|
||||
</span>
|
||||
<span
|
||||
@@ -95,7 +95,7 @@ const avatarClass = computed(() => {
|
||||
<slot name="meta" />
|
||||
<AccountPlanBadge v-if="showPlan" :plan-type="account.planType" size="sm" />
|
||||
</div>
|
||||
<div v-else-if="secondaryText" class="truncate font-[650]" :class="secondaryClass">
|
||||
<div v-else-if="secondaryText" class="truncate font-emphasis" :class="secondaryClass">
|
||||
{{ secondaryText }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -70,15 +70,15 @@ function overviewIconClass(tone: string) {
|
||||
>
|
||||
<div class="flex h-full items-stretch justify-between gap-3 px-5 py-3">
|
||||
<div class="flex min-w-0 flex-col justify-between">
|
||||
<p class="m-0 text-[12px] leading-none font-[760] text-(--cp-text-secondary)">
|
||||
<p class="m-0 text-[12px] leading-none font-heavy text-(--cp-text-secondary)">
|
||||
{{ item.label }}
|
||||
</p>
|
||||
<strong
|
||||
class="block font-mono text-[26px] leading-none font-[820] text-(--cp-text-primary)"
|
||||
class="block font-mono text-[26px] leading-none font-extrabold text-(--cp-text-primary)"
|
||||
>
|
||||
{{ item.value }}
|
||||
</strong>
|
||||
<p class="m-0 truncate text-[12px] leading-none font-[650] text-(--cp-text-muted)">
|
||||
<p class="m-0 truncate text-[12px] leading-none font-emphasis text-(--cp-text-muted)">
|
||||
{{ item.caption }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -23,8 +23,8 @@ const label = computed(() => props.planType?.trim() || 'Free')
|
||||
|
||||
const sizeClass = computed(() =>
|
||||
props.size === 'sm'
|
||||
? 'h-5 rounded-full px-1.75 text-[11px] font-[720]'
|
||||
: 'h-5.5 rounded-full px-2 text-[11px] font-[760]',
|
||||
? 'h-5 rounded-full px-1.75 text-[11px] font-bold'
|
||||
: 'h-5.5 rounded-full px-2 text-[11px] font-heavy',
|
||||
)
|
||||
|
||||
const paletteClass = computed(() => {
|
||||
|
||||
@@ -24,11 +24,11 @@ const quotaWindows = computed(() => orderedPanelQuotaWindows(props.account.quota
|
||||
<section class="rounded-lg bg-(--cp-bg-surface) p-4 shadow-(--cp-shadow-control)">
|
||||
<div class="mb-3 flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<h3 class="m-0 text-[14px] font-[760] text-(--cp-text-primary)">
|
||||
<h3 class="m-0 text-[14px] font-heavy text-(--cp-text-primary)">
|
||||
账号额度
|
||||
</h3>
|
||||
<p
|
||||
class="m-0 mt-1 flex flex-wrap items-center gap-x-1.5 gap-y-1 text-[12px] font-[620] text-(--cp-text-secondary)"
|
||||
class="m-0 mt-1 flex flex-wrap items-center gap-x-1.5 gap-y-1 text-[12px] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
<span>{{ account.provider === 'xai' ? 'xAI 用量窗口' : 'Codex 额度' }}</span>
|
||||
<template v-if="account.provider === 'openai'">
|
||||
|
||||
@@ -52,14 +52,14 @@ const dotClass = computed(() => {
|
||||
<template>
|
||||
<span
|
||||
v-if="variant === 'pill'"
|
||||
class="inline-flex h-7 shrink-0 items-center rounded-full px-2.5 text-[12px] font-[760]"
|
||||
class="inline-flex h-7 shrink-0 items-center rounded-full px-2.5 text-[12px] font-heavy"
|
||||
:class="textClass"
|
||||
>
|
||||
{{ label }}
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
class="inline-flex min-w-16 items-center gap-1.5 text-[12px] leading-none font-[650]"
|
||||
class="inline-flex min-w-16 items-center gap-1.5 text-[12px] leading-none font-emphasis"
|
||||
:class="textClass"
|
||||
>
|
||||
<span class="size-1.5 rounded-full" :class="dotClass" />
|
||||
|
||||
@@ -54,7 +54,7 @@ const canReauthorize = computed(() => props.account.provider === 'openai')
|
||||
<template #default="{ close }">
|
||||
<button
|
||||
type="button"
|
||||
class="flex h-8.5 w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 bg-transparent px-3 text-left text-[13px] leading-none font-[650] text-(--cp-text-primary) transition-colors hover:bg-(--cp-default-bg-hover) disabled:cursor-not-allowed disabled:text-(--cp-disabled-text)"
|
||||
class="flex h-8.5 w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 bg-transparent px-3 text-left text-[13px] leading-none font-emphasis text-(--cp-text-primary) transition-colors hover:bg-(--cp-default-bg-hover) disabled:cursor-not-allowed disabled:text-(--cp-disabled-text)"
|
||||
:disabled="testing"
|
||||
@click.stop="(close(), emit('test', account))"
|
||||
>
|
||||
@@ -65,7 +65,7 @@ const canReauthorize = computed(() => props.account.provider === 'openai')
|
||||
<button
|
||||
v-if="canRefreshToken"
|
||||
type="button"
|
||||
class="flex h-8.5 w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 bg-transparent px-3 text-left text-[13px] leading-none font-[650] text-(--cp-text-primary) transition-colors hover:bg-(--cp-default-bg-hover) disabled:cursor-not-allowed disabled:text-(--cp-disabled-text)"
|
||||
class="flex h-8.5 w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 bg-transparent px-3 text-left text-[13px] leading-none font-emphasis text-(--cp-text-primary) transition-colors hover:bg-(--cp-default-bg-hover) disabled:cursor-not-allowed disabled:text-(--cp-disabled-text)"
|
||||
:disabled="refreshing"
|
||||
@click.stop="(close(), emit('refresh', account.id))"
|
||||
>
|
||||
@@ -78,7 +78,7 @@ const canReauthorize = computed(() => props.account.provider === 'openai')
|
||||
<button
|
||||
v-if="canReauthorize"
|
||||
type="button"
|
||||
class="flex h-8.5 w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 bg-transparent px-3 text-left text-[13px] leading-none font-[650] text-(--cp-text-primary) transition-colors hover:bg-(--cp-default-bg-hover)"
|
||||
class="flex h-8.5 w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 bg-transparent px-3 text-left text-[13px] leading-none font-emphasis text-(--cp-text-primary) transition-colors hover:bg-(--cp-default-bg-hover)"
|
||||
@click.stop="(close(), emit('reauthorize', account))"
|
||||
>
|
||||
<KeyRound class="size-3.5 text-(--cp-text-muted)" />
|
||||
@@ -86,7 +86,7 @@ const canReauthorize = computed(() => props.account.provider === 'openai')
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex h-8.5 w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 bg-transparent px-3 text-left text-[13px] leading-none font-[650] text-(--cp-text-primary) transition-colors hover:bg-(--cp-default-bg-hover) disabled:cursor-not-allowed disabled:text-(--cp-disabled-text)"
|
||||
class="flex h-8.5 w-full items-center gap-2 rounded-(--cp-input-radius-small) border-0 bg-transparent px-3 text-left text-[13px] leading-none font-emphasis text-(--cp-text-primary) transition-colors hover:bg-(--cp-default-bg-hover) disabled:cursor-not-allowed disabled:text-(--cp-disabled-text)"
|
||||
:disabled="updatingStatus"
|
||||
@click.stop="(close(), emit('toggleSchedule', account))"
|
||||
>
|
||||
|
||||
@@ -11,7 +11,7 @@ defineProps<{
|
||||
class="grid gap-4 rounded-lg bg-(--cp-bg-surface) p-4 shadow-(--cp-shadow-control) xl:grid-cols-[0.52fr_1.48fr]"
|
||||
>
|
||||
<div>
|
||||
<h3 class="m-0 mb-3 text-[14px] font-[760] text-(--cp-text-primary)">
|
||||
<h3 class="m-0 mb-3 text-[14px] font-heavy text-(--cp-text-primary)">
|
||||
Token 结构
|
||||
</h3>
|
||||
<div class="grid gap-2">
|
||||
@@ -52,13 +52,13 @@ defineProps<{
|
||||
class="min-w-0 pt-4 shadow-[inset_0_1px_0_var(--cp-divider-subtle)] xl:pt-0 xl:pl-4 xl:shadow-[inset_1px_0_0_var(--cp-divider-subtle)]"
|
||||
>
|
||||
<div class="mb-3 flex items-center justify-between">
|
||||
<h3 class="m-0 text-[14px] font-[760] text-(--cp-text-primary)">
|
||||
<h3 class="m-0 text-[14px] font-heavy text-(--cp-text-primary)">
|
||||
模型使用排行
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="grid grid-cols-[1.2fr_0.7fr_0.8fr_1fr_1fr_1fr_1fr_1fr_1.4fr] gap-3 pb-2 text-[11px] font-[760] text-(--cp-text-secondary) shadow-[inset_0_-1px_0_var(--cp-divider-subtle)]"
|
||||
class="grid grid-cols-[1.2fr_0.7fr_0.8fr_1fr_1fr_1fr_1fr_1fr_1.4fr] gap-3 pb-2 text-[11px] font-heavy text-(--cp-text-secondary) shadow-[inset_0_-1px_0_var(--cp-divider-subtle)]"
|
||||
>
|
||||
<span>模型</span>
|
||||
<span>调用</span>
|
||||
@@ -72,7 +72,7 @@ defineProps<{
|
||||
</div>
|
||||
<div
|
||||
v-if="account.usage.models.length === 0"
|
||||
class="pt-3 text-[12px] font-[650] text-(--cp-text-muted)"
|
||||
class="pt-3 text-[12px] font-emphasis text-(--cp-text-muted)"
|
||||
>
|
||||
-
|
||||
</div>
|
||||
@@ -80,7 +80,7 @@ defineProps<{
|
||||
<div
|
||||
v-for="model in account.usage.models"
|
||||
:key="model.model"
|
||||
class="grid grid-cols-[1.2fr_0.7fr_0.8fr_1fr_1fr_1fr_1fr_1fr_1.4fr] gap-3 pt-3 text-[12px] font-[650] text-(--cp-text-primary)"
|
||||
class="grid grid-cols-[1.2fr_0.7fr_0.8fr_1fr_1fr_1fr_1fr_1fr_1.4fr] gap-3 pt-3 text-[12px] font-emphasis text-(--cp-text-primary)"
|
||||
>
|
||||
<span class="truncate">{{ model.model }}</span>
|
||||
<span>{{ model.requestCountDisplay }}</span>
|
||||
|
||||
@@ -60,16 +60,16 @@ const rootClass = computed(() =>
|
||||
)
|
||||
const headerClass = computed(() =>
|
||||
isCompact.value
|
||||
? 'mb-1 flex items-center justify-between gap-2 text-[11px] leading-none font-[720]'
|
||||
: 'flex items-center justify-between gap-3 text-[12px] font-[720]',
|
||||
? 'mb-1 flex items-center justify-between gap-2 text-[11px] leading-none font-bold'
|
||||
: 'flex items-center justify-between gap-3 text-[12px] font-bold',
|
||||
)
|
||||
const labelClass = computed(() =>
|
||||
isCompact.value ? 'text-(--cp-text-muted)' : 'text-(--cp-text-secondary)',
|
||||
)
|
||||
const valueClass = computed(() =>
|
||||
isCompact.value
|
||||
? 'text-[10px] leading-none font-[780]'
|
||||
: 'text-[12px] font-[780]',
|
||||
? 'text-[10px] leading-none font-heavy'
|
||||
: 'text-[12px] font-heavy',
|
||||
)
|
||||
const trackShapeClass = computed(() =>
|
||||
isCompact.value
|
||||
@@ -177,7 +177,7 @@ const requestBars = computed(() => {
|
||||
</div>
|
||||
<div
|
||||
v-if="!isCompact && window.resetAtDisplay !== '—'"
|
||||
class="mt-3 text-[12px] font-[620] text-(--cp-text-secondary)"
|
||||
class="mt-3 text-[12px] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
重置时间: {{ window.resetAtDisplay }}
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ defineProps<{
|
||||
<span class="text-[13px] font-bold text-(--cp-text-primary)">
|
||||
{{ apiKey.name }}
|
||||
</span>
|
||||
<span v-if="apiKey.label" class="text-[12px] font-[650] text-(--cp-text-tertiary)">
|
||||
<span v-if="apiKey.label" class="text-[12px] font-emphasis text-(--cp-text-tertiary)">
|
||||
{{ apiKey.label }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@ const emit = defineEmits<{
|
||||
|
||||
<template>
|
||||
<div class="flex items-center gap-2">
|
||||
<code class="block min-w-0 truncate font-mono text-[12px] font-[650] text-(--cp-text-primary)">
|
||||
<code class="block min-w-0 truncate font-mono text-[12px] font-emphasis text-(--cp-text-primary)">
|
||||
{{ prefix }}••••••••••••••••
|
||||
</code>
|
||||
<BaseButton
|
||||
|
||||
@@ -89,7 +89,7 @@ const visibleFiles = computed(() => [
|
||||
>
|
||||
<div class="flex items-center justify-between gap-3 px-4 py-2.5">
|
||||
<span
|
||||
class="min-w-0 truncate font-mono text-[12px] font-[650] text-(--cp-text-secondary)"
|
||||
class="min-w-0 truncate font-mono text-[12px] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
{{ file.path }}
|
||||
</span>
|
||||
@@ -108,7 +108,7 @@ const visibleFiles = computed(() => [
|
||||
view-class="mx-3 mb-3 rounded-(--cp-input-radius-base) bg-(--cp-bg-surface) px-3.5 py-3 shadow-(--cp-shadow-input)"
|
||||
>
|
||||
<pre
|
||||
class="m-0 whitespace-pre-wrap wrap-break-word font-mono text-[12px] leading-[1.65] font-[650] text-(--cp-text-primary)"
|
||||
class="m-0 whitespace-pre-wrap wrap-break-word font-mono text-[12px] leading-[1.65] font-emphasis text-(--cp-text-primary)"
|
||||
>{{ file.content }}</pre>
|
||||
</BaseScrollbar>
|
||||
</section>
|
||||
|
||||
@@ -33,7 +33,7 @@ export const apiKeyColumns = [
|
||||
sortKey: 'createdAt',
|
||||
width: '176px',
|
||||
minWidth: '176px',
|
||||
cellClass: 'font-mono text-[12px] font-[650] tabular-nums text-(--cp-text-secondary)',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis tabular-nums text-(--cp-text-secondary)',
|
||||
},
|
||||
{
|
||||
key: 'lastUsedAtDisplay',
|
||||
@@ -42,7 +42,7 @@ export const apiKeyColumns = [
|
||||
sortKey: 'lastUsedAt',
|
||||
width: '176px',
|
||||
minWidth: '176px',
|
||||
cellClass: 'font-mono text-[12px] font-[650] tabular-nums text-(--cp-text-secondary)',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis tabular-nums text-(--cp-text-secondary)',
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
|
||||
@@ -158,7 +158,7 @@ const statusBars = computed(() => {
|
||||
class="grid px-4 pt-5 pb-6 lg:px-7 lg:pt-6 xl:grid-cols-[minmax(0,0.9fr)_minmax(0,1.28fr)_minmax(280px,0.9fr)] xl:gap-7 xl:pb-0"
|
||||
>
|
||||
<section class="min-w-0 w-full pb-6 xl:h-100.5 xl:pb-0">
|
||||
<h2 class="m-0 text-xl leading-[1.15] font-[760] text-(--cp-text-primary)">
|
||||
<h2 class="m-0 text-xl leading-[1.15] font-heavy text-(--cp-text-primary)">
|
||||
账号调度
|
||||
</h2>
|
||||
<p class="mt-1.75 mb-0 text-[13px] leading-[1.15] font-semibold text-(--cp-text-secondary)">
|
||||
@@ -167,13 +167,13 @@ const statusBars = computed(() => {
|
||||
|
||||
<div class="mt-6.75 grid gap-4 xl:h-82.5 xl:grid-rows-[122px_90px_minmax(0,1fr)]">
|
||||
<div class="grid h-30.5 content-between rounded-[14px] bg-(--cp-bg-subtle) p-4 xl:h-auto">
|
||||
<span class="block h-3.5 text-xs leading-[1.15] font-[650] text-(--cp-text-secondary)">槽位占用</span>
|
||||
<span class="block h-3.5 text-xs leading-[1.15] font-emphasis text-(--cp-text-secondary)">槽位占用</span>
|
||||
<div>
|
||||
<div class="grid h-8.5 grid-cols-[minmax(0,1fr)_auto] items-start gap-4">
|
||||
<strong
|
||||
class="font-mono text-[32px] leading-[1.05] font-[760] tabular-nums text-(--cp-text-primary)"
|
||||
class="font-mono text-[32px] leading-[1.05] font-heavy tabular-nums text-(--cp-text-primary)"
|
||||
>{{ usedRatio }}</strong>
|
||||
<span class="mt-3.5 text-xs leading-[1.15] font-[650] text-(--cp-text-secondary)">
|
||||
<span class="mt-3.5 text-xs leading-[1.15] font-emphasis text-(--cp-text-secondary)">
|
||||
{{ occupancyLabel }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -190,18 +190,18 @@ const statusBars = computed(() => {
|
||||
class="grid h-22.5 grid-cols-3 gap-4 rounded-[14px] bg-(--cp-bg-subtle) p-4 xl:h-auto"
|
||||
>
|
||||
<div v-for="stat in scheduleStats" :key="stat.label" class="grid content-between">
|
||||
<span class="text-xs leading-[1.15] font-[650] text-(--cp-text-secondary)">{{
|
||||
<span class="text-xs leading-[1.15] font-emphasis text-(--cp-text-secondary)">{{
|
||||
stat.label
|
||||
}}</span>
|
||||
<strong
|
||||
class="block font-mono text-[21px] leading-[1.1] font-[760] tabular-nums text-(--cp-text-primary)"
|
||||
class="block font-mono text-[21px] leading-[1.1] font-heavy tabular-nums text-(--cp-text-primary)"
|
||||
>{{ stat.value }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid h-20.5 content-between rounded-[14px] bg-(--cp-bg-subtle) p-4 xl:h-auto">
|
||||
<span class="text-xs leading-[1.15] font-[650] text-(--cp-text-secondary)">分配策略</span>
|
||||
<strong class="block text-[17px] leading-[1.15] font-[650] text-(--cp-text-primary)">{{
|
||||
<span class="text-xs leading-[1.15] font-emphasis text-(--cp-text-secondary)">分配策略</span>
|
||||
<strong class="block text-[17px] leading-[1.15] font-emphasis text-(--cp-text-primary)">{{
|
||||
strategyLabel
|
||||
}}</strong>
|
||||
</div>
|
||||
@@ -209,7 +209,7 @@ const statusBars = computed(() => {
|
||||
</section>
|
||||
|
||||
<section class="min-w-0 w-full">
|
||||
<h2 class="m-0 text-xl leading-[1.15] font-[760] text-(--cp-text-primary)">
|
||||
<h2 class="m-0 text-xl leading-[1.15] font-heavy text-(--cp-text-primary)">
|
||||
活跃账号用量
|
||||
</h2>
|
||||
<p class="mt-1.75 mb-0 text-[13px] leading-[1.15] font-semibold text-(--cp-text-secondary)">
|
||||
@@ -252,18 +252,18 @@ const statusBars = computed(() => {
|
||||
class="grid min-w-0 grid-cols-[minmax(0,0.82fr)_minmax(0,0.64fr)_minmax(104px,1fr)] items-end gap-3 xl:contents"
|
||||
>
|
||||
<span class="grid min-w-0 gap-1">
|
||||
<span class="text-[11px] leading-none font-[720] text-(--cp-text-muted)">
|
||||
<span class="text-[11px] leading-none font-bold text-(--cp-text-muted)">
|
||||
{{ account.metricLabel }}
|
||||
</span>
|
||||
<strong
|
||||
class="font-mono text-sm leading-[1.15] font-[780] tabular-nums text-(--cp-text-primary)"
|
||||
class="font-mono text-sm leading-[1.15] font-heavy tabular-nums text-(--cp-text-primary)"
|
||||
>{{ account.metricValue }}</strong>
|
||||
</span>
|
||||
|
||||
<span class="grid min-w-0 gap-1">
|
||||
<span class="text-[11px] leading-none font-[720] text-(--cp-text-muted)">最近</span>
|
||||
<span class="text-[11px] leading-none font-bold text-(--cp-text-muted)">最近</span>
|
||||
<span
|
||||
class="min-w-0 truncate text-xs leading-[1.15] font-[680] text-(--cp-text-secondary) xl:whitespace-nowrap"
|
||||
class="min-w-0 truncate text-xs leading-[1.15] font-bold text-(--cp-text-secondary) xl:whitespace-nowrap"
|
||||
>
|
||||
{{ account.lastUsed }}
|
||||
</span>
|
||||
@@ -284,16 +284,16 @@ const statusBars = computed(() => {
|
||||
<section class="min-w-0 w-full pt-6 xl:h-100.5 xl:pt-0">
|
||||
<header class="flex h-12.5 items-start justify-between">
|
||||
<div>
|
||||
<h2 class="m-0 text-xl leading-[1.15] font-[760] text-(--cp-text-primary)">
|
||||
<h2 class="m-0 text-xl leading-[1.15] font-heavy text-(--cp-text-primary)">
|
||||
账号状态
|
||||
</h2>
|
||||
<p class="mt-1 mb-0 text-[13px] leading-[1.15] font-[650] text-(--cp-text-secondary)">
|
||||
<p class="mt-1 mb-0 text-[13px] leading-[1.15] font-emphasis text-(--cp-text-secondary)">
|
||||
账号池健康结构
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid justify-items-end">
|
||||
<strong
|
||||
class="font-mono text-2xl leading-[1.05] font-[760] tabular-nums text-(--cp-success-text)"
|
||||
class="font-mono text-2xl leading-[1.05] font-heavy tabular-nums text-(--cp-success-text)"
|
||||
>{{ availabilityRate }}</strong>
|
||||
<span class="mt-0.5 text-xs leading-[1.15] font-bold text-(--cp-text-secondary)">可用率</span>
|
||||
</div>
|
||||
@@ -301,8 +301,8 @@ const statusBars = computed(() => {
|
||||
|
||||
<div class="mt-5.5 h-10.5 w-full">
|
||||
<div class="flex h-4 items-center justify-between">
|
||||
<span class="text-xs leading-[1.15] font-[650] text-(--cp-text-secondary)">状态分布</span>
|
||||
<span class="text-xs leading-[1.15] font-[650] text-(--cp-danger-text)">不可用 {{ statusRows[3]?.value || '0' }}</span>
|
||||
<span class="text-xs leading-[1.15] font-emphasis text-(--cp-text-secondary)">状态分布</span>
|
||||
<span class="text-xs leading-[1.15] font-emphasis text-(--cp-danger-text)">不可用 {{ statusRows[3]?.value || '0' }}</span>
|
||||
</div>
|
||||
<div class="mt-2.5 flex h-3 w-full overflow-hidden rounded-full bg-(--cp-bg-muted)">
|
||||
<i
|
||||
@@ -328,15 +328,15 @@ const statusBars = computed(() => {
|
||||
<component :is="row.icon" :size="16" />
|
||||
</span>
|
||||
<span class="col-start-3 grid gap-1">
|
||||
<strong class="text-sm leading-[1.15] font-[650] text-(--cp-text-primary)">{{
|
||||
<strong class="text-sm leading-[1.15] font-emphasis text-(--cp-text-primary)">{{
|
||||
row.label
|
||||
}}</strong>
|
||||
<span class="text-xs leading-[1.15] font-[650] text-(--cp-text-secondary)">{{
|
||||
<span class="text-xs leading-[1.15] font-emphasis text-(--cp-text-secondary)">{{
|
||||
row.description
|
||||
}}</span>
|
||||
</span>
|
||||
<strong
|
||||
class="col-start-4 text-right font-mono text-[17px] leading-[1.15] font-[760] tabular-nums"
|
||||
class="col-start-4 text-right font-mono text-[17px] leading-[1.15] font-heavy tabular-nums"
|
||||
:class="toneValueClass(row.tone)"
|
||||
>{{ row.value }}</strong>
|
||||
</div>
|
||||
|
||||
@@ -70,17 +70,17 @@ const metricItems = outcomeMeta
|
||||
<header class="flex items-center justify-between gap-3 bg-(--cp-bg-subtle) px-3.5 py-3">
|
||||
<div class="flex min-w-0 items-center gap-2">
|
||||
<span class="size-2 shrink-0 rounded-full" :class="status.cellClass" />
|
||||
<strong class="font-mono text-[13px] leading-none font-[780] text-(--cp-text-primary)">
|
||||
<strong class="font-mono text-[13px] leading-none font-heavy text-(--cp-text-primary)">
|
||||
{{ point.time }}
|
||||
</strong>
|
||||
<span
|
||||
class="inline-flex h-5 items-center rounded-full px-2 text-[10px] leading-none font-[760]"
|
||||
class="inline-flex h-5 items-center rounded-full px-2 text-[10px] leading-none font-heavy"
|
||||
:class="status.badgeClass"
|
||||
>
|
||||
{{ status.label }}
|
||||
</span>
|
||||
</div>
|
||||
<span class="shrink-0 text-[10px] leading-none font-[650] text-(--cp-text-muted)">
|
||||
<span class="shrink-0 text-[10px] leading-none font-emphasis text-(--cp-text-muted)">
|
||||
15 分钟
|
||||
</span>
|
||||
</header>
|
||||
@@ -88,22 +88,22 @@ const metricItems = outcomeMeta
|
||||
<div class="grid gap-3.5 px-3.5 py-3.5">
|
||||
<div class="flex items-end justify-between gap-4">
|
||||
<div>
|
||||
<p class="m-0 text-[11px] leading-none font-[650] text-(--cp-text-muted)">
|
||||
<p class="m-0 text-[11px] leading-none font-emphasis text-(--cp-text-muted)">
|
||||
有效请求可用性
|
||||
</p>
|
||||
<strong
|
||||
class="mt-2 block font-mono text-[25px] leading-none font-[790] tabular-nums"
|
||||
class="mt-2 block font-mono text-[25px] leading-none font-heavy tabular-nums"
|
||||
:class="healthReliabilityValueClass(point.successRequests, point.failedRequests)"
|
||||
>
|
||||
{{ point.reliabilityDisplay }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<span class="block text-[10px] leading-none font-[650] text-(--cp-text-muted)">
|
||||
<span class="block text-[10px] leading-none font-emphasis text-(--cp-text-muted)">
|
||||
有效请求
|
||||
</span>
|
||||
<strong
|
||||
class="mt-2 block font-mono text-[15px] leading-none font-[760] tabular-nums text-(--cp-text-primary)"
|
||||
class="mt-2 block font-mono text-[15px] leading-none font-heavy tabular-nums text-(--cp-text-primary)"
|
||||
>
|
||||
{{ formatHealthCount(eligibleRequests) }}
|
||||
</strong>
|
||||
@@ -130,11 +130,11 @@ const metricItems = outcomeMeta
|
||||
class="grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-2 rounded-(--cp-input-radius-base) bg-(--cp-bg-subtle) px-2.5 py-2.5"
|
||||
>
|
||||
<span class="size-1.5 rounded-full" :class="item.dotClass" />
|
||||
<span class="truncate text-[10px] leading-none font-[650] text-(--cp-text-secondary)">
|
||||
<span class="truncate text-[10px] leading-none font-emphasis text-(--cp-text-secondary)">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
<strong
|
||||
class="font-mono text-[12px] leading-none font-[760] tabular-nums"
|
||||
class="font-mono text-[12px] leading-none font-heavy tabular-nums"
|
||||
:class="item.valueClass"
|
||||
>
|
||||
{{ formatHealthCount(item.value) }}
|
||||
@@ -143,7 +143,7 @@ const metricItems = outcomeMeta
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="m-0 border-t border-(--cp-divider-subtle) pt-3 text-[10px] leading-[1.45] font-[650] text-(--cp-text-muted)"
|
||||
class="m-0 border-t border-(--cp-divider-subtle) pt-3 text-[10px] leading-[1.45] font-emphasis text-(--cp-text-muted)"
|
||||
>
|
||||
客户端取消与调用方错误单独记录,不计入可用性。
|
||||
</p>
|
||||
|
||||
@@ -78,14 +78,14 @@ const sparklineOption = computed<EChartsOption | null>(() => {
|
||||
>
|
||||
<component :is="metric.icon" :size="18" />
|
||||
</BaseMotionIcon>
|
||||
<span class="mt-1 text-[13px] leading-[1.15] font-[650] text-(--cp-text-secondary)">{{
|
||||
<span class="mt-1 text-[13px] leading-[1.15] font-emphasis text-(--cp-text-secondary)">{{
|
||||
metric.title
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-3.25 flex h-7.75 items-end gap-2">
|
||||
<strong
|
||||
class="font-mono text-[28px] leading-[1.05] font-[780] tabular-nums text-(--cp-text-primary)"
|
||||
class="font-mono text-[28px] leading-[1.05] font-heavy tabular-nums text-(--cp-text-primary)"
|
||||
>
|
||||
<AnimatedMetricValue
|
||||
:value="metric.value"
|
||||
@@ -115,7 +115,7 @@ const sparklineOption = computed<EChartsOption | null>(() => {
|
||||
<span
|
||||
class="inline-grid min-w-0 w-full grid-cols-[auto_minmax(0,1fr)] items-baseline gap-2.5"
|
||||
>
|
||||
<span class="shrink-0 text-[11px] leading-none font-[650] text-(--cp-text-muted)">{{
|
||||
<span class="shrink-0 text-[11px] leading-none font-emphasis text-(--cp-text-muted)">{{
|
||||
metric.details[0]?.label
|
||||
}}</span>
|
||||
<b
|
||||
@@ -128,7 +128,7 @@ const sparklineOption = computed<EChartsOption | null>(() => {
|
||||
<span
|
||||
class="inline-grid min-w-0 w-full grid-cols-[auto_minmax(0,auto)] items-baseline justify-end gap-2.5"
|
||||
>
|
||||
<span class="shrink-0 text-[11px] leading-none font-[650] text-(--cp-text-muted)">{{
|
||||
<span class="shrink-0 text-[11px] leading-none font-emphasis text-(--cp-text-muted)">{{
|
||||
metric.details[1]?.label
|
||||
}}</span>
|
||||
<b
|
||||
|
||||
@@ -216,7 +216,7 @@ onBeforeUnmount(() => {
|
||||
<template #actions>
|
||||
<div class="flex w-full flex-wrap items-center justify-between gap-x-4 gap-y-2">
|
||||
<div
|
||||
class="flex max-w-full flex-wrap items-center gap-x-2 gap-y-1 text-[11px] leading-none font-[650] text-(--cp-text-muted)"
|
||||
class="flex max-w-full flex-wrap items-center gap-x-2 gap-y-1 text-[11px] leading-none font-emphasis text-(--cp-text-muted)"
|
||||
>
|
||||
<span
|
||||
v-for="item in healthLegend"
|
||||
@@ -233,7 +233,7 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-3">
|
||||
<strong
|
||||
class="font-mono text-sm leading-none font-[760] tabular-nums"
|
||||
class="font-mono text-sm leading-none font-heavy tabular-nums"
|
||||
:class="healthReliabilityValueClass(timeline.successRequests, timeline.failedRequests)"
|
||||
>
|
||||
{{ timeline.reliabilityDisplay }}
|
||||
|
||||
@@ -79,11 +79,11 @@ const {
|
||||
]"
|
||||
/>
|
||||
<span class="grid min-w-0 gap-1">
|
||||
<span class="truncate text-[10px] leading-none font-[680] text-(--cp-text-secondary)">
|
||||
<span class="truncate text-[10px] leading-none font-bold text-(--cp-text-secondary)">
|
||||
{{ item.label }}
|
||||
</span>
|
||||
<strong
|
||||
class="truncate font-mono text-[15px] leading-none font-[760] tabular-nums text-(--cp-text-primary)"
|
||||
class="truncate font-mono text-[15px] leading-none font-heavy tabular-nums text-(--cp-text-primary)"
|
||||
:title="item.value"
|
||||
>
|
||||
{{ item.value }}
|
||||
|
||||
@@ -209,10 +209,10 @@ function providerLabel(provider: string) {
|
||||
>
|
||||
<Box aria-hidden="true" class="size-3.75 text-(--cp-text-secondary)" />
|
||||
</span>
|
||||
<span class="truncate text-[11px] leading-none font-[760]">{{ profile.product }}</span>
|
||||
<span class="truncate text-[11px] leading-none font-heavy">{{ profile.product }}</span>
|
||||
</div>
|
||||
<span
|
||||
class="inline-flex h-7 shrink-0 items-center gap-1.5 rounded-lg px-2.5 text-[12px] leading-none font-[720]"
|
||||
class="inline-flex h-7 shrink-0 items-center gap-1.5 rounded-lg px-2.5 text-[12px] leading-none font-bold"
|
||||
:class="releaseStatus.tone"
|
||||
:title="releaseStatus.title"
|
||||
>
|
||||
@@ -224,14 +224,14 @@ function providerLabel(provider: string) {
|
||||
<div class="grid min-h-0 content-center">
|
||||
<div class="flex min-w-0 flex-wrap items-baseline gap-x-2.5 gap-y-1.5">
|
||||
<strong
|
||||
class="block max-w-full wrap-break-word font-mono text-[27px] leading-[1.05] font-[790] tabular-nums text-(--cp-text-primary)"
|
||||
class="block max-w-full wrap-break-word font-mono text-[27px] leading-[1.05] font-heavy tabular-nums text-(--cp-text-primary)"
|
||||
:title="profile.version"
|
||||
>
|
||||
{{ profile.version }}
|
||||
</strong>
|
||||
<span
|
||||
v-if="profile.build"
|
||||
class="shrink-0 font-mono text-[10px] leading-none font-[650] tabular-nums text-(--cp-text-muted)"
|
||||
class="shrink-0 font-mono text-[10px] leading-none font-emphasis tabular-nums text-(--cp-text-muted)"
|
||||
>
|
||||
Build {{ profile.build }}
|
||||
</span>
|
||||
@@ -246,13 +246,13 @@ function providerLabel(provider: string) {
|
||||
>
|
||||
<div v-if="profile.provider === 'xai'" class="min-w-0">
|
||||
<dt
|
||||
class="flex items-center gap-1.5 text-[10px] leading-none font-[720] text-(--cp-text-muted)"
|
||||
class="flex items-center gap-1.5 text-[10px] leading-none font-bold text-(--cp-text-muted)"
|
||||
>
|
||||
<ShieldCheck aria-hidden="true" class="size-3.25 text-(--cp-info)" />
|
||||
认证协议
|
||||
</dt>
|
||||
<dd
|
||||
class="mt-2 mb-0 truncate font-mono text-[14px] leading-none font-[720] tabular-nums text-(--cp-text-primary)"
|
||||
class="mt-2 mb-0 truncate font-mono text-[14px] leading-none font-bold tabular-nums text-(--cp-text-primary)"
|
||||
:title="authProtocol"
|
||||
>
|
||||
{{ authProtocol }}
|
||||
@@ -261,19 +261,19 @@ function providerLabel(provider: string) {
|
||||
|
||||
<div class="min-w-0">
|
||||
<dt
|
||||
class="flex items-center gap-1.5 text-[10px] leading-none font-[720] text-(--cp-text-muted)"
|
||||
class="flex items-center gap-1.5 text-[10px] leading-none font-bold text-(--cp-text-muted)"
|
||||
>
|
||||
<Monitor aria-hidden="true" class="size-3.25 text-(--cp-normal)" />
|
||||
{{ profile.provider === 'openai' ? '模拟运行环境' : '运行环境' }}
|
||||
</dt>
|
||||
<dd
|
||||
class="mt-2 mb-0 truncate font-mono text-[14px] leading-none font-[720] tabular-nums text-(--cp-text-primary)"
|
||||
class="mt-2 mb-0 truncate font-mono text-[14px] leading-none font-bold tabular-nums text-(--cp-text-primary)"
|
||||
:title="runtimeEnvironment.title"
|
||||
>
|
||||
{{ runtimeEnvironment.primary }}
|
||||
<span
|
||||
v-if="runtimeEnvironment.details.length"
|
||||
class="text-[11px] font-[650] text-(--cp-text-secondary)"
|
||||
class="text-[11px] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
<template v-for="detail in runtimeEnvironment.details" :key="detail">
|
||||
· {{ detail }}
|
||||
@@ -284,13 +284,13 @@ function providerLabel(provider: string) {
|
||||
|
||||
<div class="min-w-0">
|
||||
<dt
|
||||
class="flex items-center gap-1.5 text-[10px] leading-none font-[720] text-(--cp-text-muted)"
|
||||
class="flex items-center gap-1.5 text-[10px] leading-none font-bold text-(--cp-text-muted)"
|
||||
>
|
||||
<Terminal aria-hidden="true" class="size-3.25 text-(--cp-info)" />
|
||||
{{ profile.provider === 'openai' ? 'Codex Core' : 'Grok Client' }}
|
||||
</dt>
|
||||
<dd
|
||||
class="mt-2 mb-0 truncate font-mono text-[16px] leading-none font-[760] tabular-nums text-(--cp-text-primary)"
|
||||
class="mt-2 mb-0 truncate font-mono text-[16px] leading-none font-heavy tabular-nums text-(--cp-text-primary)"
|
||||
:title="clientIdentity"
|
||||
>
|
||||
{{ clientIdentity }}
|
||||
@@ -300,7 +300,7 @@ function providerLabel(provider: string) {
|
||||
|
||||
<footer
|
||||
v-if="verifiedLabel || checkedLabel"
|
||||
class="flex min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-1 text-[10px] leading-none font-[650] text-(--cp-text-muted)"
|
||||
class="flex min-w-0 flex-wrap items-center justify-between gap-x-4 gap-y-1 text-[10px] leading-none font-emphasis text-(--cp-text-muted)"
|
||||
>
|
||||
<span v-if="verifiedLabel" :title="profile.userAgent">{{ verifiedLabel }}</span>
|
||||
<span v-if="checkedLabel">{{ checkedLabel }}</span>
|
||||
|
||||
@@ -70,11 +70,11 @@ const emit = defineEmits<{
|
||||
<KeyRound class="size-4" />
|
||||
</BaseMotionIcon>
|
||||
<div class="min-w-0">
|
||||
<p class="m-0 text-[13px] leading-[1.15] font-[720] text-(--cp-text-primary)">
|
||||
<p class="m-0 text-[13px] leading-[1.15] font-bold text-(--cp-text-primary)">
|
||||
{{ status.exists ? '已启用' : '未生成' }}
|
||||
</p>
|
||||
<p
|
||||
class="mt-1.5 mb-0 truncate text-[12px] leading-[1.15] font-[650] text-(--cp-text-secondary)"
|
||||
class="mt-1.5 mb-0 truncate text-[12px] leading-[1.15] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
{{
|
||||
loading
|
||||
@@ -89,12 +89,12 @@ const emit = defineEmits<{
|
||||
</div>
|
||||
|
||||
<div v-if="generatedKey" class="grid gap-2">
|
||||
<p class="m-0 text-[13px] leading-[1.15] font-[650] text-(--cp-text-secondary)">
|
||||
<p class="m-0 text-[13px] leading-[1.15] font-emphasis text-(--cp-text-secondary)">
|
||||
完整 Key 仅显示一次,请立即保存
|
||||
</p>
|
||||
<div class="flex min-w-0 items-center gap-2">
|
||||
<code
|
||||
class="min-w-0 flex-1 rounded-(--cp-input-radius-base) bg-(--cp-bg-subtle) px-3 py-2.5 font-mono text-[12px] leading-normal font-[650] break-all text-(--cp-text-primary)"
|
||||
class="min-w-0 flex-1 rounded-(--cp-input-radius-base) bg-(--cp-bg-subtle) px-3 py-2.5 font-mono text-[12px] leading-normal font-emphasis break-all text-(--cp-text-primary)"
|
||||
>
|
||||
{{ generatedKey }}
|
||||
</code>
|
||||
|
||||
@@ -40,28 +40,28 @@ const rows = computed(() => props.mappings)
|
||||
</template>
|
||||
添加映射
|
||||
</BaseButton>
|
||||
<span v-if="error" class="text-xs font-[650] text-(--cp-danger-text)">{{ error }}</span>
|
||||
<span v-if="error" class="text-xs font-emphasis text-(--cp-danger-text)">{{ error }}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2 text-[12px] font-[650] text-(--cp-text-secondary)">
|
||||
<div class="flex items-center gap-2 text-[12px] font-emphasis text-(--cp-text-secondary)">
|
||||
<GitBranch class="size-4 text-(--cp-info)" />
|
||||
全局模型映射
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="loading"
|
||||
class="rounded-(--cp-input-radius-base) bg-(--cp-bg-subtle) px-4 py-4 text-[13px] font-[650] text-(--cp-text-muted)"
|
||||
class="rounded-(--cp-input-radius-base) bg-(--cp-bg-subtle) px-4 py-4 text-[13px] font-emphasis text-(--cp-text-muted)"
|
||||
>
|
||||
正在加载模型映射...
|
||||
</div>
|
||||
<div
|
||||
v-else-if="rows.length === 0"
|
||||
class="rounded-(--cp-input-radius-base) bg-(--cp-bg-subtle) px-4 py-4 text-[13px] font-[650] text-(--cp-text-muted)"
|
||||
class="rounded-(--cp-input-radius-base) bg-(--cp-bg-subtle) px-4 py-4 text-[13px] font-emphasis text-(--cp-text-muted)"
|
||||
>
|
||||
暂无模型映射
|
||||
</div>
|
||||
<div v-else class="grid gap-3">
|
||||
<div class="grid grid-cols-[1fr_auto_1fr_auto] items-center gap-3 px-1 text-[12px] font-[700] text-(--cp-text-muted)">
|
||||
<div class="grid grid-cols-[1fr_auto_1fr_auto] items-center gap-3 px-1 text-[12px] font-bold text-(--cp-text-muted)">
|
||||
<span>请求模型</span>
|
||||
<span />
|
||||
<span>上游模型</span>
|
||||
|
||||
@@ -43,9 +43,9 @@ const model = defineModel<RotationStrategy | ''>({ required: true })
|
||||
:class="model === option.value ? 'bg-(--cp-info) opacity-100' : 'opacity-0'"
|
||||
/>
|
||||
</span>
|
||||
<span class="text-[14px] leading-[1.15] font-[760]">{{ option.label }}</span>
|
||||
<span class="text-[14px] leading-[1.15] font-heavy">{{ option.label }}</span>
|
||||
</span>
|
||||
<span class="mt-2 block text-[13px] leading-normal font-[650] text-(--cp-text-secondary)">
|
||||
<span class="mt-2 block text-[13px] leading-normal font-emphasis text-(--cp-text-secondary)">
|
||||
{{ option.description }}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -65,7 +65,7 @@ function latencyDisplay(value: unknown) {
|
||||
上游 {{ display(record.upstreamStatusCode) }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="mt-3 mb-0 text-[13px] leading-relaxed font-[680] text-(--cp-text-primary)">
|
||||
<p class="mt-3 mb-0 text-[13px] leading-relaxed font-bold text-(--cp-text-primary)">
|
||||
{{ display(record.message) }}
|
||||
</p>
|
||||
</section>
|
||||
@@ -83,7 +83,7 @@ function latencyDisplay(value: unknown) {
|
||||
{{ field.label }}
|
||||
</dt>
|
||||
<dd
|
||||
class="mt-1.5 mb-0 truncate font-mono text-[12px] leading-normal font-[650] text-(--cp-text-primary)"
|
||||
class="mt-1.5 mb-0 truncate font-mono text-[12px] leading-normal font-emphasis text-(--cp-text-primary)"
|
||||
:title="display(field.value)"
|
||||
>
|
||||
{{ display(field.value) }}
|
||||
@@ -95,7 +95,7 @@ function latencyDisplay(value: unknown) {
|
||||
v-if="metadataText"
|
||||
class="mt-3 rounded-(--cp-card-radius) bg-(--cp-bg-subtle) px-4 py-3.5"
|
||||
>
|
||||
<h3 class="m-0 text-[12px] leading-none font-[780] text-(--cp-text-secondary)">
|
||||
<h3 class="m-0 text-[12px] leading-none font-heavy text-(--cp-text-secondary)">
|
||||
Metadata
|
||||
</h3>
|
||||
<BaseScrollbar
|
||||
|
||||
@@ -94,7 +94,7 @@ function showDetail(record: Awaited<ReturnType<typeof getOpsErrors>>['items'][nu
|
||||
/>
|
||||
</template>
|
||||
<template #failureClass="{ row }">
|
||||
<span class="font-mono text-[12px] font-[680] text-(--cp-danger-text)">
|
||||
<span class="font-mono text-[12px] font-bold text-(--cp-danger-text)">
|
||||
{{ row.failureClass || '—' }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -50,7 +50,7 @@ function itemValueClass(tone?: string, accent?: boolean) {
|
||||
|
||||
<template>
|
||||
<div class="flex items-center justify-end gap-1.5">
|
||||
<span class="font-mono text-[12px] font-[760] tabular-nums text-(--cp-success-text)">
|
||||
<span class="font-mono text-[12px] font-heavy tabular-nums text-(--cp-success-text)">
|
||||
{{ usageBillingText(record) }}
|
||||
</span>
|
||||
|
||||
@@ -58,7 +58,7 @@ function itemValueClass(tone?: string, accent?: boolean) {
|
||||
<div class="grid gap-1.5 text-(--cp-text-secondary)">
|
||||
<div v-for="item in amountItems" :key="item.label" class="flex justify-between gap-4">
|
||||
<span>{{ item.label }}</span>
|
||||
<span class="font-mono font-[760]" :class="itemValueClass(undefined, item.accent)">
|
||||
<span class="font-mono font-heavy" :class="itemValueClass(undefined, item.accent)">
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -66,7 +66,7 @@ function itemValueClass(tone?: string, accent?: boolean) {
|
||||
<div class="mt-1 grid gap-1.5 rounded-(--cp-input-radius-base) bg-(--cp-bg-subtle) p-2 text-(--cp-text-secondary)">
|
||||
<div v-for="item in billingItems" :key="item.label" class="flex justify-between gap-4">
|
||||
<span>{{ item.label }}</span>
|
||||
<span class="font-mono font-[760]" :class="itemValueClass(item.tone)">
|
||||
<span class="font-mono font-heavy" :class="itemValueClass(item.tone)">
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ defineProps<{
|
||||
content: string
|
||||
}>()
|
||||
|
||||
const panelTitleClass = 'm-0 text-[12px] leading-none font-[780] text-(--cp-text-secondary)'
|
||||
const panelTitleClass = 'm-0 text-[12px] leading-none font-heavy text-(--cp-text-secondary)'
|
||||
const codeBlockViewClass = 'rounded-(--cp-input-radius-base) bg-(--cp-bg-surface) px-3 py-2.5'
|
||||
const codeBlockClass
|
||||
= 'm-0 whitespace-pre-wrap wrap-break-word font-mono text-[12px] leading-[1.65] text-(--cp-text-primary)'
|
||||
|
||||
@@ -30,7 +30,7 @@ defineProps<{
|
||||
</template>
|
||||
|
||||
<div class="grid gap-2 text-[12px] leading-none">
|
||||
<p class="m-0 font-[760] text-(--cp-text-primary)">
|
||||
<p class="m-0 font-heavy text-(--cp-text-primary)">
|
||||
{{ title }}
|
||||
</p>
|
||||
<slot />
|
||||
|
||||
@@ -147,7 +147,7 @@ function diagnosticNameDisplay(name: string) {
|
||||
<template #nameDisplay="{ row }">
|
||||
<div class="inline-grid max-w-full min-w-0 gap-1" :title="row.nameDisplay.full">
|
||||
<code
|
||||
class="block max-w-full truncate font-mono text-[12px] leading-none font-[760] text-(--cp-text-primary)"
|
||||
class="block max-w-full truncate font-mono text-[12px] leading-none font-heavy text-(--cp-text-primary)"
|
||||
>
|
||||
{{ row.nameDisplay.primary }}
|
||||
</code>
|
||||
@@ -172,10 +172,10 @@ function diagnosticNameDisplay(name: string) {
|
||||
class="grid justify-items-end gap-1 font-mono leading-none tabular-nums"
|
||||
:title="`成功 ${formatCompactNumber(row.successCount)}`"
|
||||
>
|
||||
<strong class="font-[720] text-(--cp-text-primary)">
|
||||
<strong class="font-bold text-(--cp-text-primary)">
|
||||
{{ formatCompactNumber(row.requestCount) }}
|
||||
</strong>
|
||||
<small class="text-[10px] font-[650] text-(--cp-text-muted)">
|
||||
<small class="text-[10px] font-emphasis text-(--cp-text-muted)">
|
||||
{{ formatPercent(row.requestShare) }}
|
||||
</small>
|
||||
</span>
|
||||
@@ -184,13 +184,13 @@ function diagnosticNameDisplay(name: string) {
|
||||
<template #errorCount="{ row }">
|
||||
<span class="grid justify-items-end gap-1 font-mono leading-none tabular-nums">
|
||||
<strong
|
||||
class="font-[720]"
|
||||
class="font-bold"
|
||||
:class="row.errorCount > 0 ? 'text-(--cp-danger-text)' : 'text-(--cp-text-primary)'"
|
||||
>
|
||||
{{ formatCompactNumber(row.errorCount) }}
|
||||
</strong>
|
||||
<small
|
||||
class="text-[10px] font-[650]"
|
||||
class="text-[10px] font-emphasis"
|
||||
:class="row.errorRate > 0 ? 'text-(--cp-danger-text)' : 'text-(--cp-text-muted)'"
|
||||
>
|
||||
{{ formatPercent(row.errorRate) }}
|
||||
@@ -199,13 +199,13 @@ function diagnosticNameDisplay(name: string) {
|
||||
</template>
|
||||
|
||||
<template #latencyP95Ms="{ row }">
|
||||
<span class="font-mono font-[680] tabular-nums text-(--cp-warning-text)">
|
||||
<span class="font-mono font-bold tabular-nums text-(--cp-warning-text)">
|
||||
{{ formatDuration(row.latencyP95Ms) }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #estimatedCost="{ row }">
|
||||
<span class="font-mono font-[680] tabular-nums text-(--cp-success-text)">
|
||||
<span class="font-mono font-bold tabular-nums text-(--cp-success-text)">
|
||||
{{ formatUsd(row.estimatedCost) }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
@@ -15,7 +15,7 @@ const latencyDetails = computed(() => usageLatencyDetails(props.record))
|
||||
<template>
|
||||
<div class="flex items-center justify-end gap-1.5">
|
||||
<div
|
||||
class="grid grid-cols-[auto_auto] items-center justify-end gap-x-2 gap-y-1.5 font-mono text-[12px] leading-none font-[760] tabular-nums"
|
||||
class="grid grid-cols-[auto_auto] items-center justify-end gap-x-2 gap-y-1.5 font-mono text-[12px] leading-none font-heavy tabular-nums"
|
||||
>
|
||||
<span class="text-[11px] text-(--cp-text-muted)">{{ latencyDetails.firstOutputLabel }}</span>
|
||||
<span class="text-(--cp-text-secondary)">{{ latencyDetails.firstOutputDisplay }}</span>
|
||||
@@ -34,7 +34,7 @@ const latencyDetails = computed(() => usageLatencyDetails(props.record))
|
||||
class="flex justify-between gap-4"
|
||||
>
|
||||
<span class="whitespace-nowrap">{{ item.label }}</span>
|
||||
<span class="whitespace-nowrap font-mono font-[760] text-(--cp-text-primary)">
|
||||
<span class="whitespace-nowrap font-mono font-heavy text-(--cp-text-primary)">
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -45,7 +45,7 @@ const latencyDetails = computed(() => usageLatencyDetails(props.record))
|
||||
|
||||
<div class="flex justify-between border-t border-(--cp-divider-subtle) pt-2">
|
||||
<span class="whitespace-nowrap text-(--cp-text-secondary)">总耗时</span>
|
||||
<span class="whitespace-nowrap font-mono font-[760] text-(--cp-info-text)">
|
||||
<span class="whitespace-nowrap font-mono font-heavy text-(--cp-info-text)">
|
||||
{{ latencyDetails.totalDisplay }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -54,7 +54,7 @@ const latencyDetails = computed(() => usageLatencyDetails(props.record))
|
||||
v-if="latencyDetails.transportItems.length"
|
||||
class="grid gap-1.5 border-t border-(--cp-divider-subtle) pt-2 text-(--cp-text-secondary)"
|
||||
>
|
||||
<p class="m-0 font-[760] text-(--cp-text-primary)">
|
||||
<p class="m-0 font-heavy text-(--cp-text-primary)">
|
||||
传输观测
|
||||
</p>
|
||||
<div
|
||||
@@ -63,7 +63,7 @@ const latencyDetails = computed(() => usageLatencyDetails(props.record))
|
||||
class="flex justify-between gap-4"
|
||||
>
|
||||
<span class="whitespace-nowrap">{{ item.label }}</span>
|
||||
<span class="whitespace-nowrap font-mono font-[760] text-(--cp-text-primary)">
|
||||
<span class="whitespace-nowrap font-mono font-heavy text-(--cp-text-primary)">
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@ const modelDisplay = computed(() => usageModelDisplay(props.record))
|
||||
<template>
|
||||
<div class="inline-grid max-w-full gap-1">
|
||||
<code
|
||||
class="block max-w-full truncate font-mono text-[12px] leading-none font-[760] text-(--cp-text-primary)"
|
||||
class="block max-w-full truncate font-mono text-[12px] leading-none font-heavy text-(--cp-text-primary)"
|
||||
>
|
||||
{{ modelDisplay.primary }}
|
||||
</code>
|
||||
|
||||
@@ -11,7 +11,7 @@ defineProps<{
|
||||
|
||||
<template>
|
||||
<span
|
||||
class="inline-flex items-center gap-1 whitespace-nowrap text-[12px] font-[720] text-(--cp-text-primary)"
|
||||
class="inline-flex items-center gap-1 whitespace-nowrap text-[12px] font-bold text-(--cp-text-primary)"
|
||||
>
|
||||
<span>{{ usageReasoningEffort(record) }}</span>
|
||||
<span
|
||||
|
||||
@@ -44,7 +44,7 @@ const billing = computed(() => props.record ? usageBilling(props.record) : null)
|
||||
const latencyDetails = computed(() => props.record ? usageLatencyDetails(props.record) : null)
|
||||
|
||||
const panelClass = 'rounded-(--cp-card-radius) bg-(--cp-bg-subtle) px-4 py-3.5'
|
||||
const panelTitleClass = 'm-0 text-[12px] leading-none font-[780] text-(--cp-text-secondary)'
|
||||
const panelTitleClass = 'm-0 text-[12px] leading-none font-heavy text-(--cp-text-secondary)'
|
||||
|
||||
const accountDisplay = computed(() => props.record ? usageAccountText(props.record) : '—')
|
||||
const overviewItems = computed(() => [
|
||||
@@ -229,7 +229,7 @@ const tokenDonutOption = computed<EChartsOption>(() => {
|
||||
<div class="min-w-0">
|
||||
<span :class="fieldLabelClass">账号</span>
|
||||
<p
|
||||
class="mt-1.5 mb-0 truncate font-mono text-[13px] leading-none font-[760] text-(--cp-text-primary)"
|
||||
class="mt-1.5 mb-0 truncate font-mono text-[13px] leading-none font-heavy text-(--cp-text-primary)"
|
||||
:title="displayValue(accountDisplay)"
|
||||
>
|
||||
{{ displayValue(accountDisplay) }}
|
||||
|
||||
@@ -38,7 +38,7 @@ defineProps<{
|
||||
|
||||
<template #accountEmail="{ row }">
|
||||
<span
|
||||
class="block max-w-full truncate font-mono text-[12px] leading-none font-[720] text-(--cp-text-primary)"
|
||||
class="block max-w-full truncate font-mono text-[12px] leading-none font-bold text-(--cp-text-primary)"
|
||||
:title="usageAccountText(row)"
|
||||
>
|
||||
{{ usageAccountText(row) }}
|
||||
@@ -59,7 +59,7 @@ defineProps<{
|
||||
|
||||
<template #route="{ row }">
|
||||
<div class="inline-flex max-w-full items-center gap-1.5 whitespace-nowrap">
|
||||
<code class="font-mono text-[12px] font-[650]">{{ row.route || '—' }}</code>
|
||||
<code class="font-mono text-[12px] font-emphasis">{{ row.route || '—' }}</code>
|
||||
<span
|
||||
v-if="usageIsCompact(row)"
|
||||
class="inline-flex shrink-0 text-(--cp-warning-text)"
|
||||
|
||||
@@ -75,7 +75,7 @@ const items = computed(() => [
|
||||
>
|
||||
{{ item.value }}
|
||||
</strong>
|
||||
<span class="block truncate text-[12px] leading-none font-[650] text-(--cp-text-secondary)">
|
||||
<span class="block truncate text-[12px] leading-none font-emphasis text-(--cp-text-secondary)">
|
||||
{{ item.detail }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -43,14 +43,14 @@ const tokenItems = computed(() => [
|
||||
<div class="grid gap-1.5 text-(--cp-text-secondary)">
|
||||
<div v-for="item in tokenItems" :key="item.label" class="flex justify-between gap-4">
|
||||
<span class="whitespace-nowrap">{{ item.label }}</span>
|
||||
<span class="whitespace-nowrap font-mono font-[760] text-(--cp-text-primary)">
|
||||
<span class="whitespace-nowrap font-mono font-heavy text-(--cp-text-primary)">
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-1 flex justify-between border-t border-(--cp-divider-subtle) pt-2">
|
||||
<span class="whitespace-nowrap text-(--cp-text-secondary)">总 Token</span>
|
||||
<span class="whitespace-nowrap font-mono font-[760] text-(--cp-info-text)">
|
||||
<span class="whitespace-nowrap font-mono font-heavy text-(--cp-info-text)">
|
||||
{{ tokenDetails.totalTokensDisplay }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -26,14 +26,14 @@ export const usageRecordColumns = [
|
||||
label: '推理强度',
|
||||
width: '98px',
|
||||
ellipsis: false,
|
||||
cellClass: 'whitespace-nowrap text-[12px] font-[700] text-(--cp-text-primary)',
|
||||
cellClass: 'whitespace-nowrap text-[12px] font-bold text-(--cp-text-primary)',
|
||||
},
|
||||
{
|
||||
key: 'route',
|
||||
label: '端点',
|
||||
width: '185px',
|
||||
ellipsis: false,
|
||||
cellClass: 'font-mono text-[12px] font-[650]',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis',
|
||||
},
|
||||
{
|
||||
key: 'recordType',
|
||||
@@ -69,7 +69,7 @@ export const usageRecordColumns = [
|
||||
width: '190px',
|
||||
ellipsis: false,
|
||||
cellClass:
|
||||
'whitespace-nowrap font-mono text-[12px] font-[650] tabular-nums text-(--cp-text-secondary)',
|
||||
'whitespace-nowrap font-mono text-[12px] font-emphasis tabular-nums text-(--cp-text-secondary)',
|
||||
},
|
||||
{
|
||||
key: 'clientIp',
|
||||
@@ -83,7 +83,7 @@ export const usageRecordColumns = [
|
||||
width: '340px',
|
||||
ellipsis: false,
|
||||
cellClass:
|
||||
'whitespace-normal break-words text-[12px] leading-[1.45] font-[650] text-(--cp-text-secondary)',
|
||||
'whitespace-normal break-words text-[12px] leading-[1.45] font-emphasis text-(--cp-text-secondary)',
|
||||
},
|
||||
{
|
||||
key: 'actions',
|
||||
@@ -101,44 +101,44 @@ export const opsErrorColumns = [
|
||||
label: '时间',
|
||||
width: '190px',
|
||||
cellClass:
|
||||
'whitespace-nowrap font-mono text-[12px] font-[650] tabular-nums text-(--cp-text-secondary)',
|
||||
'whitespace-nowrap font-mono text-[12px] font-emphasis tabular-nums text-(--cp-text-secondary)',
|
||||
},
|
||||
{ key: 'upstreamStatusCode', label: '上游状态', width: '96px', align: 'center' as const },
|
||||
{
|
||||
key: 'failureClass',
|
||||
label: '失败分类',
|
||||
width: '170px',
|
||||
cellClass: 'font-mono text-[12px] font-[650]',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis',
|
||||
},
|
||||
{
|
||||
key: 'kind',
|
||||
label: '事件',
|
||||
width: '170px',
|
||||
cellClass: 'font-mono text-[12px] font-[650]',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis',
|
||||
},
|
||||
{
|
||||
key: 'route',
|
||||
label: '端点',
|
||||
width: '190px',
|
||||
cellClass: 'font-mono text-[12px] font-[650]',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis',
|
||||
},
|
||||
{
|
||||
key: 'model',
|
||||
label: '模型',
|
||||
width: '180px',
|
||||
cellClass: 'font-mono text-[12px] font-[650]',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis',
|
||||
},
|
||||
{
|
||||
key: 'accountId',
|
||||
label: '账号 ID',
|
||||
width: '230px',
|
||||
cellClass: 'font-mono text-[12px] font-[650]',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis',
|
||||
},
|
||||
{
|
||||
key: 'requestId',
|
||||
label: '请求 ID',
|
||||
width: '250px',
|
||||
cellClass: 'font-mono text-[12px] font-[650]',
|
||||
cellClass: 'font-mono text-[12px] font-emphasis',
|
||||
},
|
||||
{ key: 'message', label: '消息', minWidth: '300px', flex: 1 },
|
||||
{
|
||||
|
||||
@@ -87,11 +87,11 @@ watch(timeRange, () => {
|
||||
<template #header>
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<h2 class="m-0 text-xl leading-[1.15] font-[760] text-(--cp-text-primary)">
|
||||
<h2 class="m-0 text-xl leading-[1.15] font-heavy text-(--cp-text-primary)">
|
||||
请求明细
|
||||
</h2>
|
||||
<p
|
||||
class="mt-1.75 mb-0 text-[13px] leading-[1.15] font-[650] text-(--cp-text-secondary)"
|
||||
class="mt-1.75 mb-0 text-[13px] leading-[1.15] font-emphasis text-(--cp-text-secondary)"
|
||||
>
|
||||
成功请求与失败请求明细
|
||||
</p>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// 详情弹窗共享的字段展示约定:占位符、标签/值样式,供弹窗与其子组件复用。
|
||||
export const fieldLabelClass = 'text-[11px] leading-none font-bold text-(--cp-text-muted)'
|
||||
export const fieldValueBaseClass
|
||||
= 'mt-1.5 mb-0 min-w-0 truncate text-[12px] leading-none font-[700] text-(--cp-text-primary)'
|
||||
= 'mt-1.5 mb-0 min-w-0 truncate text-[12px] leading-none font-bold text-(--cp-text-primary)'
|
||||
|
||||
export function displayValue(value: unknown) {
|
||||
if (value === undefined || value === null || value === '')
|
||||
|
||||
Reference in New Issue
Block a user