diff --git a/packages/webui/docs/design/design-language.md b/packages/webui/docs/design/design-language.md index 712315656..a9df1b0a8 100644 --- a/packages/webui/docs/design/design-language.md +++ b/packages/webui/docs/design/design-language.md @@ -108,9 +108,13 @@ styled with the same names the token file declares. a copy of it. A settings page brings its own content, never its own frame. - The 用量与模型 page names the account's plan, it does not name a product: the plan name, the model-source label and the 限额重置 section all follow the account's own answer - (`features/settings/projection/usage-plan.ts` and `features/settings/ui/UsageResetCards.tsx`). + (`features/settings/projection/usage-plan.public.ts` and `features/settings/ui/UsageResetCards.tsx`). A hard-coded plan name is a bug, not a default — the legacy "Token Plan" label belongs to the - legacy `token_plan` subscription kind alone. + legacy `token_plan` subscription kind alone. The account's tier is shown as the membership answer + reports it: the M Plan levels (Go / Explore / Build) read as reported, and the pre-upgrade + identifiers (starter / plus / max / ultra / plus极速版) read as their product display names. Any + other reported tier name passes through, and only a numeric combo id falls back to the kind's + generic plan name. - The settings pages share their controls too, not only their frame: `features/settings/ui/settings-atoms.tsx` owns the page's button (`SettingsButton`, with a `compact` size for a row action) and its dialog (`SettingsDialog` — a scrim, a surface, a header and a scrolling body). A control that each page diff --git a/packages/webui/src/client/features/account/projection/usage.public.ts b/packages/webui/src/client/features/account/projection/usage.public.ts index 07fd89261..c72edd729 100644 --- a/packages/webui/src/client/features/account/projection/usage.public.ts +++ b/packages/webui/src/client/features/account/projection/usage.public.ts @@ -8,6 +8,22 @@ // The text below is the declaration as it stood in the source module — no // behaviour change. +import type { WebuiUsageQuotaResult } from "../../../../shared/contracts/usage-quota.js"; +import { formatPlanName } from "../../settings/projection/usage-plan.public.js"; + +/** + * The line under the rail identity: the plan a signed-in account reports, the + * sign-in prompt for a signed-out one, and nothing until the quota answer + * arrives (or when it cannot be read). + */ +export function formatRailPlanLabel( + result: WebuiUsageQuotaResult | undefined, +): string | undefined { + if (!result) return undefined; + if (result.signedIn === false) return "请先登录账号!"; + return formatPlanName(result); +} + /** * Formats a quota reset timestamp: * `3小时13分后重置` below a day, `5天7小时后重置` once days are involved, diff --git a/packages/webui/src/client/features/account/ui/UserMenu.tsx b/packages/webui/src/client/features/account/ui/UserMenu.tsx index 3c55614a1..4a0d30a59 100644 --- a/packages/webui/src/client/features/account/ui/UserMenu.tsx +++ b/packages/webui/src/client/features/account/ui/UserMenu.tsx @@ -52,12 +52,12 @@ import { type SigninState, } from "./UserMenuSignin.js"; import { UsagePanel, type UsageState } from "./UserMenuUsage.js"; +import { formatRailPlanLabel } from "../projection/usage.public.js"; type AccountStatus = Record; interface UserMenuProps { readonly collapsed: boolean; - readonly hostLabel?: string; readonly dataDir?: string; readonly version?: WebuiVersionInfo; readonly sessionId?: string; @@ -151,7 +151,6 @@ function Chevron(): ReactElement { export function UserMenu({ collapsed, - hostLabel, dataDir, sessionId, version, @@ -285,10 +284,9 @@ export function UserMenu({ "MiniMax Code"; const avatarUrl = profile?.avatarUrl?.trim() || profile?.defaultAvatarUrl?.trim(); - const plan = - accountString(account, "plan") ?? - accountString(account, "planName") ?? - (hostLabel ? `本地 · ${hostLabel}` : "本地"); + const planLabel = formatRailPlanLabel( + usage.status === "ready" ? usage.result : undefined, + ); const identity = objectValue(account?.identity); const auth = objectValue(account?.auth); const uid = @@ -374,7 +372,7 @@ export function UserMenu({ {nickname} - {plan} + {planLabel ? {planLabel} : null}