Fix marketing product routes for Next.js params (#653)

This commit is contained in:
shenlan 2025-11-09 16:51:47 +08:00 committed by GitHub
parent 369c615560
commit 559b3e40f9
6 changed files with 167 additions and 21 deletions

View File

@ -2,6 +2,13 @@ export const dynamic = 'error'
import ComposeForm from '../../../../components/mail/ComposeForm'
export default function ComposePage({ params }: { params: { slug: string } }) {
return <ComposeForm tenantId={params.slug} />
type PageProps = {
params: Promise<{
slug: string
}>
}
export default async function ComposePage({ params }: PageProps) {
const { slug } = await params
return <ComposeForm tenantId={slug} />
}

View File

@ -2,7 +2,13 @@ export const dynamic = 'error'
import MailDashboard from '../../../components/mail/MailDashboard'
export default function TenantMailPage({ params }: { params: { slug: string } }) {
const { slug } = params
type PageProps = {
params: Promise<{
slug: string
}>
}
export default async function TenantMailPage({ params }: PageProps) {
const { slug } = await params
return <MailDashboard tenantId={slug} tenantName={slug} />
}

View File

@ -2,6 +2,13 @@ export const dynamic = 'error'
import MailSettings from '../../../../components/mail/MailSettings'
export default function MailSettingsPage({ params }: { params: { slug: string } }) {
return <MailSettings tenantId={params.slug} />
type PageProps = {
params: Promise<{
slug: string
}>
}
export default async function MailSettingsPage({ params }: PageProps) {
const { slug } = await params
return <MailSettings tenantId={slug} />
}

View File

@ -183,7 +183,7 @@ export default function Client({ config }: ClientProps) {
</header>
<main>
<ProductHero config={config} lang={lang} onExportPoster={handleExportPoster} />
<ProductFeatures lang={lang} />
<ProductFeatures config={config} lang={lang} />
<ProductEditions config={config} lang={lang} />
<ProductScenarios lang={lang} />
<ProductDownload config={config} lang={lang} />

View File

@ -5,9 +5,9 @@ import Client from './Client'
import { PRODUCT_MAP, getAllSlugs } from '@src/products/registry'
type PageProps = {
params: {
params: Promise<{
slug: string
}
}>
}
export async function generateStaticParams() {
@ -15,7 +15,8 @@ export async function generateStaticParams() {
}
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
const config = PRODUCT_MAP.get(params.slug)
const { slug } = await params
const config = PRODUCT_MAP.get(slug)
if (!config) {
return {}
@ -45,8 +46,9 @@ export async function generateMetadata({ params }: PageProps): Promise<Metadata>
}
}
export default function ProductPage({ params }: PageProps) {
const config = PRODUCT_MAP.get(params.slug)
export default async function ProductPage({ params }: PageProps) {
const { slug } = await params
const config = PRODUCT_MAP.get(slug)
if (!config) {
notFound()

View File

@ -1,10 +1,37 @@
import { Activity, Brain, Rocket, Shield } from 'lucide-react'
import type { LucideIcon } from 'lucide-react'
import {
Activity,
BellRing,
Brain,
Cloud,
Coins,
Database,
GitBranch,
Puzzle,
Rocket,
Shield,
ShieldCheck,
} from 'lucide-react'
import type { ProductConfig } from '@src/products/registry'
type ProductFeaturesProps = {
config: ProductConfig
lang: 'zh' | 'en'
}
const FEATURES = {
type FeatureDefinition = {
title: string
description: string
icon: LucideIcon
}
type FeatureSet = {
zh: FeatureDefinition[]
en: FeatureDefinition[]
}
const DEFAULT_FEATURES: FeatureSet = {
zh: [
{
title: '极速连接',
@ -51,8 +78,109 @@ const FEATURES = {
],
}
export default function ProductFeatures({ lang }: ProductFeaturesProps) {
const items = FEATURES[lang]
const FEATURE_LIBRARY: Record<string, FeatureSet> = {
xstream: DEFAULT_FEATURES,
xscopehub: {
zh: [
{
title: '全栈可观测数据',
description: '统一聚合日志、指标与追踪,秒级关联上下游依赖。',
icon: Database,
},
{
title: 'AI 根因洞察',
description: '基于时间序列与拓扑的智能关联分析,快速定位故障。',
icon: Brain,
},
{
title: '自动化告警编排',
description: '多渠道告警与自愈策略编排,减少人工值守负担。',
icon: BellRing,
},
{
title: '生态级集成',
description: '通过 Webhook 与插件体系,与 CI/CD、ITSM 平台无缝联动。',
icon: Puzzle,
},
],
en: [
{
title: 'Full-stack telemetry',
description: 'Unify logs, metrics, and traces with second-level dependency mapping.',
icon: Database,
},
{
title: 'AI-driven insights',
description: 'Correlate time-series signals with topology to pinpoint root causes fast.',
icon: Brain,
},
{
title: 'Automated alerting',
description: 'Orchestrate multichannel alerts and auto-remediation runbooks to cut toil.',
icon: BellRing,
},
{
title: 'Ecosystem integrations',
description: 'Connect to CI/CD and ITSM systems through webhooks and an extensible plugin hub.',
icon: Puzzle,
},
],
},
xcloudflow: {
zh: [
{
title: '多云蓝图编排',
description: '跨公有云与私有云的资源模型统一建模,一次定义多环境复用。',
icon: Cloud,
},
{
title: 'GitOps 流水线',
description: '将基础设施交付纳入 Git 审批与回滚流程,自动推进部署。',
icon: GitBranch,
},
{
title: '策略与合规',
description: '内置策略扫描与准入控制,确保资源变更符合监管要求。',
icon: ShieldCheck,
},
{
title: '成本可视化',
description: '实时跟踪多云资源使用与成本分摊,辅助优化预算。',
icon: Coins,
},
],
en: [
{
title: 'Multi-cloud blueprints',
description: 'Model infrastructure once and reuse across public and private clouds.',
icon: Cloud,
},
{
title: 'GitOps pipelines',
description: 'Bring infrastructure delivery into Git reviews with automated rollouts.',
icon: GitBranch,
},
{
title: 'Policy & compliance',
description: 'Built-in policy checks and admission controls enforce governance at deploy time.',
icon: ShieldCheck,
},
{
title: 'Cost visibility',
description: 'Track multi-cloud spend and allocations in real time to optimize budgets.',
icon: Coins,
},
],
},
}
export default function ProductFeatures({ config, lang }: ProductFeaturesProps) {
const featureSet = FEATURE_LIBRARY[config.slug] ?? DEFAULT_FEATURES
const items = featureSet[lang]
const intro =
lang === 'zh'
? `${config.name} 的核心能力组合,帮助团队快速落地。`
: `Key capabilities from ${config.name} to help your team ship faster.`
return (
<section id="features" aria-labelledby="features-title" className="py-16">
@ -61,11 +189,7 @@ export default function ProductFeatures({ lang }: ProductFeaturesProps) {
<h2 id="features-title" className="text-3xl font-bold text-slate-900">
{lang === 'zh' ? '核心功能' : 'Core Features'}
</h2>
<p className="mt-2 text-slate-600">
{lang === 'zh'
? '为稳定、低延迟的全球访问而生。'
: 'Built for stable, low-latency global access.'}
</p>
<p className="mt-2 text-slate-600">{intro}</p>
</header>
<div className="mt-10 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{items.map(({ title, description, icon: Icon }) => (