You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js项目双布局实现:路由分组与会话驱动布局切换

实现Next.js双布局与会话路由判断

1. 创建落地页布局组件

先新建MainLayout组件,包含落地页所需的导航栏、Hero区域、页脚等元素:

// src/components/Layout/MainLayout.tsx
import React from 'react';
import LandingNavbar from '../Navbar/LandingNavbar';
import LandingHero from '../Hero/LandingHero';
import LandingFooter from '../Footer/LandingFooter';

const MainLayout = ({ children }: { children: React.ReactNode }) => {
  return (
    <div className="landing-container">
      <LandingNavbar />
      <LandingHero />
      <main className="landing-content">{children}</main>
      <LandingFooter />
    </div>
  );
};

export default MainLayout;

2. 修改根布局逻辑

更新RootLayout,加入会话判断、路由重定向逻辑,并切换渲染对应布局:

import type { Metadata } from "next";
import { Inter, Poppins } from "next/font/google";
import { redirect } from "next/navigation";
import "../globals.css";
import ThemeProvider from "src/provider/ThemeProvider/ThemeProvider";
import GlobalProvider from "src/provider/GlobalProvider/GlobalProvider";
import UserLayout from "src/components/Layout/UserLayout";
import MainLayout from "src/components/Layout/MainLayout"; // 引入落地页布局

const inter = Inter({ subsets: ['latin'], weight: ['400', '500', '600', '700', '900'], style: ['normal'], variable: '--font-inter' });
const poppins = Poppins({ subsets: ['latin'], weight: ['400', '500', '600', '700', '900'], style: ['italic', 'normal'], variable: '--font-poppins' })

// 动态设置落地页元数据
export async function generateMetadata(): Promise<Metadata> {
  return {
    title: "ValuBox - 便捷缴费与流量充值平台",
    description: "一站式解决水电费、数据流量与话费购买需求。",
  };
}

export default async function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  // 替换为你实际的会话获取逻辑(比如从cookies、auth库读取并验证)
  const session = await getValidUserSession(); 
  const isSessionValid = session && session.expires > new Date().toISOString();

  // 会话有效则重定向到用户面板
  if (isSessionValid) {
    redirect("/user/dashboard");
  }

  return (
    <html lang="en">
      <body className={`${inter.className} ${poppins.className}`}>
        <GlobalProvider>
          <ThemeProvider>
            <MainLayout>
              {children}
            </MainLayout>
          </ThemeProvider>
        </GlobalProvider>
      </body>
    </html>
  );
}

3. 独立配置用户路由布局

在app/user目录下新建专属布局,确保用户面板路由统一使用UserLayout:

// app/user/layout.tsx
import UserLayout from "src/components/Layout/UserLayout";
import ThemeProvider from "src/provider/ThemeProvider/ThemeProvider";
import GlobalProvider from "src/provider/GlobalProvider/GlobalProvider";

// 设置用户面板元数据
export const metadata: Metadata = {
  title: "ValuBox - 用户控制台",
  description: "管理账户、查看交易记录、充值钱包与转账。",
};

export default function UserRootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <GlobalProvider>
      <ThemeProvider>
        <UserLayout>
          {children}
        </UserLayout>
      </ThemeProvider>
    </GlobalProvider>
  );
}

4. 路由保护(可选但推荐)

新建中间件保护/user/*路由,防止未认证用户直接访问:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export async function middleware(request: NextRequest) {
  // 复用会话验证逻辑
  const session = await getValidUserSession(request);
  const isAuthenticated = session && session.expires > new Date().toISOString();

  if (request.nextUrl.pathname.startsWith('/user') && !isAuthenticated) {
    return NextResponse.redirect(new URL('/', request.url));
  }

  return NextResponse.next();
}

// 指定中间件生效的路由
export const config = {
  matcher: ['/user/:path*'],
};

关键说明

  • 替换代码中的getValidUserSession为你项目实际的会话验证方法(比如next-auth的getServerSession,或自定义的cookie验证逻辑)。
  • 落地页的Hero区域如果仅需在首页显示,可通过路由判断或让首页单独渲染,避免所有落地页重复展示。

内容的提问来源于stack exchange,提问作者Chibuike Ilo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:42:08