feat(desktop): 顶栏租户切换器(多租户)—— 切换活跃租户即换工作区+计费
用户属多个租户时,顶栏显示租户下拉(Building2 图标):切换即调 POST /me/tenant 换活跃租户,随后刷新余额芯片(显示新计费租户的可花余额)。仅 >1 租户时出现。 api 加 myTenants/switchTenant。 live 验证(preview):demoB(属公司A+公司B) 切换器显两租户;从公司A(共享,余额15.84) 切到公司B(个人,余额6.38)→ 后端 active 持久化、芯片随之更新为 6.4(橙,偏低)。tsc+48 测试全过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -139,6 +139,32 @@ export async function tenantCurrent(): Promise<TenantCtx | null> {
|
||||
};
|
||||
}
|
||||
|
||||
// ---- 我所属的租户 + 切换活跃租户(多租户)----
|
||||
export interface MyTenant {
|
||||
id: string;
|
||||
name: string;
|
||||
slug: string;
|
||||
plan: string;
|
||||
credit_balance_micro: number;
|
||||
shared_billing: boolean;
|
||||
members: number;
|
||||
}
|
||||
|
||||
export async function myTenants(): Promise<{ tenants: MyTenant[]; active: string }> {
|
||||
const res = guard401(await fetch(`${GATEWAY}/api/v1/me/tenants`, { headers: bearer() }));
|
||||
if (!res.ok) return { tenants: [], active: "" };
|
||||
const d = (await res.json()) as { tenants?: MyTenant[]; active?: string };
|
||||
return { tenants: d.tenants ?? [], active: d.active ?? "" };
|
||||
}
|
||||
|
||||
export async function switchTenant(tenantId: string): Promise<void> {
|
||||
const res = guard401(await fetch(`${GATEWAY}/api/v1/me/tenant`, { method: "POST", headers: { "Content-Type": "application/json", ...bearer() }, body: JSON.stringify({ tenant_id: tenantId }) }));
|
||||
if (!res.ok) {
|
||||
const d = (await res.json().catch(() => ({}))) as { error?: string };
|
||||
throw new Error(d.error ?? `switch failed: ${res.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 我的用量明细(当前用户自己租户:余额 + 按天趋势 + 最近消耗)----
|
||||
export interface UsageDay {
|
||||
day: string; // YYYYMMDD
|
||||
|
||||
Reference in New Issue
Block a user