- {/* Header */}
-
-
- {String(pkg[getKeyWithLanguage('name')] ?? '')}
-
-
{String(pkg[getKeyWithLanguage('core_value')] ?? '')}
-
- {pkg.billing_cycle !== 'permanent_free' && <>¥{pkg.price}>}
- {pkg.billing_cycle && {pkg.billing_cycle !== 'permanent_free' && '/'}{t(`package.${pkg.billing_cycle}`)}}
-
+ {showTabs && (
+
+
+
+ )}
+
+
+ {showArrows && (
+
0,
+ 'rb:cursor-not-allowed': currentPage === 0
+ })}
+ onClick={() => {
+ if (currentPage === 0) return
+ setCurrentPage(p => p - 1)
+ }}
+ >
+
+
+ )}
+
+
+ {pageData.map((pkg) => (
+
+
+
+
+ {/* Header */}
+
+
+
+ {String(pkg[getKeyWithLanguage('name')] ?? '')}
+
+
+
+
+ {/* Subtitle */}
+
+
+ {String(pkg[getKeyWithLanguage('core_value')] ?? '')}
+
+
+ {/* Price */}
+
+ {pkg.billing_cycle !== 'permanent_free' && <>
+ ¥
+ {pkg.price}
+ >}
+ {pkg.billing_cycle && (
+
+ {pkg.billing_cycle !== 'permanent_free' && ' /'}
+ {t(`package.${pkg.billing_cycle}`)}
+
+ )}
+
+
+
+
+
+
{/* Features */}
-
- {billingUnits.map(({ key, unit }) => {
- if (typeof pkg.quotas[key as keyof Package['quotas']] === 'number') {
- return (
-
- {t(`package.${key}`)}
- {pkg.quotas[key as keyof Package['quotas']]}{t(`package.${unit}`)}
-
- )
- }
+
- {t(`package.api_ops_rate_limit`)}
- {pkg.api_ops_rate_limit}{t('package.ops')}
-
- }
- {pkg.tech_support &&
-
- {t(`package.tech_support`)}
- {String(pkg[getKeyWithLanguage('tech_support')] ?? '')}
-
- }
-
+ >
+ {billingUnits.map(({ key, unit, icon }) => {
+ const value = pkg?.quotas?.[key as keyof Package['quotas']];
+ if (value === undefined || value === null) return null;
+ return (
+
+ )
+ })}
+ {pkg.tech_support && (
+
+ )}
+ {pkg.sla_compliance && (
+
+ )}
+
-
+
+
+ ))}
+
-
-
- ))}
-
+ {showArrows && (
+ = totalPages - 1
+ })}
+ onClick={() => {
+ if (currentPage >= totalPages - 1) return
+ setCurrentPage(p => p + 1)
+ }}
+ >
+ = totalPages - 1 ? '#E1E2E7' : '#171719', fontSize: 24 }} />
+
+ )}
+
>
);
diff --git a/web/src/views/Package/types.ts b/web/src/views/Package/types.ts
index 6517f63a..6ae9e48c 100644
--- a/web/src/views/Package/types.ts
+++ b/web/src/views/Package/types.ts
@@ -2,60 +2,60 @@
* @Author: ZhaoYing
* @Date: 2026-04-14 11:35:01
* @Last Modified by: ZhaoYing
- * @Last Modified time: 2026-04-14 14:28:46
+ * @Last Modified time: 2026-04-16 16:44:19
*/
export interface Package {
- id: string;
- // 名称
- name: string;
- name_en: string;
- // 类型
- category: "saas_personal" | "commercial_deployment";
- tier_level: number;
- // 版本
- version: string;
- // 状态
- status: boolean;
- // 价格
- price: string;
- // 计费周期
- billing_cycle: "monthly" | "yearly" | "permanent_free" | "local_deployment";
- // 核心价值
- core_value: string;
- core_value_en: string;
- // 技术支持
- tech_support: string;
- tech_support_en: string;
- // SLA与合规
- sla_compliance: string;
- sla_compliance_en: string;
- // 对话页面个性化配置
- page_customization: string;
- page_customization_en: string;
- // API OPS 频次(次/秒)
- api_ops_rate_limit: number;
- // 主题色
- theme_color: string;
- quotas: {
- // 空间数量
- workspace_quota: number;
- // 技能库数量
- skill_quota: number;
- // 应用数量
- app_quota: number;
- // 知识库容量
- knowledge_capacity_quota: string;
- // 记忆引擎数量
- memory_engine_quota: number;
- // 可记忆终端用户数
- end_user_quota: number;
- // 本体工程
- ontology_project_quota: number;
- // 可负载模型数量
- model_quota: number;
- },
- created_at: number;
- updated_at: number;
- created_by: string;
- updated_by: string | null;
+ id: string;
+ // 名称
+ name: string | null;
+ name_en: string | null;
+ // 类型
+ category: "saas_personal" | "commercial_deployment";
+ tier_level: number;
+ // 版本
+ version: string;
+ // 状态
+ status: boolean;
+ // 价格
+ price: string | null;
+ // 计费周期
+ billing_cycle: "monthly" | "yearly" | "permanent_free" | "local_deployment";
+ // 核心价值
+ core_value: string | null;
+ core_value_en: string | null;
+ // 技术支持
+ tech_support: string | null;
+ tech_support_en: string | null;
+ // SLA与合规
+ sla_compliance: string | null;
+ sla_compliance_en: string | null;
+ // 对话页面个性化配置
+ page_customization: string | null;
+ page_customization_en: string | null;
+ // 主题色
+ theme_color: string;
+ quotas: {
+ // API OPS 频次(次/秒)
+ api_ops_rate_limit: number | null;
+ // 空间数量
+ workspace_quota: number | null;
+ // 技能库数量
+ skill_quota: number | null;
+ // 应用数量
+ app_quota: number | null;
+ // 知识库容量
+ knowledge_capacity_quota: number | null;
+ // 记忆引擎数量
+ memory_engine_quota: number | null;
+ // 可记忆终端用户数
+ end_user_quota: number | null;
+ // 本体工程
+ ontology_project_quota: number | null;
+ // 可负载模型数量
+ model_quota: number | null;
+ },
+ created_at: number;
+ updated_at: number;
+ created_by: string | null;
+ updated_by: string | null;
}
diff --git a/web/vite.config.ts b/web/vite.config.ts
index 8cc1fa3b..4a1a0b34 100644
--- a/web/vite.config.ts
+++ b/web/vite.config.ts
@@ -3,6 +3,7 @@ import react from '@vitejs/plugin-react'
import { resolve } from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import tailwindcss from '@tailwindcss/vite'
+import svgr from 'vite-plugin-svgr';
// https://vite.dev/config/
export default defineConfig({
@@ -32,6 +33,7 @@ export default defineConfig({
imports: ['react', 'react-router-dom'],
dts: 'public/auto-imports.d.ts',
}),
+ svgr({ svgrOptions: { icon: true } }),
],
css: {
modules: {