生产管理系统前端-上边栏搭建与侧边栏搭建
This commit is contained in:
File diff suppressed because it is too large
Load Diff
135
docs/stories/story-1-9-三级菜单实现.md
Normal file
135
docs/stories/story-1-9-三级菜单实现.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# 用户故事:多级菜单布局系统重构
|
||||
|
||||
## 故事标题
|
||||
**多级菜单布局系统重构 - Brownfield Addition**
|
||||
|
||||
## 用户故事
|
||||
作为系统用户,
|
||||
我需要一个新的多级菜单布局系统,
|
||||
以便更好地组织和访问系统的各个功能模块。
|
||||
|
||||
## 故事上下文
|
||||
|
||||
### 现有系统集成
|
||||
- **集成与**: 现有 `Navigation.tsx` 和 `Sidebar.tsx` 组件
|
||||
- **技术**: React + TypeScript + Tailwind CSS
|
||||
- **遵循模式**: 现有 shadcn/ui 组件库和项目架构
|
||||
- **接触点**: `src/App.tsx`, 路由系统, 菜单配置
|
||||
|
||||
## 验收标准
|
||||
|
||||
### 功能需求
|
||||
|
||||
#### 1. 顶部菜单栏 (占15%视口高度)
|
||||
- **左侧**: Logo + "智慧农业生产管理系统"标题
|
||||
- 显示绿色拖拉机图标和系统名称
|
||||
- 包含英文副标题 "Smart Agriculture Management System"
|
||||
- **中间**: 7大子系统菜单项与图标
|
||||
- 智能农机管理系统 (Tractor图标)
|
||||
- 地块信息管理系统 (Map图标)
|
||||
- 农事操作管理系统 (Clipboard图标)
|
||||
- 农业资产管理系统 (Package图标)
|
||||
- AI作物模型精准决策系统 (Brain图标)
|
||||
- 水肥一体化控制系统 (Droplets图标)
|
||||
- 中心配置管理系统 (Settings图标)
|
||||
- **右侧**: 用户功能区域
|
||||
- 消息铃铛图标(显示未读消息数量)
|
||||
- 系统管理员用户信息(头像+用户名)
|
||||
- 用户下拉菜单(个人中心、退出登录等选项)
|
||||
|
||||
#### 2. 左侧二级菜单
|
||||
- 根据选中的一级菜单动态显示对应的二级菜单项
|
||||
- 支持多级展开/折叠功能
|
||||
- 当前选中页面高亮显示(绿色背景)
|
||||
- 菜单项层次清晰,缩进合理
|
||||
|
||||
#### 3. 右侧内容区域
|
||||
- 根据路由对应显示具体页面内容
|
||||
- 无路由对应时显示空页面状态
|
||||
- 内容区域自适应高度和宽度
|
||||
- 保持现有页面组件的功能不变
|
||||
|
||||
### 集成需求
|
||||
4. **现有导航功能继续正常工作**: 保持与 `src/App.tsx` 中现有路由逻辑的兼容性
|
||||
5. **新布局遵循现有的设计模式和样式**: 使用 shadcn/ui 组件库,保持绿色主题
|
||||
6. **与现有认证系统和路由系统无缝集成**: 保持 `AuthContext` 和路径状态管理
|
||||
|
||||
### 质量需求
|
||||
7. **响应式设计**: 适配不同屏幕尺寸(桌面、平板、移动端)
|
||||
8. **保持现有功能不回退**: 所有现有页面和功能必须正常工作
|
||||
9. **代码符合现有项目规范**: 遵循 TypeScript 严格模式,使用现有工具函数
|
||||
|
||||
## 技术说明
|
||||
|
||||
### 集成方法
|
||||
- **目录结构**: 在 `src/components/layouts/` 目录创建新的布局组件系统
|
||||
- **文件组织**:
|
||||
- `MainLayout.tsx` - 主布局容器
|
||||
- `TopNavigation.tsx` - 顶部导航栏
|
||||
- `SideNavigation.tsx` - 侧边栏导航
|
||||
- `ContentArea.tsx` - 内容区域组件
|
||||
|
||||
### 现有模式参考
|
||||
- **组件样式**: 参考现有的 `Navigation.tsx` 实现模式
|
||||
- **菜单数据处理**: 保持与 `types/navigation.ts` 中菜单结构的一致性
|
||||
- **状态管理**: 使用现有的 `useState` 和路径状态管理模式
|
||||
- **UI组件**: 使用现有的 shadcn/ui 组件(Button, Popover, Badge等)
|
||||
|
||||
### 关键约束
|
||||
- **保持现有菜单结构**: 7个子系统的菜单配置和层级结构不能改变
|
||||
- **保持路由逻辑**: 现有的路径导航和页面渲染逻辑必须保持兼容
|
||||
- **保持认证集成**: 用户认证状态和权限控制逻辑保持不变
|
||||
- **保持主题风格**: 绿色主题和整体视觉风格保持一致
|
||||
|
||||
## 风险和兼容性检查
|
||||
|
||||
### 最小风险评估
|
||||
- **主要风险**: 布局重构可能影响现有页面的显示和交互
|
||||
- **缓解措施**: 渐进式重构,保持现有组件接口不变
|
||||
- **回滚方案**: 可快速回退到现有的 Navigation + Sidebar 布局
|
||||
|
||||
### 兼容性验证
|
||||
- [x] 无对现有API的破坏性更改
|
||||
- [x] 无数据库变更(纯前端重构)
|
||||
- [x] UI更改遵循现有设计模式
|
||||
- [x] 对性能的影响可忽略不计
|
||||
|
||||
## 验证清单
|
||||
|
||||
### 范围验证
|
||||
- [x] 故事可在一次开发会话内完成(预计2-4小时)
|
||||
- [x] 集成方法直接明了
|
||||
- [x] 完全遵循现有模式
|
||||
- [x] 无需设计或架构工作
|
||||
|
||||
### 清晰度检查
|
||||
- [x] 故事要求明确无误
|
||||
- [x] 集成点明确指定
|
||||
- [x] 成功标准可测试
|
||||
- [x] 回滚计划简单
|
||||
|
||||
## 完成标准
|
||||
|
||||
- [ ] 顶部菜单栏正确显示,占15%视口高度
|
||||
- [ ] 7大子系统菜单项正确显示并可点击
|
||||
- [ ] 消息铃铛和用户下拉菜单功能正常
|
||||
- [ ] 左侧二级菜单根据一级菜单选择动态更新
|
||||
- [ ] 右侧内容区域正确显示对应页面内容
|
||||
- [ ] 响应式设计在不同屏幕尺寸下正常工作
|
||||
- [ ] 现有功能回归测试通过
|
||||
- [ ] 代码遵循现有模式和标准
|
||||
- [ ] 与现有认证系统正常集成
|
||||
- [ ] 无浏览器控制台错误或警告
|
||||
|
||||
## 重要的注意事项
|
||||
|
||||
- 这个故事主要涉及UI结构调整,不需要复杂的后端集成
|
||||
- 重构过程中应保持所有现有页面的功能和数据流
|
||||
- 重点关注用户体验的一致性和导航的流畅性
|
||||
- 如果复杂度超出预期,考虑拆分为多个较小的故事
|
||||
- 预计开发时间:2-4小时的专注开发工作
|
||||
|
||||
---
|
||||
**故事创建时间**: 2025-10-17
|
||||
**创建人**: PM Agent (John)
|
||||
**预计工作量**: 0.5 story points (小型重构任务)
|
||||
471
docs/项目架构设计文档.md
471
docs/项目架构设计文档.md
@@ -218,7 +218,9 @@ interface User {
|
||||
- ✅ React Hook Form + Zod
|
||||
|
||||
#### 新增核心技术
|
||||
- 🆕 **React Router v6**: 专业路由管理
|
||||
- 🆕 **Next.js 14**: 现代化 React 全栈框架,支持动态路由和SSR
|
||||
- 🆕 **Next.js App Router**: 基于文件系统的动态路由
|
||||
- 🆕 **React Server Components**: 服务端组件渲染优化
|
||||
- 🆕 **Zustand**: 轻量级状态管理
|
||||
- 🆕 **TanStack Query**: 服务端状态管理
|
||||
- 🆕 **MSW**: Mock Service Worker
|
||||
@@ -231,8 +233,48 @@ interface User {
|
||||
crop-x/
|
||||
├── public/ # 静态资源
|
||||
│ ├── favicon.ico
|
||||
│ └── index.html
|
||||
│ └── next-env.d.ts # Next.js 类型声明
|
||||
├── src/
|
||||
│ ├── app/ # Next.js App Router 目录
|
||||
│ │ ├── layout.tsx # 根布局
|
||||
│ │ ├── page.tsx # 首页
|
||||
│ │ ├── globals.css # 全局样式
|
||||
│ │ ├── (auth)/ # 认证相关路由组
|
||||
│ │ │ ├── login/
|
||||
│ │ │ │ └── page.tsx
|
||||
│ │ │ └── register/
|
||||
│ │ │ └── page.tsx
|
||||
│ │ ├── machinery/ # 农机管理动态路由
|
||||
│ │ │ ├── layout.tsx # 农机模块布局
|
||||
│ │ │ ├── page.tsx # 农机默认页面
|
||||
│ │ │ ├── archive/
|
||||
│ │ │ │ ├── entry/
|
||||
│ │ │ │ │ └── page.tsx
|
||||
│ │ │ │ └── [id]/
|
||||
│ │ │ │ └── page.tsx # 动态路由详情页
|
||||
│ │ │ ├── driver/
|
||||
│ │ │ │ └── page.tsx
|
||||
│ │ │ └── monitoring/
|
||||
│ │ │ └── realtime/
|
||||
│ │ │ └── page.tsx
|
||||
│ │ ├── field/ # 地块管理动态路由
|
||||
│ │ │ ├── layout.tsx
|
||||
│ │ │ ├── page.tsx
|
||||
│ │ │ └── [category]/
|
||||
│ │ │ └── page.tsx
|
||||
│ │ ├── operation/ # 农事操作动态路由
|
||||
│ │ ├── asset/ # 资产管理动态路由
|
||||
│ │ ├── ai-model/ # AI模型动态路由
|
||||
│ │ ├── irrigation/ # 灌溉控制动态路由
|
||||
│ │ ├── config/ # 配置管理动态路由
|
||||
│ │ │ ├── layout.tsx
|
||||
│ │ │ ├── page.tsx
|
||||
│ │ │ └── tenant/
|
||||
│ │ │ ├── enterprise-audit/
|
||||
│ │ │ │ └── page.tsx
|
||||
│ │ │ └── [enterpriseId]/
|
||||
│ │ │ └── page.tsx # 企业详情动态路由
|
||||
│ │ └── loading.tsx # 全局加载组件
|
||||
│ ├── components/ # 可复用组件
|
||||
│ │ ├── ui/ # shadcn/ui 基础组件
|
||||
│ │ │ ├── button/
|
||||
@@ -247,178 +289,307 @@ crop-x/
|
||||
│ │ ├── Header/
|
||||
│ │ ├── Sidebar/
|
||||
│ │ └── Layout/
|
||||
│ ├── pages/ # 页面组件(按业务模块)
|
||||
│ │ ├── auth/ # 认证相关页面
|
||||
│ │ │ ├── LoginPage.tsx
|
||||
│ │ │ └── RegisterPage.tsx
|
||||
│ │ ├── machinery/ # 农机管理页面
|
||||
│ │ │ ├── MachineryListPage.tsx
|
||||
│ │ │ ├── MachineryDetailPage.tsx
|
||||
│ │ │ ├── DriverListPage.tsx
|
||||
│ ├── lib/ # Next.js 库目录
|
||||
│ │ ├── stores/ # Zustand 状态管理
|
||||
│ │ │ ├── authStore.ts
|
||||
│ │ │ ├── machineryStore.ts
|
||||
│ │ │ └── ...
|
||||
│ │ ├── field/ # 地块管理页面
|
||||
│ │ ├── operation/ # 农事操作页面
|
||||
│ │ ├── asset/ # 资产管理页面
|
||||
│ │ ├── ai-model/ # AI模型页面
|
||||
│ │ ├── irrigation/ # 灌溉控制页面
|
||||
│ │ └── config/ # 配置管理页面
|
||||
│ ├── stores/ # Zustand 状态管理
|
||||
│ │ ├── authStore.ts # 认证状态
|
||||
│ │ ├── machineryStore.ts # 农机状态
|
||||
│ │ ├── fieldStore.ts # 地块状态
|
||||
│ │ ├── operationStore.ts # 农事状态
|
||||
│ │ ├── assetStore.ts # 资产状态
|
||||
│ │ ├── aiModelStore.ts # AI模型状态
|
||||
│ │ ├── irrigationStore.ts # 灌溉状态
|
||||
│ │ └── configStore.ts # 配置状态
|
||||
│ ├── services/ # API 服务层
|
||||
│ │ ├── api/ # API 配置和请求
|
||||
│ │ │ ├── client.ts # Axios 配置
|
||||
│ │ │ ├── machineryApi.ts
|
||||
│ │ │ ├── fieldApi.ts
|
||||
│ │ │ └── ...
|
||||
│ │ ├── mock/ # Mock 数据管理
|
||||
│ │ │ ├── handlers/ # MSW 处理器
|
||||
│ │ │ ├── data/ # Mock 数据
|
||||
│ │ │ └── browser.ts # MSW 配置
|
||||
│ │ └── types/ # API 类型定义
|
||||
│ │ ├── machinery.ts
|
||||
│ │ ├── field.ts
|
||||
│ │ └── ...
|
||||
│ ├── hooks/ # 自定义 Hooks
|
||||
│ │ ├── useAuth.ts
|
||||
│ │ ├── useMachinery.ts
|
||||
│ │ └── ...
|
||||
│ ├── utils/ # 工具函数
|
||||
│ │ ├── date.ts
|
||||
│ │ ├── format.ts
|
||||
│ │ └── ...
|
||||
│ ├── constants/ # 常量定义
|
||||
│ │ ├── routes.ts
|
||||
│ │ ├── permissions.ts
|
||||
│ │ └── ...
|
||||
│ ├── router/ # 路由配置
|
||||
│ │ ├── index.ts # 路由器配置
|
||||
│ │ ├── authRoutes.ts # 认证路由
|
||||
│ │ ├── machineryRoutes.ts # 农机路由
|
||||
│ │ └── ...
|
||||
│ ├── styles/ # 样式文件
|
||||
│ │ ├── globals.css
|
||||
│ │ └── components.css
|
||||
│ │ ├── services/ # API 服务层
|
||||
│ │ │ ├── api/ # API 配置和请求
|
||||
│ │ │ │ ├── client.ts
|
||||
│ │ │ │ ├── machineryApi.ts
|
||||
│ │ │ │ └── ...
|
||||
│ │ │ ├── mock/ # Mock 数据管理
|
||||
│ │ │ │ ├── handlers/
|
||||
│ │ │ │ ├── data/
|
||||
│ │ │ │ └── browser.ts
|
||||
│ │ │ └── types/
|
||||
│ │ │ ├── machinery.ts
|
||||
│ │ │ └── ...
|
||||
│ │ ├── hooks/ # 自定义 Hooks
|
||||
│ │ │ ├── useAuth.ts
|
||||
│ │ │ └── useMachinery.ts
|
||||
│ │ ├── utils/ # 工具函数
|
||||
│ │ │ ├── date.ts
|
||||
│ │ │ └── format.ts
|
||||
│ │ └── constants/ # 常量定义
|
||||
│ │ ├── routes.ts
|
||||
│ │ └── permissions.ts
|
||||
│ ├── types/ # 全局类型定义
|
||||
│ │ ├── auth.ts
|
||||
│ │ ├── machinery.ts
|
||||
│ │ ├── navigation.ts
|
||||
│ │ └── ...
|
||||
│ ├── App.tsx # 根组件
|
||||
│ └── main.tsx # 应用入口
|
||||
│ │ └── navigation.ts
|
||||
│ └── styles/ # 样式文件
|
||||
│ └── globals.css
|
||||
├── tests/ # 测试文件
|
||||
│ ├── __mocks__/ # 全局 Mock
|
||||
│ ├── fixtures/ # 测试数据
|
||||
│ ├── unit/ # 单元测试
|
||||
│ ├── integration/ # 集成测试
|
||||
│ └── setup.ts # 测试配置
|
||||
│ ├── __mocks__/
|
||||
│ ├── fixtures/
|
||||
│ ├── unit/
|
||||
│ ├── integration/
|
||||
│ └── setup.ts
|
||||
├── docs/ # 项目文档
|
||||
├── .eslintrc.js # ESLint 配置
|
||||
├── .prettierrc # Prettier 配置
|
||||
├── next.config.js # Next.js 配置
|
||||
├── package.json
|
||||
├── vite.config.ts
|
||||
├── tsconfig.json
|
||||
├── tailwind.config.js
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### 路由系统重设计
|
||||
### Next.js 动态路由系统设计
|
||||
|
||||
#### App Router 架构
|
||||
Next.js App Router 提供了基于文件系统的路由,支持动态路由、嵌套路由和路由组。
|
||||
|
||||
#### 路由架构
|
||||
```typescript
|
||||
// router/index.ts
|
||||
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
|
||||
import { ProtectedRoute } from '../components/ProtectedRoute'
|
||||
import { Layout } from '../components/layout/Layout'
|
||||
import { authRoutes } from './authRoutes'
|
||||
import { machineryRoutes } from './machineryRoutes'
|
||||
// ... 其他路由
|
||||
// src/app/layout.tsx - 根布局
|
||||
import { AuthProvider } from '@/lib/providers/AuthProvider'
|
||||
import { ThemeProvider } from '@/lib/providers/ThemeProvider'
|
||||
import './globals.css'
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
// 公开路由
|
||||
...authRoutes,
|
||||
|
||||
// 受保护的主路由
|
||||
{
|
||||
path: '/',
|
||||
element: (
|
||||
<ProtectedRoute>
|
||||
<Layout />
|
||||
</ProtectedRoute>
|
||||
),
|
||||
children: [
|
||||
// 7大业务系统路由
|
||||
...machineryRoutes,
|
||||
...fieldRoutes,
|
||||
...operationRoutes,
|
||||
...assetRoutes,
|
||||
...aiModelRoutes,
|
||||
...irrigationRoutes,
|
||||
...configRoutes,
|
||||
|
||||
// 默认路由
|
||||
{
|
||||
index: true,
|
||||
element: <Navigate to="/machinery/archive/entry" replace />
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
// 404页面
|
||||
{ path: '*', element: <NotFoundPage /> }
|
||||
])
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="zh-CN">
|
||||
<body>
|
||||
<ThemeProvider>
|
||||
<AuthProvider>
|
||||
{children}
|
||||
</AuthProvider>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### 业务路由示例
|
||||
#### 动态路由示例
|
||||
|
||||
##### 1. 农机管理模块路由结构
|
||||
```
|
||||
src/app/machinery/
|
||||
├── layout.tsx # 农机模块专属布局
|
||||
├── page.tsx # /machinery - 农机管理首页
|
||||
├── archive/
|
||||
│ ├── page.tsx # /machinery/archive - 档案管理
|
||||
│ ├── entry/
|
||||
│ │ └── page.tsx # /machinery/archive/entry - 档案录入
|
||||
│ └── [id]/
|
||||
│ └── page.tsx # /machinery/archive/[id] - 动态详情页
|
||||
├── driver/
|
||||
│ ├── page.tsx # /machinery/driver - 驾驶员管理
|
||||
│ └── [driverId]/
|
||||
│ └── page.tsx # /machinery/driver/[driverId] - 驾驶员详情
|
||||
└── monitoring/
|
||||
└── realtime/
|
||||
└── page.tsx # /machinery/monitoring/realtime - 实时监控
|
||||
```
|
||||
|
||||
##### 2. 动态路由组件实现
|
||||
```typescript
|
||||
// router/machineryRoutes.ts
|
||||
import { lazy } from 'react'
|
||||
// src/app/machinery/archive/[id]/page.tsx
|
||||
import { notFound } from 'next/navigation'
|
||||
import { MachineryDetailPage } from '@/components/pages/machinery/MachineryDetailPage'
|
||||
import { getMachineryById } from '@/lib/services/api/machineryApi'
|
||||
|
||||
// 懒加载页面组件
|
||||
const MachineryListPage = lazy(() => import('../pages/machinery/MachineryListPage'))
|
||||
const MachineryDetailPage = lazy(() => import('../pages/machinery/MachineryDetailPage'))
|
||||
const DriverListPage = lazy(() => import('../pages/machinery/DriverListPage'))
|
||||
interface Props {
|
||||
params: { id: string }
|
||||
}
|
||||
|
||||
export const machineryRoutes = [
|
||||
{
|
||||
path: 'machinery/*',
|
||||
children: [
|
||||
// 农机档案管理
|
||||
{
|
||||
path: 'archive/entry',
|
||||
element: <MachineryListPage />
|
||||
},
|
||||
{
|
||||
path: 'archive/detail/:id',
|
||||
element: <MachineryDetailPage />
|
||||
},
|
||||
export default async function MachineryDetail({ params }: Props) {
|
||||
const machinery = await getMachineryById(params.id)
|
||||
|
||||
// 驾驶员管理
|
||||
{
|
||||
path: 'driver/list',
|
||||
element: <DriverListPage />
|
||||
},
|
||||
|
||||
// 实时监控
|
||||
{
|
||||
path: 'monitoring/realtime',
|
||||
element: lazy(() => import('../pages/machinery/MonitoringPage'))
|
||||
},
|
||||
|
||||
// 任务调度
|
||||
{
|
||||
path: 'scheduling/task',
|
||||
element: lazy(() => import('../pages/machinery/SchedulingPage'))
|
||||
}
|
||||
]
|
||||
if (!machinery) {
|
||||
notFound()
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="container mx-auto p-6">
|
||||
<MachineryDetailPage machinery={machinery} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// 生成静态路径(可选,用于SSG)
|
||||
export async function generateStaticParams() {
|
||||
// 预生成一些常见的农机详情页
|
||||
return [
|
||||
{ id: 'machinery-001' },
|
||||
{ id: 'machinery-002' },
|
||||
{ id: 'machinery-003' },
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
##### 3. 路由组的使用
|
||||
```
|
||||
src/app/
|
||||
├── (auth)/ # 路由组:不影响URL路径
|
||||
│ ├── layout.tsx # 认证页面专属布局
|
||||
│ ├── login/
|
||||
│ │ └── page.tsx # /login
|
||||
│ └── register/
|
||||
│ └── page.tsx # /register
|
||||
├── (dashboard)/ # 路由组:受保护的管理区域
|
||||
│ ├── layout.tsx # 仪表板布局
|
||||
│ ├── machinery/
|
||||
│ ├── field/
|
||||
│ └── config/
|
||||
```
|
||||
|
||||
##### 4. 路由布局系统
|
||||
```typescript
|
||||
// src/app/(dashboard)/layout.tsx
|
||||
import { SidebarProvider } from '@/lib/providers/SidebarProvider'
|
||||
import { MainLayout } from '@/components/layout/MainLayout'
|
||||
import { auth } from '@/lib/auth'
|
||||
|
||||
export default async function DashboardLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
// 服务端认证检查
|
||||
const session = await auth()
|
||||
|
||||
if (!session) {
|
||||
redirect('/login')
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<MainLayout>
|
||||
{children}
|
||||
</MainLayout>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### 动态路由特性
|
||||
|
||||
##### 1. 路由参数处理
|
||||
```typescript
|
||||
// src/app/config/tenant/[enterpriseId]/page.tsx
|
||||
interface PageProps {
|
||||
params: { enterpriseId: string }
|
||||
searchParams: { [key: string]: string | string[] | undefined }
|
||||
}
|
||||
|
||||
export default async function EnterpriseDetail({
|
||||
params,
|
||||
searchParams,
|
||||
}: PageProps) {
|
||||
const enterpriseId = params.enterpriseId
|
||||
const tab = searchParams.tab as string || 'basic'
|
||||
|
||||
// 根据查询参数显示不同tab
|
||||
return (
|
||||
<div>
|
||||
<h1>企业详情:{enterpriseId}</h1>
|
||||
<EnterpriseDetailTab activeTab={tab} enterpriseId={enterpriseId} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
##### 2. 平行路由和插槽
|
||||
```typescript
|
||||
// src/app/machinery/layout.tsx
|
||||
export default function MachineryLayout({
|
||||
children,
|
||||
analytics,
|
||||
monitoring, // 插槽
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
analytics?: React.ReactNode
|
||||
monitoring?: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<div className="flex h-full">
|
||||
<div className="flex-1">{children}</div>
|
||||
{analytics && (
|
||||
<div className="w-80 border-l">{analytics}</div>
|
||||
)}
|
||||
{monitoring && (
|
||||
<div className="w-80 border-l">{monitoring}</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
##### 3. 路由中间件
|
||||
```typescript
|
||||
// middleware.ts
|
||||
import { NextResponse } from 'next/server'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { auth } from './lib/auth'
|
||||
|
||||
export async function middleware(request: NextRequest) {
|
||||
const session = await auth()
|
||||
const { pathname } = request.nextUrl
|
||||
|
||||
// 未登录用户重定向到登录页
|
||||
if (!session && pathname.startsWith('/dashboard')) {
|
||||
return NextResponse.redirect(new URL('/login', request.url))
|
||||
}
|
||||
|
||||
// 已登录用户访问登录页重定向到仪表板
|
||||
if (session && pathname === '/login') {
|
||||
return NextResponse.redirect(new URL('/dashboard', request.url))
|
||||
}
|
||||
|
||||
return NextResponse.next()
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ['/dashboard/:path*', '/login', '/register']
|
||||
}
|
||||
```
|
||||
|
||||
#### 服务端组件优势
|
||||
|
||||
##### 1. 数据获取
|
||||
```typescript
|
||||
// src/app/machinery/page.tsx - 服务端组件
|
||||
import { getMachineryList } from '@/lib/services/api/machineryApi'
|
||||
import { MachineryGrid } from '@/components/business/machinery/MachineryGrid'
|
||||
|
||||
export default async function MachineryPage() {
|
||||
// 服务端直接获取数据
|
||||
const machineryData = await getMachineryList()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>农机管理系统</h1>
|
||||
<MachineryGrid initialData={machineryData} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
##### 2. 缓存和重新验证
|
||||
```typescript
|
||||
// src/lib/services/api/machineryApi.ts
|
||||
export async function getMachineryList() {
|
||||
const res = await fetch('/api/machinery', {
|
||||
next: {
|
||||
tags: ['machinery'], // 缓存标签
|
||||
revalidate: 60, // 60秒重新验证
|
||||
}
|
||||
})
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error('Failed to fetch machinery data')
|
||||
}
|
||||
|
||||
return res.json()
|
||||
}
|
||||
```
|
||||
|
||||
### 状态管理架构
|
||||
|
||||
Reference in New Issue
Block a user