# 开发指南

本文档为智慧农业生产管理系统的开发指南，帮助开发者快速了解项目结构、开发规范和最佳实践。

## 📋 目录

- [环境准备](#环境准备)
- [项目结构](#项目结构)
- [开发规范](#开发规范)
- [组件开发](#组件开发)
- [状态管理](#状态管理)
- [样式指南](#样式指南)
- [API集成](#api集成)
- [测试指南](#测试指南)
- [调试技巧](#调试技巧)
- [常见问题](#常见问题)

## 🛠️ 环境准备

### 必需软件

- **Node.js**: >= 18.0.0
- **npm**: >= 8.0.0 或 **yarn**: >= 1.22.0
- **Git**: 最新版本

### 推荐工具

- **IDE**: Visual Studio Code
- **浏览器**: Chrome/Firefox (最新版本)
- **Node管理**: nvm (可选)

### VSCode扩展推荐

项目已配置 `.vscode/extensions.json`，安装以下扩展获得最佳开发体验：

```json
{
  "recommendations": [
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "bradlc.vscode-tailwindcss",
    "ms-vscode.vscode-typescript-next",
    "formulahendry.auto-rename-tag",
    "christian-kohler.path-intellisense"
  ]
}
```

## 📁 项目结构详解

### 核心目录

```
src/
├── components/          # 组件库
│   ├── ui/             # shadcn/ui基础组件
│   ├── common/         # 通用业务组件
│   └── layouts/        # 布局组件
├── pages/              # 页面组件
├── hooks/              # 自定义Hooks
├── lib/                # 工具库
├── config/             # 配置文件
├── types/              # TypeScript类型
├── utils/              # 工具函数
├── styles/             # 样式文件
└── assets/             # 静态资源
```

### 组件组织原则

1. **UI组件** (`components/ui/`): 纯UI组件，无业务逻辑
2. **业务组件** (`components/common/`): 包含业务逻辑的复用组件
3. **页面组件** (`pages/`): 具体页面实现，组合业务组件
4. **布局组件** (`components/layouts/`): 页面布局结构

## 📏 开发规范

### 代码规范

#### TypeScript规范

```typescript
// ✅ 使用类型注解
interface UserData {
  id: string
  name: string
  email: string
}

const getUser = async (id: string): Promise<UserData> => {
  // 实现
}

// ✅ 使用泛型
interface ApiResponse<T> {
  data: T
  success: boolean
}

// ✅ 枚举使用
enum UserRole {
  ADMIN = 'admin',
  USER = 'user'
}
```

#### React组件规范

```typescript
// ✅ 函数式组件 + Hooks
interface UserCardProps {
  user: UserData
  onEdit?: (user: UserData) => void
  className?: string
}

export const UserCard: React.FC<UserCardProps> = ({
  user,
  onEdit,
  className
}) => {
  const [isEditing, setIsEditing] = useState(false)

  const handleEdit = useCallback(() => {
    onEdit?.(user)
    setIsEditing(true)
  }, [user, onEdit])

  return (
    <div className={cn('user-card', className)}>
      {/* 组件内容 */}
    </div>
  )
}
```

#### 命名规范

- **文件名**: kebab-case (`user-card.tsx`)
- **组件名**: PascalCase (`UserCard`)
- **变量名**: camelCase (`userName`)
- **常量名**: UPPER_SNAKE_CASE (`API_BASE_URL`)
- **类型名**: PascalCase (`UserData`)

### Git提交规范

使用 [Conventional Commits](https://conventionalcommits.org/) 规范：

```
<type>(<scope>): <subject>

<body>

<footer>
```

#### 提交类型

- `feat`: 新功能
- `fix`: 修复bug
- `docs`: 文档更新
- `style`: 代码格式化
- `refactor`: 重构代码
- `test`: 测试相关
- `chore`: 构建工具、依赖更新

#### 示例

```bash
feat(machinery): add machinery status monitoring
fix(auth): resolve login validation issue
docs(readme): update installation guide
```

## 🧩 组件开发

### 组件结构模板

```typescript
// src/components/example/ExampleComponent.tsx
import React, { useState, useCallback } from 'react'
import { cn } from '@/lib/utils'

interface ExampleComponentProps {
  title: string
  onAction?: () => void
  className?: string
}

export const ExampleComponent: React.FC<ExampleComponentProps> = ({
  title,
  onAction,
  className
}) => {
  const [state, setState] = useState(false)

  const handleClick = useCallback(() => {
    setState(prev => !prev)
    onAction?.()
  }, [onAction])

  return (
    <div className={cn('example-component', className)}>
      <h3 className="example-title">{title}</h3>
      <button onClick={handleClick}>
        Click me
      </button>
    </div>
  )
}
```

### 组件样式规范

```css
/* 优先使用Tailwind CSS类名 */
.example-component {
  @apply rounded-lg border border-gray-200 p-4 bg-white shadow-sm;
}

.example-title {
  @apply text-lg font-semibold text-gray-900 mb-2;
}

/* 必要时使用传统CSS */
.example-component:hover {
  transform: translateY(-1px);
  transition: transform 0.2s ease;
}
```

### shadcn/ui组件使用

```typescript
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'

export const MachineryCard = ({ machinery }) => {
  return (
    <Card className="machinery-card">
      <CardHeader>
        <CardTitle>{machinery.name}</CardTitle>
        <Badge variant={machinery.status === 'running' ? 'default' : 'secondary'}>
          {machinery.status}
        </Badge>
      </CardHeader>
      <CardContent>
        {/* 内容 */}
      </CardContent>
    </Card>
  )
}
```

## 🔄 状态管理

### useState使用

```typescript
const [formData, setFormData] = useState({
  name: '',
  email: '',
  phone: ''
})

// 更新对象状态
const handleChange = (field: string, value: string) => {
  setFormData(prev => ({
    ...prev,
    [field]: value
  }))
}
```

### useReducer使用

```typescript
type State = {
  count: number
  loading: boolean
}

type Action =
  | { type: 'increment' }
  | { type: 'decrement' }
  | { type: 'setLoading'; payload: boolean }

const reducer = (state: State, action: Action): State => {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + 1 }
    case 'decrement':
      return { ...state, count: state.count - 1 }
    case 'setLoading':
      return { ...state, loading: action.payload }
    default:
      return state
  }
}

const [state, dispatch] = useReducer(reducer, {
  count: 0,
  loading: false
})
```

### 自定义Hooks

```typescript
// src/hooks/useApi.ts
import { useState, useEffect } from 'react'

export function useApi<T>(url: string) {
  const [data, setData] = useState<T | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    const fetchData = async () => {
      try {
        setLoading(true)
        const response = await fetch(url)
        const result = await response.json()
        setData(result)
      } catch (err) {
        setError(err.message)
      } finally {
        setLoading(false)
      }
    }

    fetchData()
  }, [url])

  return { data, loading, error }
}
```

## 🎨 样式指南

### Tailwind CSS最佳实践

```typescript
// ✅ 使用cn工具函数合并类名
import { cn } from '@/lib/utils'

const Button = ({ variant = 'primary', className, ...props }) => {
  return (
    <button
      className={cn(
        'px-4 py-2 rounded-md font-medium transition-colors',
        {
          'bg-blue-600 text-white hover:bg-blue-700': variant === 'primary',
          'bg-gray-200 text-gray-900 hover:bg-gray-300': variant === 'secondary'
        },
        className
      )}
      {...props}
    />
  )
}
```

### 响应式设计

```typescript
// 移动优先的响应式设计
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  {/* 内容 */}
</div>

// 响应式间距
<div className="px-4 sm:px-6 lg:px-8">
  {/* 内容 */}
</div>
```

### 深色模式支持

```typescript
import { useTheme } from '@/hooks/useTheme'

export const ThemedComponent = () => {
  const { theme, setTheme } = useTheme()

  return (
    <div className="bg-background text-foreground">
      <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
        切换主题
      </button>
    </div>
  )
}
```

## 🌐 API集成

### API配置

```typescript
// src/config/api.ts
export const API_CONFIG = {
  baseUrl: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000
}

export const apiClient = {
  get: <T>(url: string): Promise<T> => {
    return fetch(`${API_CONFIG.baseUrl}${url}`).then(res => res.json())
  },

  post: <T>(url: string, data: any): Promise<T> => {
    return fetch(`${API_CONFIG.baseUrl}${url}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    }).then(res => res.json())
  }
}
```

### 数据获取Hook

```typescript
// src/hooks/useMachinery.ts
import { useState, useEffect } from 'react'
import { apiClient } from '@/config/api'

export function useMachinery() {
  const [machinery, setMachinery] = useState([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)

  useEffect(() => {
    apiClient.get('/machinery')
      .then(setMachinery)
      .catch(setError)
      .finally(() => setLoading(false))
  }, [])

  return { machinery, loading, error }
}
```

## 🧪 测试指南

### 单元测试示例

```typescript
// src/components/__tests__/Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react'
import { Button } from '../Button'

describe('Button', () => {
  it('renders correctly', () => {
    render(<Button>Click me</Button>)
    expect(screen.getByRole('button')).toBeInTheDocument()
  })

  it('calls onClick when clicked', () => {
    const handleClick = jest.fn()
    render(<Button onClick={handleClick}>Click me</Button>)

    fireEvent.click(screen.getByRole('button'))
    expect(handleClick).toHaveBeenCalledTimes(1)
  })
})
```

### Hook测试

```typescript
// src/hooks/__tests__/useCounter.test.ts
import { renderHook, act } from '@testing-library/react'
import { useCounter } from '../useCounter'

describe('useCounter', () => {
  it('initializes with default value', () => {
    const { result } = renderHook(() => useCounter())
    expect(result.current.count).toBe(0)
  })

  it('increments count', () => {
    const { result } = renderHook(() => useCounter())

    act(() => {
      result.current.increment()
    })

    expect(result.current.count).toBe(1)
  })
})
```

## 🐛 调试技巧

### React DevTools

安装 React Developer Tools 浏览器扩展：

```bash
# 检查组件状态
# 查看组件层次结构
# 性能分析
```

### VSCode调试配置

```json
// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug React",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/node_modules/.bin/vite",
      "args": ["--mode", "development"],
      "env": {
        "NODE_ENV": "development"
      }
    }
  ]
}
```

### 常用调试代码

```typescript
// 开发环境调试
if (import.meta.env.DEV) {
  console.log('Debug info:', data)
}

// 性能监控
console.time('component-render')
// ... 组件渲染逻辑
console.timeEnd('component-render')

// 网络请求调试
const debugFetch = async (url: string) => {
  console.log(`Fetching: ${url}`)
  const start = performance.now()

  try {
    const response = await fetch(url)
    const data = await response.json()
    console.log(`Fetched in ${performance.now() - start}ms`, data)
    return data
  } catch (error) {
    console.error(`Fetch failed after ${performance.now() - start}ms`, error)
    throw error
  }
}
```

## ❓ 常见问题

### Q: 如何添加新的UI组件？

A:
1. 在 `src/components/ui/` 下创建组件文件
2. 使用 shadcn/ui 设计规范
3. 添加 TypeScript 类型定义
4. 编写组件文档

### Q: 如何处理表单验证？

A: 推荐使用 react-hook-form + zod：

```typescript
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'

const schema = z.object({
  name: z.string().min(1, '名称不能为空'),
  email: z.string().email('邮箱格式不正确')
})

const { register, handleSubmit, formState: { errors } } = useForm({
  resolver: zodResolver(schema)
})
```

### Q: 如何优化性能？

A:
1. 使用 React.memo 避免不必要的重渲染
2. 使用 useMemo 和 useCallback 缓存计算结果
3. 实现虚拟列表处理大数据
4. 使用代码分割减少初始加载时间

### Q: 如何处理国际化？

A: 项目支持多语言配置：

```typescript
// src/config/i18n.ts
export const locales = {
  'zh-CN': '简体中文',
  'en-US': 'English'
}

export const translations = {
  'zh-CN': {
    'machinery.title': '农机管理',
    'machinery.status.running': '运行中'
  },
  'en-US': {
    'machinery.title': 'Machinery Management',
    'machinery.status.running': 'Running'
  }
}
```

### Q: 如何配置开发工具？

A: 使用项目提供的脚本：

```bash
# 查看状态
npm run scripts:setup

# 启用工具
npm run scripts:enable

# 禁用工具
npm run scripts:disable
```

## 📚 更多资源

- [React 官方文档](https://react.dev/)
- [TypeScript 手册](https://www.typescriptlang.org/docs/)
- [Tailwind CSS 文档](https://tailwindcss.com/docs)
- [shadcn/ui 组件库](https://ui.shadcn.com/)
- [Vite 构建工具](https://vitejs.dev/)

---

💡 **提示**: 如果遇到问题，请先查看常见问题部分，或联系项目维护者获取帮助。