From 09821aab85827e5c68603185015ad9dce74c5316 Mon Sep 17 00:00:00 2001 From: jialin Date: Mon, 8 Jun 2026 14:43:16 +0800 Subject: [PATCH] feat: add a billing holder page --- config/routes.ts | 13 ++++++ src/layouts/index.tsx | 2 +- src/locales/en-US/billing.ts | 15 +++++++ src/locales/en-US/menu.ts | 1 + src/locales/ja-JP/billing.ts | 15 +++++++ src/locales/ja-JP/menu.ts | 1 + src/locales/ru-RU/billing.ts | 15 +++++++ src/locales/ru-RU/menu.ts | 1 + src/locales/tr-TR/billing.ts | 15 +++++++ src/locales/tr-TR/menu.ts | 1 + src/locales/zh-CN/billing.ts | 11 +++++ src/locales/zh-CN/menu.ts | 1 + src/pages/billing/index.tsx | 80 ++++++++++++++++++++++++++++++++++++ 13 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 src/locales/en-US/billing.ts create mode 100644 src/locales/ja-JP/billing.ts create mode 100644 src/locales/ru-RU/billing.ts create mode 100644 src/locales/tr-TR/billing.ts create mode 100644 src/locales/zh-CN/billing.ts create mode 100644 src/pages/billing/index.tsx diff --git a/config/routes.ts b/config/routes.ts index 9ebeb957..f8e5892e 100644 --- a/config/routes.ts +++ b/config/routes.ts @@ -338,6 +338,19 @@ const baseRoutes = [ selectedIcon: 'icon-usage-filled', defaultIcon: 'icon-usage-outlined', component: './usage/index' + }, + { + name: 'billing', + path: '/usage/billing', + key: 'billing', + icon: 'icon-billing-outlined', + selectedIcon: 'icon-billing-filled', + defaultIcon: 'icon-billing-outlined', + // OSS exposes the menu as a teaser for the enterprise billing + // module. The page itself just renders an upsell notice — the real + // billing UI lives in the enterprise plugin and shadows this route + // via `routes.extensions.ts`. + component: './billing' } ] }, diff --git a/src/layouts/index.tsx b/src/layouts/index.tsx index fd8cc2f2..d1a5eb67 100644 --- a/src/layouts/index.tsx +++ b/src/layouts/index.tsx @@ -327,7 +327,7 @@ export default (props: any) => { config={{ apiBaseUrl: GPUSTACK_API_BASE_URL, theme: userSettings.theme, - iconUrl: '//at.alicdn.com/t/c/font_4613488_rwchdketjg8.js', + iconUrl: '//at.alicdn.com/t/c/font_4613488_or5t9922sfk.js', isDarkTheme: userSettings.isDarkTheme, defaultColorPrimary: COLOR_PRIMARY }} diff --git a/src/locales/en-US/billing.ts b/src/locales/en-US/billing.ts new file mode 100644 index 00000000..5fa6c7c9 --- /dev/null +++ b/src/locales/en-US/billing.ts @@ -0,0 +1,15 @@ +export default { + 'billing.upsell.title': 'Billing is an Enterprise feature', + 'billing.upsell.subtitle': + 'Track spend, generate invoices, and enforce budgets across teams. Upgrade to GPUStack Enterprise to manage billing.', + 'billing.upsell.featuresTitle': 'What you get in Enterprise', + 'billing.upsell.feature.usage': + 'See cost breakdowns by organization, user, and model', + 'billing.upsell.feature.invoices': + 'Generate invoices and export billing reports', + 'billing.upsell.feature.budgets': + 'Set budgets and spending limits with alerts', + 'billing.upsell.feature.chargeback': + 'Attribute and charge back usage to teams and projects', + 'billing.upsell.cta': 'Learn about Enterprise' +}; diff --git a/src/locales/en-US/menu.ts b/src/locales/en-US/menu.ts index ae6892be..c229d878 100644 --- a/src/locales/en-US/menu.ts +++ b/src/locales/en-US/menu.ts @@ -38,6 +38,7 @@ export default { 'menu.usage.usage': 'Usage', 'menu.billingAndUsage': 'Usage & Billing', 'menu.billingAndUsage.usage': 'Usage', + 'menu.billingAndUsage.billing': 'Billing', 'menu.404': '404', 'menu.resources.clusters': 'Clusters', 'menu.resources.credentials': 'Cloud Credentials', diff --git a/src/locales/ja-JP/billing.ts b/src/locales/ja-JP/billing.ts new file mode 100644 index 00000000..5fa6c7c9 --- /dev/null +++ b/src/locales/ja-JP/billing.ts @@ -0,0 +1,15 @@ +export default { + 'billing.upsell.title': 'Billing is an Enterprise feature', + 'billing.upsell.subtitle': + 'Track spend, generate invoices, and enforce budgets across teams. Upgrade to GPUStack Enterprise to manage billing.', + 'billing.upsell.featuresTitle': 'What you get in Enterprise', + 'billing.upsell.feature.usage': + 'See cost breakdowns by organization, user, and model', + 'billing.upsell.feature.invoices': + 'Generate invoices and export billing reports', + 'billing.upsell.feature.budgets': + 'Set budgets and spending limits with alerts', + 'billing.upsell.feature.chargeback': + 'Attribute and charge back usage to teams and projects', + 'billing.upsell.cta': 'Learn about Enterprise' +}; diff --git a/src/locales/ja-JP/menu.ts b/src/locales/ja-JP/menu.ts index bc685b54..e9b955e4 100644 --- a/src/locales/ja-JP/menu.ts +++ b/src/locales/ja-JP/menu.ts @@ -29,6 +29,7 @@ export default { 'menu.usage.usage': '使用状況', 'menu.billingAndUsage': '使用状況と請求', 'menu.billingAndUsage.usage': '使用状況', + 'menu.billingAndUsage.billing': '請求', 'menu.404': '404', 'menu.settings': 'Settings', 'menu.resources.workers': 'Workers', diff --git a/src/locales/ru-RU/billing.ts b/src/locales/ru-RU/billing.ts new file mode 100644 index 00000000..5fa6c7c9 --- /dev/null +++ b/src/locales/ru-RU/billing.ts @@ -0,0 +1,15 @@ +export default { + 'billing.upsell.title': 'Billing is an Enterprise feature', + 'billing.upsell.subtitle': + 'Track spend, generate invoices, and enforce budgets across teams. Upgrade to GPUStack Enterprise to manage billing.', + 'billing.upsell.featuresTitle': 'What you get in Enterprise', + 'billing.upsell.feature.usage': + 'See cost breakdowns by organization, user, and model', + 'billing.upsell.feature.invoices': + 'Generate invoices and export billing reports', + 'billing.upsell.feature.budgets': + 'Set budgets and spending limits with alerts', + 'billing.upsell.feature.chargeback': + 'Attribute and charge back usage to teams and projects', + 'billing.upsell.cta': 'Learn about Enterprise' +}; diff --git a/src/locales/ru-RU/menu.ts b/src/locales/ru-RU/menu.ts index 1225945b..9eabe623 100644 --- a/src/locales/ru-RU/menu.ts +++ b/src/locales/ru-RU/menu.ts @@ -29,6 +29,7 @@ export default { 'menu.usage.usage': 'Использование', 'menu.billingAndUsage': 'Использование и биллинг', 'menu.billingAndUsage.usage': 'Использование', + 'menu.billingAndUsage.billing': 'Биллинг', 'menu.404': 'Ошибка 404', 'menu.resources.workers': 'Воркеры', 'menu.resources.gpus': 'GPUs', diff --git a/src/locales/tr-TR/billing.ts b/src/locales/tr-TR/billing.ts new file mode 100644 index 00000000..5fa6c7c9 --- /dev/null +++ b/src/locales/tr-TR/billing.ts @@ -0,0 +1,15 @@ +export default { + 'billing.upsell.title': 'Billing is an Enterprise feature', + 'billing.upsell.subtitle': + 'Track spend, generate invoices, and enforce budgets across teams. Upgrade to GPUStack Enterprise to manage billing.', + 'billing.upsell.featuresTitle': 'What you get in Enterprise', + 'billing.upsell.feature.usage': + 'See cost breakdowns by organization, user, and model', + 'billing.upsell.feature.invoices': + 'Generate invoices and export billing reports', + 'billing.upsell.feature.budgets': + 'Set budgets and spending limits with alerts', + 'billing.upsell.feature.chargeback': + 'Attribute and charge back usage to teams and projects', + 'billing.upsell.cta': 'Learn about Enterprise' +}; diff --git a/src/locales/tr-TR/menu.ts b/src/locales/tr-TR/menu.ts index 81f96b0d..3e9239fa 100644 --- a/src/locales/tr-TR/menu.ts +++ b/src/locales/tr-TR/menu.ts @@ -36,6 +36,7 @@ export default { 'menu.usage.usage': 'Kullanım', 'menu.billingAndUsage': 'Kullanım ve Faturalandırma', 'menu.billingAndUsage.usage': 'Kullanım', + 'menu.billingAndUsage.billing': 'Faturalandırma', 'menu.404': '404', 'menu.resources.clusters': 'Kümeler', 'menu.resources.credentials': 'Bulut Kimlik Bilgileri', diff --git a/src/locales/zh-CN/billing.ts b/src/locales/zh-CN/billing.ts new file mode 100644 index 00000000..71e9e8b7 --- /dev/null +++ b/src/locales/zh-CN/billing.ts @@ -0,0 +1,11 @@ +export default { + 'billing.upsell.title': '计费是企业版功能', + 'billing.upsell.subtitle': + '在团队间跟踪花费、生成账单并执行预算。升级到 GPUStack 企业版即可管理计费。', + 'billing.upsell.featuresTitle': '企业版包含的能力', + 'billing.upsell.feature.usage': '按组织、用户与模型查看成本明细', + 'billing.upsell.feature.invoices': '生成账单并导出计费报表', + 'billing.upsell.feature.budgets': '设置预算与花费上限并触发告警', + 'billing.upsell.feature.chargeback': '将用量归属并分摊到团队与项目', + 'billing.upsell.cta': '了解企业版' +}; diff --git a/src/locales/zh-CN/menu.ts b/src/locales/zh-CN/menu.ts index 40da5533..583d8a79 100644 --- a/src/locales/zh-CN/menu.ts +++ b/src/locales/zh-CN/menu.ts @@ -31,6 +31,7 @@ export default { 'menu.usage.usage': '使用量', 'menu.billingAndUsage': '用量与计费', 'menu.billingAndUsage.usage': '用量统计', + 'menu.billingAndUsage.billing': '计费', 'menu.404': '404', 'menu.resources.workers': '节点', 'menu.resources.gpus': 'GPU', diff --git a/src/pages/billing/index.tsx b/src/pages/billing/index.tsx new file mode 100644 index 00000000..adcb326e --- /dev/null +++ b/src/pages/billing/index.tsx @@ -0,0 +1,80 @@ +import { IconFont } from '@gpustack/core-ui'; +import { useIntl } from '@umijs/max'; +import { Button, Result, Typography } from 'antd'; +import PageBox from '../_components/page-box'; + +// OSS-only upsell page for the billing module. The real Billing UI ships +// in the enterprise plugin and shadows this route via +// `routes.extensions.ts` — when the enterprise plugin is loaded, the +// merger removes this entry by name. So this file is what users see on +// the OSS build only. +const Billing: React.FC = () => { + const intl = useIntl(); + const features = [ + 'billing.upsell.feature.usage', + 'billing.upsell.feature.invoices', + 'billing.upsell.feature.budgets', + 'billing.upsell.feature.chargeback' + ]; + return ( + +
+ + } + title={intl.formatMessage({ id: 'billing.upsell.title' })} + subTitle={intl.formatMessage({ id: 'billing.upsell.subtitle' })} + extra={ +
+ + {intl.formatMessage({ + id: 'billing.upsell.featuresTitle' + })} + +
    + {features.map((id) => ( +
  • + {intl.formatMessage({ id })} +
  • + ))} +
+
+ +
+
+ } + /> +
+
+ ); +}; + +export default Billing;