生产管理系统前端-上边栏搭建与侧边栏搭建

This commit is contained in:
2025-10-20 10:07:45 +08:00
parent ec58562661
commit b63716d002
39 changed files with 9097 additions and 6668 deletions

View File

@@ -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()
}
```
### 状态管理架构