Next.js 16 全栈实战(二):引入 Shadcn UI 与构建 Dashboard 布局
在当下,大模型的多模态能力,结合trae的选中元素功能,组合起来,只要你把意图表达明白,大模型就可以又好又快的实现功能。先在trae里打开我们的页面,然后用选中元素选中我们左侧的工作台菜单,这样右边的对话框可以看到一个a标签,输入提示词。有些命令是需要我们点击运行的,点运行,一路按照提示,就可以看到代码被正确的提交到了仓库里。再一个我们的LOGO有点过于高了,我们让AI优化一下,告诉他调整到合适的
目录
前情回顾
在上一篇中,我们使用 Trae 成功初始化了 Next.js 16 + Tailwind CSS 的项目环境,并配置好了 PostgreSQL 数据库连接。
本篇目标:
- 安装并配置 Shadcn UI(目前 React 生态最流行的组件库)。
- 梳理 Next.js App Router 的文件目录结构。
- 手写代码:实现响应式的 侧边栏 (Sidebar) 和 Dashboard 布局。
1. 为什么选择 Shadcn UI?
很多初学者习惯用 Ant Design 或 Material UI。但 Shadcn UI 不同,它不是一个通过 npm 安装的黑盒库,而是一个代码生成器。
当你运行命令时,它会把组件的源码直接“复制”到你的项目中。
- 优点:你可以随意修改组件代码,拥有 100% 的控制权。
- 风格:极简、现代,完美契合 Tailwind CSS。
1.1 初始化 Shadcn
打开 Trae 的终端,输入:
npx shadcn@latest init

按照以下选项进行配置(这是教培管家系统的设计风格):
Which color would you like to use as base color? › Zinc (中性灰,高级感)

初始化完成后,你会发现项目根目录多了一个 components.json,且 lib/utils.ts 文件被自动创建了(用于处理 CSS 类名合并)。


1.2 安装基础图标库
我们需要一套漂亮的图标,这里使用 Lucide React(Shadcn 官方推荐):
npm install lucide-react

2. 目录结构规划
在 Next.js 16 (App Router) 中,文件放哪里很有讲究。为了保证项目后期不乱,我们先建好“房间”:
在 app 目录下,创建以下文件夹:
app/ui:存放所有的 UI 组件(侧边栏、卡片、按钮等)。app/lib:存放数据定义、工具函数。app/dashboard:核心业务页面(在这个文件夹下的page.tsx只有登录后才能访问)。

3. 实战:搭建 Dashboard 布局
我们要实现的是经典的 “左侧固定侧边栏 + 右侧内容自适应” 布局。
3.1 第一步:编写侧边栏组件 (SideNav)
新建文件 app/ui/dashboard/sidenav.tsx。
我们将使用 Next.js 的 <Link> 组件来实现无刷新跳转,用 Tailwind 实现样式。
import Link from 'next/link';
import {
LayoutDashboard,
Building2,
Users,
ShieldCheck,
Menu,
GraduationCap,
LogOut
} from 'lucide-react';
// 定义菜单数据(暂时写死,后续会从数据库读取)
const links = [
{ name: '工作台', href: '/dashboard', icon: LayoutDashboard },
{ name: '机构管理', href: '/dashboard/dept', icon: Building2 },
{ name: '人员管理', href: '/dashboard/user', icon: Users },
{ name: '角色管理', href: '/dashboard/role', icon: ShieldCheck },
{ name: '菜单配置', href: '/dashboard/menu', icon: Menu },
];
export default function SideNav() {
return (
<div className="flex h-full flex-col px-3 py-4 md:px-2">
{/* 1. Logo 区域 */}
<Link
className="mb-2 flex h-20 items-end justify-start rounded-md bg-zinc-900 p-4 md:h-40"
href="/"
>
<div className="w-32 text-white md:w-40 flex items-center gap-2">
<GraduationCap className="h-8 w-8" />
<span className="text-lg font-bold">教培管家</span>
</div>
</Link>
{/* 2. 导航链接区域 */}
<div className="flex grow flex-row justify-between space-x-2 md:flex-col md:space-x-0 md:space-y-2">
{links.map((link) => {
const LinkIcon = link.icon;
return (
<Link
key={link.name}
href={link.href}
className="flex h-[48px] grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3"
>
<LinkIcon className="w-6" />
<p className="hidden md:block">{link.name}</p>
</Link>
);
})}
{/* 占位符,把登出按钮顶到底部 */}
<div className="hidden h-auto w-full grow rounded-md bg-gray-50 md:block"></div>
{/* 3. 登出按钮 */}
<form>
<button className="flex h-[48px] w-full grow items-center justify-center gap-2 rounded-md bg-gray-50 p-3 text-sm font-medium hover:bg-sky-100 hover:text-blue-600 md:flex-none md:justify-start md:p-2 md:px-3">
<LogOut className="w-6" />
<div className="hidden md:block">退出登录</div>
</button>
</form>
</div>
</div>
);
}
AI 编程小技巧:
如果你不理解上面的 Tailwind 类名(如md:hidden),可以在 Trae 的聊天框里选中代码问 Kimi:“解释一下这段代码中 Tailwind 类名的作用,特别是响应式部分。”

