diff --git a/apps/admin-web/src/i18n/messages/en-US.ts b/apps/admin-web/src/i18n/messages/en-US.ts index fba581e..e05a9d4 100644 --- a/apps/admin-web/src/i18n/messages/en-US.ts +++ b/apps/admin-web/src/i18n/messages/en-US.ts @@ -94,6 +94,7 @@ const enUS = { tenantAdminLogin: "Tenant Admin Login", loginAndEnter: "Sign in to workspace", email: "Email", + loginIdentifier: "Phone / Email", password: "Password", defaultTestAccount: "Default account", defaultTestPassword: "Default password", @@ -101,6 +102,7 @@ const enUS = { membershipBlocked: { eyebrow: "Access Paused", title: "This tenant plan is unavailable", + expiredMessage: "Membership expired. Please renew or contact support.", reasonTrialExpired: "The free trial's 3-day page access window has ended. All business pages are now locked. Please contact an administrator to reactivate trial access.", reasonRequired: "This tenant does not have an active plan. All business pages are now locked. Please contact an administrator.", reasonInactive: "This tenant plan has expired or been disabled. All business pages are now locked. Please contact an administrator to restore access.", @@ -118,6 +120,7 @@ const enUS = { localeLabel: "Language", quotaTitle: "Plan & Quota", quotaStatus: "Healthy", + membershipExpiresAt: "Expires", remainingQuota: "Article quota", aiPoints: "AI points", resetAt: "Reset at", diff --git a/apps/admin-web/src/i18n/messages/zh-CN.ts b/apps/admin-web/src/i18n/messages/zh-CN.ts index f42da2b..6d62fa4 100644 --- a/apps/admin-web/src/i18n/messages/zh-CN.ts +++ b/apps/admin-web/src/i18n/messages/zh-CN.ts @@ -94,6 +94,7 @@ const zhCN = { tenantAdminLogin: "租户后台登录", loginAndEnter: "登录并进入工作台", email: "邮箱", + loginIdentifier: "手机号 / 邮箱", password: "密码", defaultTestAccount: "默认测试账号", defaultTestPassword: "默认测试密码", @@ -101,6 +102,7 @@ const zhCN = { membershipBlocked: { eyebrow: "访问已暂停", title: "当前租户套餐不可用", + expiredMessage: "会员到期,请充值或联系客服", reasonTrialExpired: "免费试用的 3 天页面可访问期已经结束,当前业务页面已全部关闭,请联系管理员重新开通试用权限。", reasonRequired: "当前租户尚未开通有效套餐,业务页面已全部关闭,请联系管理员处理。", reasonInactive: "当前租户套餐已失效或已停用,业务页面已全部关闭,请联系管理员恢复访问。", @@ -118,6 +120,7 @@ const zhCN = { localeLabel: "语言", quotaTitle: "套餐与额度", quotaStatus: "状态正常", + membershipExpiresAt: "会员到期", remainingQuota: "生成文章", aiPoints: "AI 点数", resetAt: "重置时间", diff --git a/apps/admin-web/src/layouts/AppShell.vue b/apps/admin-web/src/layouts/AppShell.vue index 54590b7..b941f42 100644 --- a/apps/admin-web/src/layouts/AppShell.vue +++ b/apps/admin-web/src/layouts/AppShell.vue @@ -24,13 +24,37 @@ const router = useRouter(); const authStore = useAuthStore(); const { locale, t } = useI18n(); +const isMembershipBlocked = computed(() => authStore.isMembershipBlocked); + const quotaQuery = useQuery({ queryKey: ["workspace", "quota-summary", "shell"], queryFn: () => workspaceApi.quotaSummary(), + enabled: computed(() => !isMembershipBlocked.value), }); -const userInitial = computed(() => authStore.user?.name?.slice(0, 1).toUpperCase() ?? "A"); +const userDisplayName = computed(() => { + return authStore.user?.name || authStore.user?.phone || authStore.user?.email || t("shell.userFallback"); +}); +const userSecondaryIdentifier = computed(() => authStore.user?.email || authStore.user?.phone || "--"); +const userInitial = computed(() => userDisplayName.value.slice(0, 1).toUpperCase() || "A"); const quotaSummary = computed(() => quotaQuery.data.value); +const membershipExpiryText = computed(() => { + const value = authStore.membership?.end_at; + if (!value) { + return "--"; + } + + const date = new Date(value); + if (Number.isNaN(date.getTime())) { + return value; + } + + return new Intl.DateTimeFormat(locale.value, { + year: "numeric", + month: "2-digit", + day: "2-digit", + }).format(date); +}); const selectedKeys = computed(() => { if (route.meta.navKey === null) { return []; @@ -242,9 +266,9 @@ async function handleLogout(): Promise { - - -