01Nextjs+shadcn 医疗预约系统搭建-初始化脚手架

目录

  • [1 环境准备](#1 环境准备)
  • [2 初始化 Next.js](#2 初始化 Next.js)
  • [3 集成 Shadcn UI](#3 集成 Shadcn UI)
  • [4 清理与重置](#4 清理与重置)
    • [4.1 清空全局样式](#4.1 清空全局样式)
    • [4.2 重置首页](#4.2 重置首页)
  • [5 目录结构规划](#5 目录结构规划)
  • [6. 启动验证](#6. 启动验证)

我们的低代码小程序已经搭建的差不多了,为了对比,我们再用纯代码重新架构一遍。第一篇先搭建脚手架

1 环境准备

纯代码我们的技术栈还是基于javascript,首先确保你安装了nodejs,打开cmd命令行查看一下安装的版本

bash 复制代码
node -v

2 初始化 Next.js

nextjs作为react的全栈框架非常适合作为我们的框架使用,使用命令行安装nextjs

bash 复制代码
npx create-next-app@latest hospital-booking-system

3 集成 Shadcn UI

用trae打开我们按照好的目录,新建一个终端

运行初始化命令:

bash 复制代码
npx shadcn@latest init

安装基础组件

bash 复制代码
npx shadcn@latest add button input card

4 清理与重置

Next.js 默认生成的首页太花哨了,我们需要一个干净的画板。

4.1 清空全局样式

打开 src/app/globals.css,删除所有内容,贴入如下代码:

bash 复制代码
@import "tailwindcss";
@import "tw-animate-css";

@custom-variant dark (&:is(.dark *));

:root {
  --muted: oklch(0.967 0.001 286.375);
  --muted-foreground: oklch(0.552 0.016 285.938);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.141 0.005 285.823);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.141 0.005 285.823);
  --border: oklch(0.92 0.004 286.32);
  --input: oklch(0.92 0.004 286.32);
  --primary: oklch(0.21 0.006 285.885);
  --primary-foreground: oklch(0.985 0 0);
  --secondary: oklch(0.967 0.001 286.375);
  --secondary-foreground: oklch(0.21 0.006 285.885);
  --accent: oklch(0.967 0.001 286.375);
  --accent-foreground: oklch(0.21 0.006 285.885);
  --destructive: oklch(0.577 0.245 27.325);
  --destructive-foreground: 0% 0% 98%;
  --ring: oklch(0.705 0.015 286.067);
  --radius: 0.625rem;
  --background: oklch(1 0 0);
  --foreground: oklch(0.141 0.005 285.823);
  --chart-1: oklch(0.646 0.222 41.116);
  --chart-2: oklch(0.6 0.118 184.704);
  --chart-3: oklch(0.398 0.07 227.392);
  --chart-4: oklch(0.828 0.189 84.429);
  --chart-5: oklch(0.769 0.188 70.08);
  --sidebar: oklch(0.985 0 0);
  --sidebar-foreground: oklch(0.141 0.005 285.823);
  --sidebar-primary: oklch(0.21 0.006 285.885);
  --sidebar-primary-foreground: oklch(0.985 0 0);
  --sidebar-accent: oklch(0.967 0.001 286.375);
  --sidebar-accent-foreground: oklch(0.21 0.006 285.885);
  --sidebar-border: oklch(0.92 0.004 286.32);
  --sidebar-ring: oklch(0.705 0.015 286.067);
}

.dark {
  --background: oklch(0.141 0.005 285.823);
  --foreground: oklch(0.985 0 0);
  --muted: oklch(0.274 0.006 286.033);
  --muted-foreground: oklch(0.705 0.015 286.067);
  --popover: oklch(0.21 0.006 285.885);
  --popover-foreground: oklch(0.985 0 0);
  --card: oklch(0.21 0.006 285.885);
  --card-foreground: oklch(0.985 0 0);
  --border: oklch(1 0 0 / 10%);
  --input: oklch(1 0 0 / 15%);
  --primary: oklch(0.92 0.004 286.32);
  --primary-foreground: oklch(0.21 0.006 285.885);
  --secondary: oklch(0.274 0.006 286.033);
  --secondary-foreground: oklch(0.985 0 0);
  --accent: oklch(0.274 0.006 286.033);
  --accent-foreground: oklch(0.985 0 0);
  --destructive: oklch(0.704 0.191 22.216);
  --destructive-foreground: 0% 0% 98%;
  --ring: oklch(0.552 0.016 285.938);
  --chart-1: oklch(0.488 0.243 264.376);
  --chart-2: oklch(0.696 0.17 162.48);
  --chart-3: oklch(0.769 0.188 70.08);
  --chart-4: oklch(0.627 0.265 303.9);
  --chart-5: oklch(0.645 0.246 16.439);
  --sidebar: oklch(0.21 0.006 285.885);
  --sidebar-foreground: oklch(0.985 0 0);
  --sidebar-primary: oklch(0.488 0.243 264.376);
  --sidebar-primary-foreground: oklch(0.985 0 0);
  --sidebar-accent: oklch(0.274 0.006 286.033);
  --sidebar-accent-foreground: oklch(0.985 0 0);
  --sidebar-border: oklch(1 0 0 / 10%);
  --sidebar-ring: oklch(0.552 0.016 285.938);
}

@theme {
  --color-background: oklch(var(--background));
  --color-foreground: oklch(var(--foreground));
  --color-muted: oklch(var(--muted));
  --color-muted-foreground: oklch(var(--muted-foreground));
  --color-popover: oklch(var(--popover));
  --color-popover-foreground: oklch(var(--popover-foreground));
  --color-card: oklch(var(--card));
  --color-card-foreground: oklch(var(--card-foreground));
  --color-border: oklch(var(--border));
  --color-input: oklch(var(--input));
  --color-primary: oklch(var(--primary));
  --color-primary-foreground: oklch(var(--primary-foreground));
  --color-secondary: oklch(var(--secondary));
  --color-secondary-foreground: oklch(var(--secondary-foreground));
  --color-accent: oklch(var(--accent));
  --color-accent-foreground: oklch(var(--accent-foreground));
  --color-destructive: oklch(var(--destructive));
  --color-destructive-foreground: oklch(var(--destructive-foreground));
  --color-ring: oklch(var(--ring));

  --radius: var(--radius);
}

@theme inline {
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-popover: var(--popover);
  --color-popover-foreground: var(--popover-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-secondary: var(--secondary);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-accent: var(--accent);
  --color-accent-foreground: var(--accent-foreground);
  --color-destructive: var(--destructive);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --color-chart-1: var(--chart-1);
  --color-chart-2: var(--chart-2);
  --color-chart-3: var(--chart-3);
  --color-chart-4: var(--chart-4);
  --color-chart-5: var(--chart-5);
  --color-sidebar: var(--sidebar);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-ring: var(--sidebar-ring);
}

@layer base {
  * {
    @apply border-border outline-ring/50;
  }
  body {
    @apply bg-background text-foreground;
  }
}

4.2 重置首页

打开 src/app/page.tsx,替换为以下简单的代码。我们顺便用一下刚才安装的 Button,验证 Shadcn 是否生效。

bash 复制代码
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";

export default function Home() {
  return (
    <div className="flex h-screen w-full items-center justify-center bg-gray-50">
      <Card className="w-[350px]">
        <CardHeader>
          <CardTitle>系统初始化成功</CardTitle>
        </CardHeader>
        <CardContent>
          <p className="mb-4 text-sm text-muted-foreground">
            Next.js + Shadcn 医院预约系统环境已准备就绪。
          </p>
          <Button className="w-full">进入系统</Button>
        </CardContent>
      </Card>
    </div>
  );
}

5 目录结构规划

在开始写业务逻辑前,我们需要按照**"PC端与移动端分离"**的策略规划路由。在 src/app 下,我们将建立完全隔离的布局体系。

请在手动创建以下文件夹结构:

bash 复制代码
src/
├── app/
│   ├── (auth)/           # 路由组:登录注册(不影响URL路径)
│   │   ├── login/        # localhost:3000/login
│   │   └── register/     # localhost:3000/register
│   ├── admin/            # PC管理端
│   │   ├── dashboard/    # localhost:3000/admin/dashboard
│   │   ├── department/   # 科室管理
│   │   ├── doctors/      # 医生管理
│   │   └── layout.tsx    # ★ PC端专用布局(侧边栏+顶栏)
│   ├── mobile/           # 移动端/小程序H5
│   │   ├── home/         # localhost:3000/mobile/home
│   │   └── layout.tsx    # ★ 移动端专用布局(底部导航)
│   ├── api/              # 后端接口
│   ├── layout.tsx        # 全局根布局
│   └── page.tsx          # 根入口(通常重定向到 login 或 home)
├── components/
│   ├── ui/               # shadcn 通用组件
│   ├── admin/            # PC端专用业务组件 (如 Sidebar)
│   └── mobile/           # 移动端专用业务组件 (如 TabBar)
└── lib/
    ├── db.ts             # 数据库连接单例
    └── utils.ts          # 工具函数

6. 启动验证

最后,让我们启动开发服务器:

bash 复制代码
npm run dev

打开浏览器访问 http://localhost:3000

相关推荐
吉吉安5 天前
Nextjs+Supabase
前端·nextjs·supabase·vercel
wanfeng_092 个月前
stripe/paypal
react·ts·nextjs·paypal·stripe
PyAIGCMaster3 个月前
我的项目开发的一般流程,供交流
react·nextjs
叶常落5 个月前
感恩日记:记录生活中的美好时刻
nextjs
飞鸟malred6 个月前
nextjs入门
前端·react·nextjs
任磊abc9 个月前
nextjs15简要介绍以及配置eslint和prettier
eslint·nextjs·prettier·nextjs15
任磊abc9 个月前
nextjs+material UI实现换肤功能
nextjs·material ui·换肤
engchina10 个月前
使用 Vite + React 19 集成 Tailwind CSS 与 shadcn/ui 组件库完整指南
css·react.js·ui·vite·tailwind·react 19·shadcn
堂铭1 年前
NextJS多语言
前端·i18n·nextjs