3.2 第二步:创建布局文件 (Layout)
Next.js 的 layout.tsx 是一个非常强大的特性。它允许我们在多个页面之间共享 UI(比如侧边栏),当页面切换时,侧边栏不会重新渲染,状态得以保留。
新建文件 app/dashboard/layout.tsx:
import SideNav from '@/app/ui/dashboard/sidenav';
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<div className="flex h-screen flex-col md:flex-row md:overflow-hidden">
{/* 侧边栏区域:在移动端是顶部导航,在桌面端是左侧固定 */}
<div className="w-full flex-none md:w-64 bg-white border-r">
<SideNav />
</div>
{/* 主内容区域:可滚动 */}
<div className="flex-grow p-6 md:overflow-y-auto md:p-12 bg-gray-50">
{children}
</div>
</div>
);
}

3.3 第三步:创建第一个页面
为了验证效果,我们需要一个页面。
新建 app/dashboard/page.tsx:
export default function Page() {
return (
<div>
<h1 className="text-2xl font-bold mb-4">工作台 Dashboard</h1>
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{/* 这里以后放统计卡片 */}
<div className="h-32 rounded-xl bg-white p-4 shadow-sm border border-gray-100">
<p className="text-sm text-gray-500">总学员数</p>
<p className="text-2xl font-bold">1,203</p>
</div>
<div className="h-32 rounded-xl bg-white p-4 shadow-sm border border-gray-100">
<p className="text-sm text-gray-500">本月营收</p>
<p className="text-2xl font-bold">¥ 45,231</p>
</div>
</div>
</div>
);
}

4. 见证奇迹
现在,在终端运行:
npm run dev

打开浏览器访问 http://localhost:3000/dashboard。
你应该能看到一个专业的后台管理界面:
- 左侧是黑色的 Logo 和 灰色的导航菜单。
- 右侧是灰色的背景和白色的数据卡片。
- 尝试缩小浏览器窗口,你会发现侧边栏自动变为了顶部的移动端导航(这是 Tailwind
md:前缀的功劳)。

5 vibe coding
怎么说呢,默认生成的不是太好看,我们来vibe coding一下
先在trae里打开我们的页面,然后用选中元素选中我们左侧的工作台菜单,这样右边的对话框可以看到一个a标签,输入提示词
工作台增加一个选中的效果

点击发送的箭头,让ai帮我们优化一下
ai调整好了之后,点击代码审查,可以看一下他帮我们加了什么
确认无误后,点击对号接受修改,再次刷新页面,当前工作台就高亮显示了

再一个我们的LOGO有点过于高了,我们让AI优化一下,告诉他调整到合适的高度
优化之后,看起来就顺眼多了
在当下,大模型的多模态能力,结合trae的选中元素功能,组合起来,只要你把意图表达明白,大模型就可以又好又快的实现功能。
确认修改后,我们让kimi把代码提交到我们的远程仓库里
有些命令是需要我们点击运行的,点运行,一路按照提示,就可以看到代码被正确的提交到了仓库里
下一步预告
现在的页面虽然好看,但数据是“死”的,菜单也是写死的。
在 下一篇 中,我们将深入后端核心:
- 使用 Seed 脚本 填充数据库(包含真实的部门、角色、菜单数据)。
- 学习如何用 Next.js 的 Server Actions 从数据库读取数据。
- 让左侧菜单变成从数据库动态加载的“活”菜单。
更多推荐
所有评论(0)