子仓库提交
This commit is contained in:
27
.dev-tools-config.json
Normal file
27
.dev-tools-config.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"tools": {
|
||||||
|
"eslint": {
|
||||||
|
"enabled": false,
|
||||||
|
"description": "ESLint代码检查工具",
|
||||||
|
"configFile": ".eslintrc.cjs",
|
||||||
|
"ignoreFile": ".eslintignore"
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"enabled": false,
|
||||||
|
"description": "Prettier代码格式化工具",
|
||||||
|
"configFile": ".prettierrc",
|
||||||
|
"ignoreFile": ".prettierignore"
|
||||||
|
},
|
||||||
|
"husky": {
|
||||||
|
"enabled": false,
|
||||||
|
"description": "Git hooks工具",
|
||||||
|
"hooksDir": ".husky"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"setup": "node scripts/setup-dev-tools.js",
|
||||||
|
"enable": "node scripts/setup-dev-tools.js --enable",
|
||||||
|
"disable": "node scripts/setup-dev-tools.js --disable"
|
||||||
|
},
|
||||||
|
"note": "将enabled设置为true来启用对应的开发工具,或运行 npm run scripts:enable 来启用所有工具"
|
||||||
|
}
|
||||||
97
.dockerignore
Normal file
97
.dockerignore
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
.output
|
||||||
|
.nuxt
|
||||||
|
.next
|
||||||
|
.vite
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# Development files
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# IDE files
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS generated files
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.gitattributes
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
README.md
|
||||||
|
CHANGELOG.md
|
||||||
|
LICENSE.md
|
||||||
|
docs
|
||||||
|
|
||||||
|
# Config files that shouldn't be in container
|
||||||
|
.eslintrc*
|
||||||
|
.prettierrc*
|
||||||
|
prettier.config.js
|
||||||
|
.editorconfig
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
jest.config.js
|
||||||
|
cypress
|
||||||
|
test
|
||||||
|
tests
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.turbo
|
||||||
|
.vercel
|
||||||
|
.netlify
|
||||||
|
|
||||||
|
# TypeScript
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Package manager lock files (keep package-lock.json but ignore others)
|
||||||
|
yarn.lock
|
||||||
|
pnpm-lock.yaml
|
||||||
|
|
||||||
|
# Docker
|
||||||
|
Dockerfile
|
||||||
|
docker-compose*.yml
|
||||||
|
.dockerignore
|
||||||
35
.env.example
Normal file
35
.env.example
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# 环境配置示例文件
|
||||||
|
# 复制此文件为 .env.local 并根据实际情况修改配置
|
||||||
|
|
||||||
|
# 当前环境: development, test, production
|
||||||
|
NODE_ENV=development
|
||||||
|
|
||||||
|
# API 服务器地址 (用于 API 代码生成)
|
||||||
|
API_BASE_URL=http://localhost:8080
|
||||||
|
|
||||||
|
# React 应用配置 (用于前端运行时)
|
||||||
|
REACT_APP_API_URL=http://localhost:8080
|
||||||
|
|
||||||
|
# OpenAPI 文档地址
|
||||||
|
REACT_APP_OPENAPI_URL=http://localhost:8080/openapi.json
|
||||||
|
|
||||||
|
# 其他可选配置
|
||||||
|
# REACT_APP_API_KEY=your-api-key-here
|
||||||
|
# REACT_APP_DEBUG=true
|
||||||
|
|
||||||
|
# 不同环境配置示例:
|
||||||
|
#
|
||||||
|
# 开发环境:
|
||||||
|
# NODE_ENV=development
|
||||||
|
# API_BASE_URL=http://localhost:8080
|
||||||
|
# REACT_APP_API_URL=http://localhost:8080
|
||||||
|
#
|
||||||
|
# 测试环境:
|
||||||
|
# NODE_ENV=test
|
||||||
|
# API_BASE_URL=http://test-api.example.com
|
||||||
|
# REACT_APP_API_URL=http://test-api.example.com
|
||||||
|
#
|
||||||
|
# 生产环境:
|
||||||
|
# NODE_ENV=production
|
||||||
|
# API_BASE_URL=https://api.example.com
|
||||||
|
# REACT_APP_API_URL=https://api.example.com
|
||||||
47
.eslintrc.cjs
Normal file
47
.eslintrc.cjs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// ESLint配置文件 - 需要通过 .dev-tools-config.json 启用
|
||||||
|
// 运行 `npm run scripts:enable` 来启用ESLint
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// 检查开发工具配置
|
||||||
|
const configPath = path.join(__dirname, '.dev-tools-config.json');
|
||||||
|
let eslintEnabled = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||||
|
eslintEnabled = config.tools?.eslint?.enabled === true;
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('⚠️ 无法读取开发工具配置,ESLint将被禁用');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果ESLint被禁用,返回空配置
|
||||||
|
if (!eslintEnabled) {
|
||||||
|
console.log('ℹ️ ESLint已在配置中被禁用,如需启用请运行: npm run scripts:enable');
|
||||||
|
module.exports = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ESLint正常配置
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: { browser: true, es2020: true },
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'@typescript-eslint/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
],
|
||||||
|
ignorePatterns: ['dist', '.eslintrc.cjs', 'node_modules'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
plugins: ['react-refresh'],
|
||||||
|
rules: {
|
||||||
|
'react-refresh/only-export-components': [
|
||||||
|
'warn',
|
||||||
|
{ allowConstantExport: true },
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
||||||
|
'@typescript-eslint/no-explicit-any': 'warn',
|
||||||
|
'react-hooks/rules-of-hooks': 'error',
|
||||||
|
'react-hooks/exhaustive-deps': 'warn',
|
||||||
|
},
|
||||||
|
};
|
||||||
113
.gitignore
vendored
Normal file
113
.gitignore
vendored
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Production builds
|
||||||
|
.next/
|
||||||
|
out/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# API 相关文件
|
||||||
|
# 忽略从服务器下载的临时 OpenAPI JSON 文件
|
||||||
|
api/v1-from-server.json
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
.DS_Store?
|
||||||
|
._*
|
||||||
|
.Spotlight-V100
|
||||||
|
.Trashes
|
||||||
|
ehthumbs.db
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage/
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Storybook build outputs
|
||||||
|
.out
|
||||||
|
.storybook-out
|
||||||
|
|
||||||
|
# Temporary folders
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
# Local development
|
||||||
|
.local
|
||||||
|
|
||||||
|
# TypeScript
|
||||||
|
*.tsbuildinfo
|
||||||
18
.prettierignore
Normal file
18
.prettierignore
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
*.log
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
coverage
|
||||||
|
.nyc_output
|
||||||
|
.cache
|
||||||
|
.temp
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
pnpm-lock.yaml
|
||||||
12
.prettierrc
Normal file
12
.prettierrc
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 80,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"bracketSameLine": false,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"endOfLine": "lf"
|
||||||
|
}
|
||||||
277
CHANGELOG.md
Normal file
277
CHANGELOG.md
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
# 更新日志
|
||||||
|
|
||||||
|
所有重要的项目变更都会记录在此文件中。
|
||||||
|
|
||||||
|
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||||
|
项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
||||||
|
|
||||||
|
## [未发布]
|
||||||
|
|
||||||
|
### 计划中
|
||||||
|
- 完整的UI组件库集成
|
||||||
|
- 农业管理专用组件开发
|
||||||
|
- 视觉一致性验证系统
|
||||||
|
- 完整的测试覆盖
|
||||||
|
- 国际化支持
|
||||||
|
|
||||||
|
## [1.0.0] - 2024-01-20
|
||||||
|
|
||||||
|
### 🎉 首次发布
|
||||||
|
|
||||||
|
#### ✨ 新增功能
|
||||||
|
- **完整的项目基础架构**
|
||||||
|
- React 18 + Vite 6 + TypeScript 技术栈
|
||||||
|
- shadcn/ui + Tailwind CSS UI框架
|
||||||
|
- 完整的开发工具链(可选启用)
|
||||||
|
- 标准化的项目目录结构
|
||||||
|
|
||||||
|
- **React应用完整实现**
|
||||||
|
- main.tsx 应用入口文件
|
||||||
|
- App.tsx 主应用组件(包含完整管理系统界面)
|
||||||
|
- 欢迎页面和系统状态展示
|
||||||
|
- 技术栈展示和快速操作
|
||||||
|
- 主题切换功能
|
||||||
|
- 响应式布局设计
|
||||||
|
|
||||||
|
- **开发工具配置**
|
||||||
|
- ESLint + Prettier 代码质量工具
|
||||||
|
- 可选的开发工具开关控制
|
||||||
|
- VSCode 工作区配置
|
||||||
|
- 自动化代码格式化和检查
|
||||||
|
|
||||||
|
- **构建优化**
|
||||||
|
- Vite 6 构建配置优化
|
||||||
|
- 代码分割和懒加载
|
||||||
|
- 热重载优化(<2秒响应时间)
|
||||||
|
- 生产环境构建优化
|
||||||
|
|
||||||
|
- **样式系统**
|
||||||
|
- 农业主题色彩系统
|
||||||
|
- 响应式设计支持
|
||||||
|
- 深色/浅色主题切换
|
||||||
|
- 完整的设计令牌
|
||||||
|
|
||||||
|
- **类型系统**
|
||||||
|
- 完整的 TypeScript 类型定义
|
||||||
|
- 农业管理领域模型
|
||||||
|
- API 响应类型定义
|
||||||
|
- 组件 Props 类型规范
|
||||||
|
|
||||||
|
- **工具函数库**
|
||||||
|
- 日期时间处理工具
|
||||||
|
- 数据格式化函数
|
||||||
|
- 农机状态映射
|
||||||
|
- 通用工具函数
|
||||||
|
|
||||||
|
- **自定义 Hooks**
|
||||||
|
- useTheme 主题管理
|
||||||
|
- useLocalStorage 本地存储
|
||||||
|
- useDebounce 防抖处理
|
||||||
|
- 扩展中...
|
||||||
|
|
||||||
|
- **项目文档**
|
||||||
|
- 详细的 README.md
|
||||||
|
- 完整的开发指南
|
||||||
|
- 贡献指南和行为准则
|
||||||
|
- API 文档(规划中)
|
||||||
|
|
||||||
|
#### 🏗️ 架构改进
|
||||||
|
- 模块化的项目结构
|
||||||
|
- 组件驱动的开发模式
|
||||||
|
- 类型安全的开发体验
|
||||||
|
- 可扩展的架构设计
|
||||||
|
|
||||||
|
#### 📦 依赖管理
|
||||||
|
- **核心依赖**:
|
||||||
|
- React 18.3.1
|
||||||
|
- Vite 6.3.5
|
||||||
|
- TypeScript 5.6.2
|
||||||
|
- Tailwind CSS 3.4.13
|
||||||
|
|
||||||
|
- **UI组件库**:
|
||||||
|
- 完整的 Radix UI 组件集合
|
||||||
|
- shadcn/ui 组件库基础
|
||||||
|
- Lucide React 图标库
|
||||||
|
|
||||||
|
- **开发工具**:
|
||||||
|
- ESLint 9.11.1
|
||||||
|
- Prettier 3.3.3
|
||||||
|
- Husky 9.1.6(可选)
|
||||||
|
|
||||||
|
#### 🎨 设计系统
|
||||||
|
- 农业绿色主题 (#16a34a)
|
||||||
|
- 一致的视觉语言
|
||||||
|
- 响应式断点系统
|
||||||
|
- 无障碍设计支持
|
||||||
|
|
||||||
|
#### 📚 文档完善
|
||||||
|
- **README.md**: 项目介绍和快速开始
|
||||||
|
- **DEVELOPMENT.md**: 详细的开发指南
|
||||||
|
- **CONTRIBUTING.md**: 贡献流程和规范
|
||||||
|
- **CHANGELOG.md**: 变更记录
|
||||||
|
|
||||||
|
#### 🔧 开发体验
|
||||||
|
- 热重载开发服务器
|
||||||
|
- TypeScript 严格模式
|
||||||
|
- 自动代码格式化
|
||||||
|
- 智能代码补全
|
||||||
|
|
||||||
|
### 🎯 功能模块规划
|
||||||
|
|
||||||
|
#### 🚜 农机管理 (Machinery)
|
||||||
|
- [x] 模块结构搭建
|
||||||
|
- [x] 基础组件框架
|
||||||
|
- [ ] 农机档案管理
|
||||||
|
- [ ] 驾驶员管理
|
||||||
|
- [ ] 负载管理
|
||||||
|
- [ ] 运行监控
|
||||||
|
- [ ] 故障管理
|
||||||
|
- [ ] 作业管理
|
||||||
|
- [ ] 数据分析
|
||||||
|
- [ ] 调度管理
|
||||||
|
- [ ] 安全管理
|
||||||
|
|
||||||
|
#### 🌾 地块管理 (Field)
|
||||||
|
- [x] 模块结构搭建
|
||||||
|
- [ ] 地块档案
|
||||||
|
- [ ] 土壤信息管理
|
||||||
|
- [ ] 作物管理
|
||||||
|
- [ ] 种植计划
|
||||||
|
|
||||||
|
#### 📋 农事管理 (Operation)
|
||||||
|
- [x] 模块结构搭建
|
||||||
|
- [ ] 作业计划
|
||||||
|
- [ ] 进度跟踪
|
||||||
|
- [ ] 成本核算
|
||||||
|
- [ ] 产量预测
|
||||||
|
|
||||||
|
#### 💰 资产管理 (Asset)
|
||||||
|
- [x] 模块结构搭建
|
||||||
|
- [ ] 设备资产管理
|
||||||
|
- [ ] 库存管理
|
||||||
|
- [ ] 采购管理
|
||||||
|
- [ ] 维护记录
|
||||||
|
|
||||||
|
#### 🤖 AI模型 (AI Model)
|
||||||
|
- [x] 模块结构搭建
|
||||||
|
- [ ] 智能预测
|
||||||
|
- [ ] 图像识别
|
||||||
|
- [ ] 数据分析
|
||||||
|
- [ ] 决策支持
|
||||||
|
|
||||||
|
#### 💧 灌溉控制 (Irrigation)
|
||||||
|
- [x] 模块结构搭建
|
||||||
|
- [ ] 智能灌溉
|
||||||
|
- [ ] 水资源管理
|
||||||
|
- [ ] 设备控制
|
||||||
|
- [ ] 用水统计
|
||||||
|
|
||||||
|
#### ⚙️ 配置管理 (Config)
|
||||||
|
- [x] 模块结构搭建
|
||||||
|
- [ ] 系统配置
|
||||||
|
- [ ] 用户管理
|
||||||
|
- [ ] 权限设置
|
||||||
|
- [ ] 数据字典
|
||||||
|
|
||||||
|
### 🚀 性能指标
|
||||||
|
|
||||||
|
- **构建时间**: < 30秒
|
||||||
|
- **热重载**: < 2秒
|
||||||
|
- **首屏加载**: < 3秒(目标)
|
||||||
|
- **代码分割**: 按模块自动分割
|
||||||
|
- **包大小**: 优化中...
|
||||||
|
|
||||||
|
### 🔒 安全性
|
||||||
|
- TypeScript 类型安全
|
||||||
|
- 输入验证框架
|
||||||
|
- XSS 防护
|
||||||
|
- CSRF 保护(规划中)
|
||||||
|
|
||||||
|
### 🌍 国际化
|
||||||
|
- 中文界面支持
|
||||||
|
- 英文界面(规划中)
|
||||||
|
- 多语言切换(规划中)
|
||||||
|
|
||||||
|
### 📱 兼容性
|
||||||
|
- **现代浏览器**: Chrome 90+, Firefox 88+, Safari 14+, Edge 90+
|
||||||
|
- **移动端**: iOS Safari 14+, Chrome Mobile 90+
|
||||||
|
- **响应式**: 完整的移动端适配
|
||||||
|
|
||||||
|
### 🧪 测试覆盖
|
||||||
|
- **单元测试**: 规划中
|
||||||
|
- **集成测试**: 规划中
|
||||||
|
- **E2E测试**: 规划中
|
||||||
|
- **视觉回归测试**: 规划中
|
||||||
|
|
||||||
|
## 📈 版本规划
|
||||||
|
|
||||||
|
### [1.1.0] - 计划中
|
||||||
|
- 完整的UI组件库实现
|
||||||
|
- 农机管理核心功能
|
||||||
|
- 基础数据可视化
|
||||||
|
- 用户认证系统
|
||||||
|
|
||||||
|
### [1.2.0] - 计划中
|
||||||
|
- 地块管理功能
|
||||||
|
- 农事管理功能
|
||||||
|
- 移动端适配优化
|
||||||
|
- API 集成
|
||||||
|
|
||||||
|
### [1.3.0] - 计划中
|
||||||
|
- 资产管理功能
|
||||||
|
- AI 模型集成
|
||||||
|
- 高级数据分析
|
||||||
|
- 报表系统
|
||||||
|
|
||||||
|
### [2.0.0] - 计划中
|
||||||
|
- 完整的功能覆盖
|
||||||
|
- 微服务架构
|
||||||
|
- 实时数据同步
|
||||||
|
- 第三方系统集成
|
||||||
|
|
||||||
|
## 🏷️ 标签说明
|
||||||
|
|
||||||
|
- `✨ 新增功能`: 新的功能特性
|
||||||
|
- `🔧 改进`: 现有功能的改进
|
||||||
|
- `🐛 修复`: Bug修复
|
||||||
|
- `📚 文档`: 文档相关变更
|
||||||
|
- `🎨 样式`: UI/UX 相关变更
|
||||||
|
- `⚡ 性能`: 性能优化
|
||||||
|
- `🔒 安全`: 安全相关修复
|
||||||
|
- `💥 破坏性变更`: 不兼容的API变更
|
||||||
|
- `🗑️ 废弃`: 功能的废弃
|
||||||
|
|
||||||
|
## 🤝 贡献者
|
||||||
|
|
||||||
|
感谢所有为项目做出贡献的开发者!
|
||||||
|
|
||||||
|
- **主要贡献者**: [@your-username](https://github.com/your-username)
|
||||||
|
- **项目维护**: [@maintainer](https://github.com/maintainer)
|
||||||
|
|
||||||
|
### 贡献统计
|
||||||
|
|
||||||
|
- 代码提交: XX 次
|
||||||
|
- 功能添加: XX 个
|
||||||
|
- Bug修复: XX 个
|
||||||
|
- 文档更新: XX 次
|
||||||
|
|
||||||
|
## 📞 反馈和支持
|
||||||
|
|
||||||
|
如果您有任何问题或建议,请通过以下方式联系我们:
|
||||||
|
|
||||||
|
- **GitHub Issues**: [项目Issues页面](https://github.com/your-username/agriculture-management/issues)
|
||||||
|
- **GitHub Discussions**: [讨论区](https://github.com/your-username/agriculture-management/discussions)
|
||||||
|
- **邮箱**: support@example.com
|
||||||
|
|
||||||
|
## 🔗 相关链接
|
||||||
|
|
||||||
|
- [项目主页](https://github.com/your-username/agriculture-management)
|
||||||
|
- [在线演示](https://demo.example.com)
|
||||||
|
- [API 文档](https://docs.example.com/api)
|
||||||
|
- [设计规范](https://design.example.com)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**注意**: 本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/) 规范。
|
||||||
|
|
||||||
|
📅 **最后更新**: 2024-01-20
|
||||||
382
CONTRIBUTING.md
Normal file
382
CONTRIBUTING.md
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
# 贡献指南
|
||||||
|
|
||||||
|
感谢您对智慧农业生产管理系统项目的关注!我们欢迎所有形式的贡献,包括但不限于代码贡献、问题反馈、文档改进和功能建议。
|
||||||
|
|
||||||
|
## 📋 目录
|
||||||
|
|
||||||
|
- [行为准则](#行为准则)
|
||||||
|
- [如何贡献](#如何贡献)
|
||||||
|
- [开发流程](#开发流程)
|
||||||
|
- [代码规范](#代码规范)
|
||||||
|
- [提交规范](#提交规范)
|
||||||
|
- [问题报告](#问题报告)
|
||||||
|
- [功能请求](#功能请求)
|
||||||
|
- [代码审查](#代码审查)
|
||||||
|
- [发布流程](#发布流程)
|
||||||
|
|
||||||
|
## 🤝 行为准则
|
||||||
|
|
||||||
|
### 我们的承诺
|
||||||
|
|
||||||
|
为了营造一个开放和友好的环境,我们作为贡献者和维护者承诺让每个人都能参与我们的项目和社区。
|
||||||
|
|
||||||
|
### 我们的标准
|
||||||
|
|
||||||
|
积极行为包括:
|
||||||
|
|
||||||
|
- 使用友好和包容的语言
|
||||||
|
- 尊重不同的观点和经验
|
||||||
|
- 优雅地接受建设性批评
|
||||||
|
- 关注对社区最有利的事情
|
||||||
|
- 对其他社区成员表示同理心
|
||||||
|
|
||||||
|
不可接受的行为包括:
|
||||||
|
|
||||||
|
- 使用性化的语言或图像
|
||||||
|
- 人身攻击或政治攻击
|
||||||
|
- 公开或私下骚扰
|
||||||
|
- 未经明确许可发布他人的私人信息
|
||||||
|
- 其他在专业环境中可能被认为不当的行为
|
||||||
|
|
||||||
|
## 🚀 如何贡献
|
||||||
|
|
||||||
|
### 1. 准备工作
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Fork 项目到您的GitHub账户
|
||||||
|
# 克隆您的fork
|
||||||
|
git clone https://github.com/your-username/agriculture-management.git
|
||||||
|
|
||||||
|
# 添加上游仓库
|
||||||
|
git remote add upstream https://github.com/original-owner/agriculture-management.git
|
||||||
|
|
||||||
|
# 安装依赖
|
||||||
|
cd agriculture-management
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 启动开发环境
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 选择贡献方式
|
||||||
|
|
||||||
|
- 🐛 **报告Bug**: 发现问题并创建详细的问题报告
|
||||||
|
- 💡 **功能建议**: 提出新功能或改进建议
|
||||||
|
- 📝 **文档改进**: 完善项目文档
|
||||||
|
- 💻 **代码贡献**: 修复bug或实现新功能
|
||||||
|
|
||||||
|
## 🔄 开发流程
|
||||||
|
|
||||||
|
### 1. 创建分支
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 确保master分支是最新的
|
||||||
|
git checkout master
|
||||||
|
git pull upstream master
|
||||||
|
|
||||||
|
# 创建功能分支
|
||||||
|
git checkout -b feature/your-feature-name
|
||||||
|
# 或
|
||||||
|
git checkout -b fix/your-bug-fix
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 开发过程
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 启用开发工具(可选)
|
||||||
|
npm run scripts:enable
|
||||||
|
|
||||||
|
# 进行开发
|
||||||
|
# ...
|
||||||
|
|
||||||
|
# 运行测试
|
||||||
|
npm run test
|
||||||
|
|
||||||
|
# 代码检查
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# 类型检查
|
||||||
|
npm run type-check
|
||||||
|
|
||||||
|
# 格式化代码
|
||||||
|
npm run format
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 提交更改
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 添加更改
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# 提交(遵循提交规范)
|
||||||
|
git commit -m "feat(component): add new machinery status component"
|
||||||
|
|
||||||
|
# 推送到您的fork
|
||||||
|
git push origin feature/your-feature-name
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 创建Pull Request
|
||||||
|
|
||||||
|
1. 访问GitHub上的fork页面
|
||||||
|
2. 点击"New Pull Request"
|
||||||
|
3. 选择正确的分支
|
||||||
|
4. 填写PR模板
|
||||||
|
5. 提交Pull Request
|
||||||
|
|
||||||
|
## 📏 代码规范
|
||||||
|
|
||||||
|
### TypeScript规范
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ 好的示例
|
||||||
|
interface MachineryData {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
status: MachineryStatus
|
||||||
|
lastMaintenance?: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMachineryStatus = async (id: string): Promise<MachineryData> => {
|
||||||
|
const response = await fetch(`/api/machinery/${id}`)
|
||||||
|
return response.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ❌ 避免的写法
|
||||||
|
const getData = (id) => {
|
||||||
|
return fetch('/api/machinery/' + id).then(r => r.json())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### React组件规范
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ 函数式组件 + TypeScript
|
||||||
|
interface MachineryCardProps {
|
||||||
|
machinery: MachineryData
|
||||||
|
onEdit?: (machinery: MachineryData) => void
|
||||||
|
className?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MachineryCard: React.FC<MachineryCardProps> = ({
|
||||||
|
machinery,
|
||||||
|
onEdit,
|
||||||
|
className
|
||||||
|
}) => {
|
||||||
|
const handleEdit = useCallback(() => {
|
||||||
|
onEdit?.(machinery)
|
||||||
|
}, [machinery, onEdit])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cn('machinery-card', className)}>
|
||||||
|
{/* 组件内容 */}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 样式规范
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ 使用Tailwind CSS + cn工具
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
|
const Button = ({ variant = 'primary', className, ...props }) => (
|
||||||
|
<button
|
||||||
|
className={cn(
|
||||||
|
'px-4 py-2 rounded-md font-medium transition-colors',
|
||||||
|
{
|
||||||
|
'bg-blue-600 text-white': variant === 'primary',
|
||||||
|
'bg-gray-200 text-gray-900': variant === 'secondary'
|
||||||
|
},
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 提交规范
|
||||||
|
|
||||||
|
### 提交格式
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(<scope>): <subject>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 提交类型
|
||||||
|
|
||||||
|
- `feat`: 新功能
|
||||||
|
- `fix`: Bug修复
|
||||||
|
- `docs`: 文档更新
|
||||||
|
- `style`: 代码格式化(不影响功能)
|
||||||
|
- `refactor`: 代码重构
|
||||||
|
- `perf`: 性能优化
|
||||||
|
- `test`: 添加或修改测试
|
||||||
|
- `chore`: 构建过程或辅助工具的变动
|
||||||
|
|
||||||
|
### 示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 新功能
|
||||||
|
git commit -m "feat(machinery): add real-time monitoring dashboard"
|
||||||
|
|
||||||
|
# Bug修复
|
||||||
|
git commit -m "fix(auth): resolve login validation error for special characters"
|
||||||
|
|
||||||
|
# 文档更新
|
||||||
|
git commit -m "docs(readme): update installation instructions for Windows"
|
||||||
|
|
||||||
|
# 性能优化
|
||||||
|
git commit -m "perf(machinery): optimize data loading with virtual scrolling"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐛 问题报告
|
||||||
|
|
||||||
|
### 报告Bug
|
||||||
|
|
||||||
|
使用以下模板创建Bug报告:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Bug描述
|
||||||
|
简洁明了地描述Bug
|
||||||
|
|
||||||
|
## 复现步骤
|
||||||
|
1. 进入 '...'
|
||||||
|
2. 点击 '....'
|
||||||
|
3. 滚动到 '....'
|
||||||
|
4. 看到错误
|
||||||
|
|
||||||
|
## 期望行为
|
||||||
|
描述您期望发生的行为
|
||||||
|
|
||||||
|
## 实际行为
|
||||||
|
描述实际发生的行为
|
||||||
|
|
||||||
|
## 截图
|
||||||
|
如果适用,添加截图来帮助解释问题
|
||||||
|
|
||||||
|
## 环境信息
|
||||||
|
- 操作系统: [例如 iOS]
|
||||||
|
- 浏览器: [例如 chrome, safari]
|
||||||
|
- 版本: [例如 22]
|
||||||
|
|
||||||
|
## 附加信息
|
||||||
|
添加任何其他关于问题的信息
|
||||||
|
```
|
||||||
|
|
||||||
|
### 安全漏洞
|
||||||
|
|
||||||
|
如果您发现安全漏洞,请不要公开报告。请发送邮件至:security@example.com
|
||||||
|
|
||||||
|
## 💡 功能请求
|
||||||
|
|
||||||
|
### 请求新功能
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 功能描述
|
||||||
|
简洁明了地描述您想要的功能
|
||||||
|
|
||||||
|
## 问题背景
|
||||||
|
描述这个功能要解决的问题
|
||||||
|
|
||||||
|
## 解决方案
|
||||||
|
描述您希望的解决方案
|
||||||
|
|
||||||
|
## 替代方案
|
||||||
|
描述您考虑过的其他解决方案
|
||||||
|
|
||||||
|
## 附加信息
|
||||||
|
添加任何其他关于功能请求的信息
|
||||||
|
```
|
||||||
|
|
||||||
|
## 👀 代码审查
|
||||||
|
|
||||||
|
### 审查者指南
|
||||||
|
|
||||||
|
当审查代码时,请关注:
|
||||||
|
|
||||||
|
1. **功能正确性**: 代码是否按预期工作
|
||||||
|
2. **代码质量**: 是否遵循项目规范
|
||||||
|
3. **性能影响**: 是否有性能问题
|
||||||
|
4. **安全性**: 是否存在安全隐患
|
||||||
|
5. **测试覆盖**: 是否有足够的测试
|
||||||
|
6. **文档**: 是否需要更新文档
|
||||||
|
|
||||||
|
### 审查评论规范
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# ✅ 好的评论
|
||||||
|
"建议将这个函数提取为自定义Hook,以提高复用性"
|
||||||
|
"这个变量名不够清晰,建议改为更具描述性的名称"
|
||||||
|
"考虑添加错误处理逻辑"
|
||||||
|
|
||||||
|
# ❌ 避免的评论
|
||||||
|
"这段代码不好"(过于模糊)
|
||||||
|
"重写这个"(没有具体建议)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 被审查者指南
|
||||||
|
|
||||||
|
- 对建设性反馈持开放态度
|
||||||
|
- 解释您的技术决策
|
||||||
|
- 感谢审查者的时间
|
||||||
|
- 及时响应评论
|
||||||
|
|
||||||
|
## 🏷️ 发布流程
|
||||||
|
|
||||||
|
### 版本号规范
|
||||||
|
|
||||||
|
遵循 [语义化版本](https://semver.org/lang/zh-CN/):
|
||||||
|
|
||||||
|
- `MAJOR.MINOR.PATCH`
|
||||||
|
- `MAJOR`: 不兼容的API修改
|
||||||
|
- `MINOR`: 向下兼容的功能性新增
|
||||||
|
- `PATCH`: 向下兼容的问题修正
|
||||||
|
|
||||||
|
### 发布检查清单
|
||||||
|
|
||||||
|
发布前确认:
|
||||||
|
|
||||||
|
- [ ] 所有测试通过
|
||||||
|
- [ ] 代码审查完成
|
||||||
|
- [ ] 文档已更新
|
||||||
|
- [ ] CHANGELOG已更新
|
||||||
|
- [ ] 版本号已更新
|
||||||
|
- [ ] 性能测试通过
|
||||||
|
|
||||||
|
## 🏆 贡献者认可
|
||||||
|
|
||||||
|
### 贡献者类型
|
||||||
|
|
||||||
|
- 💻 **代码贡献**: 提交代码
|
||||||
|
- 🐛 **Bug报告**: 发现并报告问题
|
||||||
|
- 💡 **功能建议**: 提出新功能想法
|
||||||
|
- 📝 **文档改进**: 完善项目文档
|
||||||
|
- 🎨 **设计贡献**: UI/UX设计改进
|
||||||
|
- 🌐 **翻译贡献**: 多语言支持
|
||||||
|
|
||||||
|
### 认可方式
|
||||||
|
|
||||||
|
- 在README中添加贡献者列表
|
||||||
|
- 在发布说明中感谢贡献者
|
||||||
|
- 颁发贡献者徽章
|
||||||
|
- 邀请加入核心团队
|
||||||
|
|
||||||
|
## 📞 联系方式
|
||||||
|
|
||||||
|
- **项目维护者**: maintainer@example.com
|
||||||
|
- **技术讨论**: GitHub Discussions
|
||||||
|
- **Bug报告**: GitHub Issues
|
||||||
|
- **安全问题**: security@example.com
|
||||||
|
|
||||||
|
## 📄 许可证
|
||||||
|
|
||||||
|
通过贡献代码,您同意您的贡献将在与项目相同的 [MIT License](LICENSE) 下获得许可。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
感谢您的贡献!🎉
|
||||||
644
DEVELOPMENT.md
Normal file
644
DEVELOPMENT.md
Normal file
@@ -0,0 +1,644 @@
|
|||||||
|
# 开发指南
|
||||||
|
|
||||||
|
本文档为智慧农业生产管理系统的开发指南,帮助开发者快速了解项目结构、开发规范和最佳实践。
|
||||||
|
|
||||||
|
## 📋 目录
|
||||||
|
|
||||||
|
- [环境准备](#环境准备)
|
||||||
|
- [项目结构](#项目结构)
|
||||||
|
- [开发规范](#开发规范)
|
||||||
|
- [组件开发](#组件开发)
|
||||||
|
- [状态管理](#状态管理)
|
||||||
|
- [样式指南](#样式指南)
|
||||||
|
- [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/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
💡 **提示**: 如果遇到问题,请先查看常见问题部分,或联系项目维护者获取帮助。
|
||||||
47
Dockerfile
Normal file
47
Dockerfile
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
FROM registry.dev.maimaiag.com/library/node:20-alpine AS base
|
||||||
|
RUN npm config set registry https://registry.npmmirror.com/
|
||||||
|
|
||||||
|
# Install dependencies only when needed
|
||||||
|
FROM base AS deps
|
||||||
|
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||||
|
RUN apk add --no-cache libc6-compat
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install dependencies based on the preferred package manager
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN npm ci --registry=https://registry.npmmirror.com/
|
||||||
|
|
||||||
|
|
||||||
|
# Rebuild the source code only when needed
|
||||||
|
FROM base AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production image, copy all the files and run next
|
||||||
|
FROM base AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
RUN addgroup --system --gid 1001 nodejs
|
||||||
|
RUN adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
|
||||||
|
# Automatically leverage output traces to reduce image size
|
||||||
|
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENV PORT=3000
|
||||||
|
|
||||||
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
322
README.md
Normal file
322
README.md
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
# 智慧农业生产管理系统
|
||||||
|
|
||||||
|
基于 React 18 + Vite 6 + TypeScript + shadcn/ui 构建的现代化农业管理平台。
|
||||||
|
|
||||||
|
## 🌟 项目特色
|
||||||
|
|
||||||
|
- 🚀 **现代化技术栈**: React 18 + Vite 6 + TypeScript
|
||||||
|
- 🎨 **优美UI设计**: 基于 shadcn/ui + Tailwind CSS
|
||||||
|
- 📱 **响应式布局**: 支持桌面端和移动端
|
||||||
|
- 🌾 **农业专业化**: 针对农业生产场景定制
|
||||||
|
- 🔧 **开发工具**: ESLint + Prettier + Husky(可选启用)
|
||||||
|
- 📊 **数据可视化**: 集成 Recharts 图表库
|
||||||
|
|
||||||
|
## 🏗️ 技术架构
|
||||||
|
|
||||||
|
### 核心技术栈
|
||||||
|
|
||||||
|
- **前端框架**: React 18.3.1
|
||||||
|
- **构建工具**: Vite 6.3.5
|
||||||
|
- **类型系统**: TypeScript 5.6.2
|
||||||
|
- **UI组件库**: shadcn/ui + Radix UI
|
||||||
|
- **样式方案**: Tailwind CSS 3.4.13
|
||||||
|
- **状态管理**: React Context + Hooks
|
||||||
|
- **路由系统**: 自定义基于路径的路由
|
||||||
|
- **图表库**: Recharts 2.15.2
|
||||||
|
- **图标库**: Lucide React 0.487.0
|
||||||
|
- **日期处理**: date-fns 4.1.0
|
||||||
|
|
||||||
|
### 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
crop-x/
|
||||||
|
├── 📄 public/ # 静态资源
|
||||||
|
├── 📄 src/
|
||||||
|
│ ├── 📄 components/ # 组件目录
|
||||||
|
│ │ ├── ui/ # shadcn/ui基础组件
|
||||||
|
│ │ ├── common/ # 通用业务组件
|
||||||
|
│ │ └── layouts/ # 布局组件
|
||||||
|
│ ├── 📄 pages/ # 页面组件
|
||||||
|
│ │ ├── machinery/ # 农机管理
|
||||||
|
│ │ ├── field/ # 地块管理
|
||||||
|
│ │ ├── operation/ # 农事管理
|
||||||
|
│ │ ├── asset/ # 资产管理
|
||||||
|
│ │ ├── ai-model/ # AI模型
|
||||||
|
│ │ ├── irrigation/ # 灌溉控制
|
||||||
|
│ │ └── config/ # 配置管理
|
||||||
|
│ ├── 📄 hooks/ # 自定义Hooks
|
||||||
|
│ ├── 📄 lib/ # 工具库
|
||||||
|
│ ├── 📄 config/ # 配置文件
|
||||||
|
│ ├── 📄 types/ # 类型定义
|
||||||
|
│ ├── 📄 utils/ # 工具函数
|
||||||
|
│ ├── 📄 assets/ # 资源文件
|
||||||
|
│ ├── 📄 styles/ # 样式文件
|
||||||
|
│ └── 📄 App.tsx # 主应用组件
|
||||||
|
├── 📄 docs/ # 文档目录
|
||||||
|
├── 📄 scripts/ # 构建脚本
|
||||||
|
└── 📄 .vscode/ # VSCode配置
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### 环境要求
|
||||||
|
|
||||||
|
- Node.js >= 18.0.0
|
||||||
|
- npm >= 8.0.0
|
||||||
|
|
||||||
|
### 安装依赖
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 开发环境
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
项目将在 http://localhost:3000 启动(如果端口被占用会自动切换)
|
||||||
|
|
||||||
|
**✅ React应用验证**:
|
||||||
|
- 启动时间: < 2秒(实测2012ms)
|
||||||
|
- 热重载: 正常工作
|
||||||
|
- 主题切换: 支持深色/浅色模式
|
||||||
|
- 响应式设计: 支持桌面端和移动端
|
||||||
|
|
||||||
|
### 构建生产版本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 预览生产版本
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ 开发工具
|
||||||
|
|
||||||
|
项目配置了可选的开发工具链,默认禁用,可通过以下命令启用:
|
||||||
|
|
||||||
|
### 查看开发工具状态
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run scripts:setup
|
||||||
|
```
|
||||||
|
|
||||||
|
### 启用所有开发工具
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run scripts:enable
|
||||||
|
```
|
||||||
|
|
||||||
|
### 禁用所有开发工具
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run scripts:disable
|
||||||
|
```
|
||||||
|
|
||||||
|
### 代码检查
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ESLint检查
|
||||||
|
npm run lint
|
||||||
|
|
||||||
|
# ESLint自动修复
|
||||||
|
npm run lint:fix
|
||||||
|
```
|
||||||
|
|
||||||
|
### 代码格式化
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Prettier格式化
|
||||||
|
npm run format
|
||||||
|
|
||||||
|
# 检查格式
|
||||||
|
npm run format:check
|
||||||
|
```
|
||||||
|
|
||||||
|
### 类型检查
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run type-check
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 功能模块
|
||||||
|
|
||||||
|
### 🚜 农机管理 (Machinery)
|
||||||
|
- 农机档案管理
|
||||||
|
- 驾驶员管理
|
||||||
|
- 负载管理
|
||||||
|
- 运行监控
|
||||||
|
- 故障管理
|
||||||
|
- 作业管理
|
||||||
|
- 数据分析
|
||||||
|
- 调度管理
|
||||||
|
- 安全管理
|
||||||
|
|
||||||
|
### 🌾 地块管理 (Field)
|
||||||
|
- 地块档案
|
||||||
|
- 土壤信息
|
||||||
|
- 作物管理
|
||||||
|
- 种植计划
|
||||||
|
|
||||||
|
### 📋 农事管理 (Operation)
|
||||||
|
- 作业计划
|
||||||
|
- 进度跟踪
|
||||||
|
- 成本核算
|
||||||
|
- 产量预测
|
||||||
|
|
||||||
|
### 💰 资产管理 (Asset)
|
||||||
|
- 设备资产
|
||||||
|
- 库存管理
|
||||||
|
- 采购管理
|
||||||
|
- 维护记录
|
||||||
|
|
||||||
|
### 🤖 AI模型 (AI Model)
|
||||||
|
- 智能预测
|
||||||
|
- 图像识别
|
||||||
|
- 数据分析
|
||||||
|
- 决策支持
|
||||||
|
|
||||||
|
### 💧 灌溉控制 (Irrigation)
|
||||||
|
- 智能灌溉
|
||||||
|
- 水资源管理
|
||||||
|
- 设备控制
|
||||||
|
- 用水统计
|
||||||
|
|
||||||
|
### ⚙️ 配置管理 (Config)
|
||||||
|
- 系统配置
|
||||||
|
- 用户管理
|
||||||
|
- 权限设置
|
||||||
|
- 数据字典
|
||||||
|
|
||||||
|
## 🎨 设计系统
|
||||||
|
|
||||||
|
### 颜色系统
|
||||||
|
|
||||||
|
- **主色调**: 农业绿色 (#16a34a)
|
||||||
|
- **辅助色**: 技术蓝色 (#3b82f6)
|
||||||
|
- **状态色**: 运行(绿)、空闲(灰)、维护(黄)、故障(红)、离线(深灰)
|
||||||
|
|
||||||
|
### 组件规范
|
||||||
|
|
||||||
|
- 基于 shadcn/ui 组件库
|
||||||
|
- 遵循 Material Design 设计规范
|
||||||
|
- 支持深色/浅色主题切换
|
||||||
|
- 完整的无障碍支持
|
||||||
|
|
||||||
|
## 🔧 配置说明
|
||||||
|
|
||||||
|
### 环境变量
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# API地址
|
||||||
|
VITE_API_BASE_URL=http://localhost:8080/api
|
||||||
|
|
||||||
|
# 应用标题
|
||||||
|
VITE_APP_TITLE=智慧农业生产管理系统
|
||||||
|
|
||||||
|
# 开发模式
|
||||||
|
VITE_DEV_MODE=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### 开发工具配置
|
||||||
|
|
||||||
|
通过 `.dev-tools-config.json` 文件控制开发工具的启用状态:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tools": {
|
||||||
|
"eslint": { "enabled": false },
|
||||||
|
"prettier": { "enabled": false },
|
||||||
|
"husky": { "enabled": false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📖 开发指南
|
||||||
|
|
||||||
|
### 添加新页面
|
||||||
|
|
||||||
|
1. 在对应模块下创建页面组件
|
||||||
|
2. 在路由配置中添加路由规则
|
||||||
|
3. 在菜单配置中添加菜单项
|
||||||
|
|
||||||
|
### 添加新组件
|
||||||
|
|
||||||
|
1. 在 `src/components/ui/` 下创建UI组件
|
||||||
|
2. 遵循 shadcn/ui 设计规范
|
||||||
|
3. 添加 TypeScript 类型定义
|
||||||
|
4. 编写组件文档和使用示例
|
||||||
|
|
||||||
|
### 样式规范
|
||||||
|
|
||||||
|
- 使用 Tailwind CSS 类名
|
||||||
|
- 遵循 BEM 命名规范
|
||||||
|
- 响应式设计优先
|
||||||
|
- 支持深色模式
|
||||||
|
|
||||||
|
## 🧪 测试
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 运行测试
|
||||||
|
npm run test
|
||||||
|
|
||||||
|
# 运行测试覆盖率
|
||||||
|
npm run test:coverage
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📤 部署
|
||||||
|
|
||||||
|
### Docker部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建镜像
|
||||||
|
docker build -t agriculture-management .
|
||||||
|
|
||||||
|
# 运行容器
|
||||||
|
docker run -p 3000:3000 agriculture-management
|
||||||
|
```
|
||||||
|
|
||||||
|
### 传统部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建项目
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# 部署build目录到Web服务器
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 更新日志
|
||||||
|
|
||||||
|
### v1.0.0 (2024-01-20)
|
||||||
|
- ✨ 初始版本发布
|
||||||
|
- 🚀 完成基础架构搭建
|
||||||
|
- 🎨 集成shadcn/ui组件库
|
||||||
|
- 📱 实现响应式设计
|
||||||
|
- 🌾 添加农业专业化功能
|
||||||
|
|
||||||
|
## 🤝 贡献指南
|
||||||
|
|
||||||
|
1. Fork 项目
|
||||||
|
2. 创建功能分支 (`git checkout -b feature/AmazingFeature`)
|
||||||
|
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
|
||||||
|
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
||||||
|
5. 创建 Pull Request
|
||||||
|
|
||||||
|
## 📄 许可证
|
||||||
|
|
||||||
|
本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情
|
||||||
|
|
||||||
|
## 📞 联系我们
|
||||||
|
|
||||||
|
- 项目地址: [GitHub Repository](https://github.com/your-username/agriculture-management)
|
||||||
|
- 问题反馈: [Issues](https://github.com/your-username/agriculture-management/issues)
|
||||||
|
- 邮箱: your-email@example.com
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
⭐ 如果这个项目对你有帮助,请给我们一个星标!
|
||||||
22
components.json
Normal file
22
components.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "default",
|
||||||
|
"rsc": false,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "tailwind.config.js",
|
||||||
|
"css": "src/styles/globals.css",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"iconLibrary": "lucide",
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
},
|
||||||
|
"registries": {}
|
||||||
|
}
|
||||||
1477
docs/开发项目规范.md
Normal file
1477
docs/开发项目规范.md
Normal file
File diff suppressed because it is too large
Load Diff
26
env/.env.dev
vendored
Normal file
26
env/.env.dev
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# 开发环境配置
|
||||||
|
NODE_ENV=development
|
||||||
|
|
||||||
|
# 前端域名
|
||||||
|
FRONTEND_BASE_URL=https://cavin-smart-crop-ui-app.dev.maimaiag.com
|
||||||
|
|
||||||
|
# 后端 API 地址
|
||||||
|
BACKEND_BASE_URL=https://gitea-admin-hm-smart-agri-app.dev.maimaiag.com/
|
||||||
|
|
||||||
|
# OpenAPI 生成配置
|
||||||
|
API_BASE_URL=https://gitea-admin-hm-smart-agri-app.dev.maimaiag.com
|
||||||
|
|
||||||
|
# API 版本
|
||||||
|
API_VERSION=v1
|
||||||
|
|
||||||
|
# 调试模式
|
||||||
|
DEBUG=true
|
||||||
|
|
||||||
|
# 是否开启 Mock 数据
|
||||||
|
USE_MOCK=false
|
||||||
|
|
||||||
|
# 应用名称
|
||||||
|
APP_NAME=智慧农业生产管理系统
|
||||||
|
|
||||||
|
# 环境描述
|
||||||
|
ENV_DESCRIPTION=开发环境
|
||||||
43
env/.env.prod
vendored
Normal file
43
env/.env.prod
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# 生产环境配置
|
||||||
|
NODE_ENV=production
|
||||||
|
|
||||||
|
# 前端域名
|
||||||
|
FRONTEND_BASE_URL=https://cavin-smart-crop-ui-app.prod.maimaiag.com
|
||||||
|
|
||||||
|
# 后端 API 地址
|
||||||
|
BACKEND_BASE_URL=https://cavin-smart-crop-backend-app.prod.maimaiag.com
|
||||||
|
|
||||||
|
# API 版本
|
||||||
|
API_VERSION=v1
|
||||||
|
|
||||||
|
# 调试模式
|
||||||
|
DEBUG=false
|
||||||
|
|
||||||
|
# 是否开启 Mock 数据
|
||||||
|
USE_MOCK=false
|
||||||
|
|
||||||
|
# 应用名称
|
||||||
|
APP_NAME=智慧农业生产管理系统
|
||||||
|
|
||||||
|
# 环境描述
|
||||||
|
ENV_DESCRIPTION=生产环境
|
||||||
|
|
||||||
|
# 生产环境特有配置
|
||||||
|
API_TIMEOUT=30000
|
||||||
|
ENABLE_ERROR_LOGGING=true
|
||||||
|
ENABLE_PERFORMANCE_MONITORING=true
|
||||||
|
ENABLE_USER_BEHAVIOR_TRACKING=true
|
||||||
|
ENABLE_ANALYTICS=true
|
||||||
|
|
||||||
|
# 安全配置
|
||||||
|
SENTRY_DSN=https://your-sentry-dsn.prod@sentry.io/project-id
|
||||||
|
CDN_BASE_URL=https://cdn.cavin-smart-crop.com
|
||||||
|
|
||||||
|
# 功能开关
|
||||||
|
ENABLE_MAINTENANCE_MODE=false
|
||||||
|
ENABLE_NEW_FEATURES=true
|
||||||
|
ENABLE_BETA_FEATURES=false
|
||||||
|
|
||||||
|
# 缓存配置
|
||||||
|
CACHE_TTL=3600
|
||||||
|
ENABLE_SERVICE_WORKER=true
|
||||||
28
env/.env.test
vendored
Normal file
28
env/.env.test
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# 测试环境配置
|
||||||
|
NODE_ENV=test
|
||||||
|
|
||||||
|
# 前端域名
|
||||||
|
FRONTEND_BASE_URL=https://cavin-smart-crop-ui-app.test.maimaiag.com
|
||||||
|
|
||||||
|
# 后端 API 地址
|
||||||
|
BACKEND_BASE_URL=http://pengcode.tech:8080
|
||||||
|
|
||||||
|
# API 版本
|
||||||
|
API_VERSION=v1
|
||||||
|
|
||||||
|
# 调试模式
|
||||||
|
DEBUG=true
|
||||||
|
|
||||||
|
# 是否开启 Mock 数据
|
||||||
|
USE_MOCK=false
|
||||||
|
|
||||||
|
# 应用名称
|
||||||
|
APP_NAME=智慧农业生产管理系统
|
||||||
|
|
||||||
|
# 环境描述
|
||||||
|
ENV_DESCRIPTION=测试环境
|
||||||
|
|
||||||
|
# 其他测试环境特有配置
|
||||||
|
API_TIMEOUT=15000
|
||||||
|
ENABLE_ERROR_LOGGING=true
|
||||||
|
ENABLE_PERFORMANCE_MONITORING=true
|
||||||
30
env/.env.uat
vendored
Normal file
30
env/.env.uat
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# UAT (用户验收测试) 环境配置
|
||||||
|
NODE_ENV=production
|
||||||
|
|
||||||
|
# 前端域名
|
||||||
|
FRONTEND_BASE_URL=https://cavin-smart-crop-ui-app.uat.maimaiag.com
|
||||||
|
|
||||||
|
# 后端 API 地址
|
||||||
|
BACKEND_BASE_URL=https://cavin-smart-crop-backend-app.uat.maimaiag.com
|
||||||
|
|
||||||
|
# API 版本
|
||||||
|
API_VERSION=v1
|
||||||
|
|
||||||
|
# 调试模式
|
||||||
|
DEBUG=false
|
||||||
|
|
||||||
|
# 是否开启 Mock 数据
|
||||||
|
USE_MOCK=false
|
||||||
|
|
||||||
|
# 应用名称
|
||||||
|
APP_NAME=智慧农业生产管理系统
|
||||||
|
|
||||||
|
# 环境描述
|
||||||
|
ENV_DESCRIPTION=UAT 环境
|
||||||
|
|
||||||
|
# UAT 特有配置
|
||||||
|
API_TIMEOUT=20000
|
||||||
|
ENABLE_ERROR_LOGGING=true
|
||||||
|
ENABLE_PERFORMANCE_MONITORING=true
|
||||||
|
ENABLE_USER_BEHAVIOR_TRACKING=true
|
||||||
|
SENTRY_DSN=https://your-sentry-dsn.uat@sentry.io/project-id
|
||||||
25
eslint.config.mjs
Normal file
25
eslint.config.mjs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { dirname } from "path";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
import { FlatCompat } from "@eslint/eslintrc";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
});
|
||||||
|
|
||||||
|
const eslintConfig = [
|
||||||
|
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
"node_modules/**",
|
||||||
|
".next/**",
|
||||||
|
"out/**",
|
||||||
|
"build/**",
|
||||||
|
"next-env.d.ts",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default eslintConfig;
|
||||||
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>智慧农业生产管理系统</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
6
next-env.d.ts
vendored
Normal file
6
next-env.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
import "./.next/dev/types/routes.d.ts";
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
37
next.config.js
Normal file
37
next.config.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
typescript: {
|
||||||
|
ignoreBuildErrors: true, // TODO: 暂时完全禁用TypeScript类型检查
|
||||||
|
},
|
||||||
|
eslint: {
|
||||||
|
ignoreDuringBuilds: true, // TODO: 暂时禁用eslint校验错误
|
||||||
|
},
|
||||||
|
transpilePackages: ['lucide-react'],
|
||||||
|
output: 'standalone',
|
||||||
|
// 修复CSS构建问题
|
||||||
|
experimental: {
|
||||||
|
// forceSwcTransforms: true,
|
||||||
|
},
|
||||||
|
// 新的 Turbopack 配置
|
||||||
|
turbopack: {
|
||||||
|
rules: {
|
||||||
|
'*.svg': {
|
||||||
|
loaders: ['@svgr/webpack'],
|
||||||
|
as: '*.js',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 解决工作区根目录问题
|
||||||
|
outputFileTracingRoot: process.cwd(),
|
||||||
|
// 添加代理配置解决CORS问题
|
||||||
|
async rewrites() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
source: '/api/:path*',
|
||||||
|
destination: 'https://gitea-admin-hm-smart-agri-app.dev.maimaiag.com/api/:path*',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
17
openapi-ts.config.ts
Normal file
17
openapi-ts.config.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { defineConfig } from "@hey-api/openapi-ts";
|
||||||
|
|
||||||
|
// 获取环境变量配置
|
||||||
|
const baseUrl = process.env.API_BASE_URL || 'http://localhost:8080';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
client: "@hey-api/client-fetch",
|
||||||
|
input: `${baseUrl}/openapi.json`,
|
||||||
|
output: "./src/lib/api",
|
||||||
|
schemas: {
|
||||||
|
name: "types.gen.ts",
|
||||||
|
},
|
||||||
|
services: {
|
||||||
|
name: "sdk.gen.ts",
|
||||||
|
},
|
||||||
|
clientName: "client.gen.ts",
|
||||||
|
});
|
||||||
14478
package-lock.json
generated
Normal file
14478
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
102
package.json
Normal file
102
package.json
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
{
|
||||||
|
"name": "智慧农业生产管理系统",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev --turbopack",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
|
"lint:fix": "eslint . --ext ts,tsx --fix",
|
||||||
|
"type-check": "tsc --noEmit",
|
||||||
|
"api:generate": "node scripts/generate-api.cjs",
|
||||||
|
"deploy": "node scripts/deploy.js",
|
||||||
|
"build:dev": "node scripts/build.cjs dev",
|
||||||
|
"build:test": "node scripts/build.cjs test",
|
||||||
|
"build:uat": "node scripts/build.cjs uat",
|
||||||
|
"build:prod": "node scripts/build.cjs prod"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@hookform/resolvers": "^5.2.2",
|
||||||
|
"@radix-ui/react-accordion": "^1.2.12",
|
||||||
|
"@radix-ui/react-alert-dialog": "^1.1.15",
|
||||||
|
"@radix-ui/react-aspect-ratio": "^1.1.7",
|
||||||
|
"@radix-ui/react-avatar": "^1.1.10",
|
||||||
|
"@radix-ui/react-checkbox": "^1.3.3",
|
||||||
|
"@radix-ui/react-collapsible": "^1.1.12",
|
||||||
|
"@radix-ui/react-context-menu": "^2.2.16",
|
||||||
|
"@radix-ui/react-dialog": "^1.1.15",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||||
|
"@radix-ui/react-hover-card": "^1.1.15",
|
||||||
|
"@radix-ui/react-label": "^2.1.7",
|
||||||
|
"@radix-ui/react-menubar": "^1.1.16",
|
||||||
|
"@radix-ui/react-navigation-menu": "^1.2.14",
|
||||||
|
"@radix-ui/react-popover": "^1.1.15",
|
||||||
|
"@radix-ui/react-progress": "^1.1.7",
|
||||||
|
"@radix-ui/react-radio-group": "^1.3.8",
|
||||||
|
"@radix-ui/react-scroll-area": "^1.2.10",
|
||||||
|
"@radix-ui/react-select": "^2.2.6",
|
||||||
|
"@radix-ui/react-separator": "^1.1.7",
|
||||||
|
"@radix-ui/react-slider": "^1.3.6",
|
||||||
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
|
"@radix-ui/react-toggle": "^1.1.10",
|
||||||
|
"@radix-ui/react-toggle-group": "^1.1.11",
|
||||||
|
"@radix-ui/react-tooltip": "^1.2.8",
|
||||||
|
"@tailwindcss/postcss": "^4.1.14",
|
||||||
|
"axios": "^1.12.2",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"cmdk": "^1.1.1",
|
||||||
|
"date-fns": "^4.1.0",
|
||||||
|
"embla-carousel-react": "^8.6.0",
|
||||||
|
"input-otp": "^1.4.2",
|
||||||
|
"lucide-react": "^0.487.0",
|
||||||
|
"next": "^16.0.1",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
|
"openapi-fetch": "^0.15.0",
|
||||||
|
"qrcode": "*",
|
||||||
|
"react": "^19.2.0",
|
||||||
|
"react-day-picker": "^9.11.1",
|
||||||
|
"react-dom": "^19.2.0",
|
||||||
|
"react-hook-form": "^7.65.0",
|
||||||
|
"react-resizable-panels": "^2.1.9",
|
||||||
|
"recharts": "^2.15.4",
|
||||||
|
"sonner": "^2.0.7",
|
||||||
|
"tailwind-merge": "^3.3.1",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
"vaul": "^1.1.2",
|
||||||
|
"zod": "^4.1.12",
|
||||||
|
"zustand": "^5.0.8"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@hey-api/client-fetch": "^0.13.1",
|
||||||
|
"@hey-api/openapi-ts": "^0.86.6",
|
||||||
|
"@tailwindcss/postcss": "^4",
|
||||||
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
|
"@types/node": "^20.10.0",
|
||||||
|
"@types/react": "^18.3.11",
|
||||||
|
"@types/react-dom": "^18.3.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.7.0",
|
||||||
|
"@typescript-eslint/parser": "^8.7.0",
|
||||||
|
"@vitejs/plugin-react-swc": "^3.10.2",
|
||||||
|
"autoprefixer": "^10.4.20",
|
||||||
|
"eslint": "^9.11.1",
|
||||||
|
"eslint-config-next": "15.5.6",
|
||||||
|
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.12",
|
||||||
|
"husky": "^9.1.6",
|
||||||
|
"install": "^0.13.0",
|
||||||
|
"lint-staged": "^15.2.10",
|
||||||
|
"node-fetch": "^3.3.2",
|
||||||
|
"npm": "^11.6.2",
|
||||||
|
"openapi-typescript": "^7.10.1",
|
||||||
|
"postcss": "^8.4.47",
|
||||||
|
"prettier": "^3.3.3",
|
||||||
|
"tailwindcss": "^4.1.14",
|
||||||
|
"typescript": "^5.9.3",
|
||||||
|
"vite": "^6.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
'@tailwindcss/postcss': {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
387
scripts/build.cjs
Normal file
387
scripts/build.cjs
Normal file
@@ -0,0 +1,387 @@
|
|||||||
|
/**
|
||||||
|
* 统一构建脚本
|
||||||
|
*
|
||||||
|
* 整合环境设置、API生成和Next.js构建的完整构建流程
|
||||||
|
* 支持多环境构建:dev, test, uat, prod
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const { execSync, spawn } = require('child_process');
|
||||||
|
|
||||||
|
// ANSI 颜色代码
|
||||||
|
const colors = {
|
||||||
|
reset: '\x1b[0m',
|
||||||
|
red: '\x1b[31m',
|
||||||
|
green: '\x1b[32m',
|
||||||
|
yellow: '\x1b[33m',
|
||||||
|
blue: '\x1b[34m',
|
||||||
|
cyan: '\x1b[36m',
|
||||||
|
white: '\x1b[37m'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 日志函数
|
||||||
|
function log(message, color = 'white') {
|
||||||
|
console.log(`${colors[color]}${message}${colors.reset}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function logSuccess(message) {
|
||||||
|
log(`✓ ${message}`, 'green');
|
||||||
|
}
|
||||||
|
|
||||||
|
function logError(message) {
|
||||||
|
log(`✗ ${message}`, 'red');
|
||||||
|
}
|
||||||
|
|
||||||
|
function logInfo(message) {
|
||||||
|
log(`ℹ ${message}`, 'blue');
|
||||||
|
}
|
||||||
|
|
||||||
|
function logStep(message) {
|
||||||
|
log(`🔄 ${message}`, 'cyan');
|
||||||
|
}
|
||||||
|
|
||||||
|
function logWarning(message) {
|
||||||
|
log(`⚠ ${message}`, 'yellow');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取命令行参数中的环境
|
||||||
|
*/
|
||||||
|
function getEnvironmentFromArgs() {
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
|
||||||
|
// 查找 --env 参数
|
||||||
|
const envArg = args.find(arg => arg.startsWith('--env='));
|
||||||
|
if (envArg) {
|
||||||
|
return envArg.split('=')[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找直接的参数
|
||||||
|
const directEnv = args[0];
|
||||||
|
if (['dev', 'test', 'uat', 'prod'].includes(directEnv)) {
|
||||||
|
return directEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证环境名称
|
||||||
|
*/
|
||||||
|
function validateEnvironment(env) {
|
||||||
|
const validEnvs = ['dev', 'test', 'uat', 'prod'];
|
||||||
|
if (!validEnvs.includes(env)) {
|
||||||
|
logError(`无效的环境名称: ${env}`);
|
||||||
|
logInfo(`支持的环境: ${validEnvs.join(', ')}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制环境配置文件
|
||||||
|
*/
|
||||||
|
function copyEnvironmentConfig(env) {
|
||||||
|
logStep(`设置 ${env} 环境配置`);
|
||||||
|
|
||||||
|
const envDir = path.join(process.cwd(), 'env');
|
||||||
|
const sourceFile = path.join(envDir, `.env.${env}`);
|
||||||
|
const targetFile = path.join(process.cwd(), '.env.local');
|
||||||
|
|
||||||
|
// 检查源文件是否存在
|
||||||
|
if (!fs.existsSync(sourceFile)) {
|
||||||
|
logError(`环境配置文件不存在: ${sourceFile}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 复制文件
|
||||||
|
fs.copyFileSync(sourceFile, targetFile);
|
||||||
|
logSuccess(`已复制环境配置: ${env}`);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
logError(`复制环境配置文件失败: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理缓存目录
|
||||||
|
*/
|
||||||
|
function cleanCache() {
|
||||||
|
logStep('清理缓存目录');
|
||||||
|
|
||||||
|
const dirsToClean = ['.next', 'node_modules/.cache'];
|
||||||
|
|
||||||
|
dirsToClean.forEach(dir => {
|
||||||
|
const dirPath = path.join(process.cwd(), dir);
|
||||||
|
if (fs.existsSync(dirPath)) {
|
||||||
|
try {
|
||||||
|
fs.rmSync(dirPath, { recursive: true, force: true });
|
||||||
|
logSuccess(`已清理: ${dir}`);
|
||||||
|
} catch (error) {
|
||||||
|
logWarning(`清理 ${dir} 失败: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成API客户端代码
|
||||||
|
*/
|
||||||
|
function generateApi(env) {
|
||||||
|
logStep('生成API客户端代码');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 设置环境变量
|
||||||
|
const apiBaseUrl = getApiBaseUrl(env);
|
||||||
|
process.env.API_BASE_URL = apiBaseUrl;
|
||||||
|
|
||||||
|
logInfo(`API服务器: ${apiBaseUrl}`);
|
||||||
|
|
||||||
|
// 执行API生成脚本
|
||||||
|
execSync('node scripts/generate-api.cjs', {
|
||||||
|
stdio: 'inherit',
|
||||||
|
cwd: process.cwd()
|
||||||
|
});
|
||||||
|
|
||||||
|
logSuccess('API客户端代码生成完成');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
logError(`API生成失败: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从环境配置文件中读取配置
|
||||||
|
*/
|
||||||
|
function getEnvConfigFromFile(env) {
|
||||||
|
try {
|
||||||
|
// 读取对应环境配置文件
|
||||||
|
const envFilePath = path.join(process.cwd(), 'env', `.env.${env}`);
|
||||||
|
|
||||||
|
if (!fs.existsSync(envFilePath)) {
|
||||||
|
logWarning(`环境配置文件不存在: ${envFilePath}`);
|
||||||
|
return {
|
||||||
|
FRONTEND_BASE_URL: 'http://localhost:3000',
|
||||||
|
BACKEND_BASE_URL: 'http://localhost:8080',
|
||||||
|
ENV_DESCRIPTION: `${env}环境`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const envContent = fs.readFileSync(envFilePath, 'utf8');
|
||||||
|
const lines = envContent.split('\n');
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
FRONTEND_BASE_URL: 'http://localhost:3000',
|
||||||
|
BACKEND_BASE_URL: 'http://localhost:8080',
|
||||||
|
ENV_DESCRIPTION: `${env}环境`
|
||||||
|
};
|
||||||
|
|
||||||
|
// 解析配置文件
|
||||||
|
for (const line of lines) {
|
||||||
|
if (line.startsWith('FRONTEND_BASE_URL=')) {
|
||||||
|
config.FRONTEND_BASE_URL = line.split('=')[1].trim();
|
||||||
|
} else if (line.startsWith('BACKEND_BASE_URL=')) {
|
||||||
|
config.BACKEND_BASE_URL = line.split('=')[1].trim();
|
||||||
|
logInfo(`从 ${envFilePath} 读取到后端地址: ${config.BACKEND_BASE_URL}`);
|
||||||
|
} else if (line.startsWith('ENV_DESCRIPTION=')) {
|
||||||
|
config.ENV_DESCRIPTION = line.split('=')[1].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
} catch (error) {
|
||||||
|
logError(`读取环境配置失败: ${error.message}`);
|
||||||
|
return {
|
||||||
|
FRONTEND_BASE_URL: 'http://localhost:3000',
|
||||||
|
BACKEND_BASE_URL: 'http://localhost:8080',
|
||||||
|
ENV_DESCRIPTION: `${env}环境`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取API基础URL - 从环境配置文件中读取
|
||||||
|
*/
|
||||||
|
function getApiBaseUrl(env) {
|
||||||
|
const config = getEnvConfigFromFile(env);
|
||||||
|
return config.BACKEND_BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取前端基础URL - 从环境配置文件中读取
|
||||||
|
*/
|
||||||
|
function getFrontendUrl(env) {
|
||||||
|
const config = getEnvConfigFromFile(env);
|
||||||
|
return config.FRONTEND_BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Next.js 构建
|
||||||
|
*/
|
||||||
|
function buildNext(env) {
|
||||||
|
logStep('执行 Next.js 构建');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 设置环境变量
|
||||||
|
process.env.NODE_ENV = 'production'; // 所有构建都使用 production 模式
|
||||||
|
process.env.NEXT_PUBLIC_ENV = env;
|
||||||
|
|
||||||
|
// 执行构建
|
||||||
|
execSync('npm run build', {
|
||||||
|
stdio: 'inherit',
|
||||||
|
cwd: process.cwd()
|
||||||
|
});
|
||||||
|
|
||||||
|
logSuccess('Next.js 构建完成');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
logError(`Next.js 构建失败: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示构建信息
|
||||||
|
*/
|
||||||
|
function showBuildInfo(env, totalTime) {
|
||||||
|
const envConfig = getEnvConfigFromFile(env);
|
||||||
|
|
||||||
|
log('='.repeat(60), 'green');
|
||||||
|
logSuccess(`构建完成!总耗时: ${totalTime}ms`);
|
||||||
|
logSuccess(`环境: ${envConfig.ENV_DESCRIPTION} (${env})`);
|
||||||
|
logSuccess(`前端地址: ${envConfig.FRONTEND_BASE_URL}`);
|
||||||
|
logSuccess(`后端地址: ${envConfig.BACKEND_BASE_URL}`);
|
||||||
|
logSuccess('构建产物: .next 目录');
|
||||||
|
log('='.repeat(60), 'green');
|
||||||
|
|
||||||
|
logInfo('部署建议:');
|
||||||
|
logInfo(` 将 .next 目录和 package.json 部署到 ${envConfig.ENV_DESCRIPTION}`);
|
||||||
|
if (env !== 'dev') {
|
||||||
|
logInfo(` 确保环境变量 NODE_ENV=production 和 NEXT_PUBLIC_ENV=${env}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示帮助信息
|
||||||
|
*/
|
||||||
|
function showHelp() {
|
||||||
|
log('用法: node scripts/build.cjs [环境] [选项]', 'cyan');
|
||||||
|
log('');
|
||||||
|
log('环境:', 'yellow');
|
||||||
|
log(' dev 开发环境', 'white');
|
||||||
|
log(' test 测试环境', 'white');
|
||||||
|
log(' uat UAT 环境', 'white');
|
||||||
|
log(' prod 生产环境', 'white');
|
||||||
|
log('');
|
||||||
|
log('选项:', 'yellow');
|
||||||
|
log(' --env=<environment> 指定环境 (与直接指定环境等效)', 'white');
|
||||||
|
log(' --clean 构建前清理缓存', 'white');
|
||||||
|
log(' --skip-api 跳过API生成', 'white');
|
||||||
|
log(' --skip-build 跳过Next.js构建(仅设置环境)', 'white');
|
||||||
|
log(' --help 显示此帮助信息', 'white');
|
||||||
|
log('');
|
||||||
|
log('示例:', 'yellow');
|
||||||
|
log(' node scripts/build.cjs dev # 开发环境完整构建', 'white');
|
||||||
|
log(' node scripts/build.cjs test --clean # 测试环境清理缓存后构建', 'white');
|
||||||
|
log(' node scripts/build.cjs prod --skip-api # 生产环境跳过API生成构建', 'white');
|
||||||
|
log(' node scripts/build.cjs uat --skip-build # UAT环境仅设置环境和API生成', 'white');
|
||||||
|
log('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主函数
|
||||||
|
*/
|
||||||
|
function main() {
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
log('='.repeat(60), 'cyan');
|
||||||
|
log('统一构建脚本', 'cyan');
|
||||||
|
log('整合环境设置、API生成和Next.js构建', 'cyan');
|
||||||
|
log('='.repeat(60), 'cyan');
|
||||||
|
|
||||||
|
// 检查帮助参数
|
||||||
|
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
||||||
|
showHelp();
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取环境参数
|
||||||
|
let env = getEnvironmentFromArgs();
|
||||||
|
if (!env) {
|
||||||
|
logError('请指定环境参数');
|
||||||
|
logInfo('使用 --help 查看帮助信息');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证环境
|
||||||
|
if (!validateEnvironment(env)) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析选项
|
||||||
|
const shouldClean = process.argv.includes('--clean');
|
||||||
|
const skipApi = process.argv.includes('--skip-api');
|
||||||
|
const skipBuild = process.argv.includes('--skip-build');
|
||||||
|
|
||||||
|
logInfo(`目标环境: ${env}`);
|
||||||
|
logInfo(`工作目录: ${process.cwd()}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 设置环境配置
|
||||||
|
const envSuccess = copyEnvironmentConfig(env);
|
||||||
|
if (!envSuccess) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 清理缓存(可选)
|
||||||
|
if (shouldClean) {
|
||||||
|
cleanCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 生成API客户端(可选)
|
||||||
|
if (!skipApi) {
|
||||||
|
const apiSuccess = generateApi(env);
|
||||||
|
if (!apiSuccess) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logInfo('跳过API生成');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Next.js 构建(可选)
|
||||||
|
if (!skipBuild) {
|
||||||
|
const buildSuccess = buildNext(env);
|
||||||
|
if (!buildSuccess) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logInfo('跳过Next.js构建');
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalTime = Date.now() - startTime;
|
||||||
|
showBuildInfo(env, totalTime);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
const totalTime = Date.now() - startTime;
|
||||||
|
logError(`构建失败 (${totalTime}ms): ${error.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行主函数
|
||||||
|
if (require.main === module) {
|
||||||
|
main();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
copyEnvironmentConfig,
|
||||||
|
generateApi,
|
||||||
|
buildNext,
|
||||||
|
validateEnvironment,
|
||||||
|
getEnvironmentFromArgs
|
||||||
|
};
|
||||||
44
scripts/deploy.js
Normal file
44
scripts/deploy.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
var data = JSON.stringify({
|
||||||
|
"namespace": "argo",
|
||||||
|
"template_name": "repo-runtime-workflow",
|
||||||
|
"parameters": {
|
||||||
|
"git-schema": "http",
|
||||||
|
"git-domain": "gitea-service-http.cropflow-dev.svc.cluster.local:3000",
|
||||||
|
"git-user": "cavin",
|
||||||
|
"git-repo": "smart-crop-ui",
|
||||||
|
"git-revision": "main",
|
||||||
|
"git-pat": "b6c02bf1aec73d7bbbfbe590ea37564a29c4bd5d",
|
||||||
|
"docker-image-domain": "172.16.102.3:30648",
|
||||||
|
"docker-dockerfile-path": "./Dockerfile.crop-x",
|
||||||
|
"resource-cpu-limit": "500m",
|
||||||
|
"resource-memory-limit": "512Mi",
|
||||||
|
"resource-gpu-mem-limit": "",
|
||||||
|
"resource-mount-path": "/data",
|
||||||
|
"resource-mount-capacity": "",
|
||||||
|
"app-namespace": "argo",
|
||||||
|
"app-env-vars": "",
|
||||||
|
"app-ingress-host": ".dev.maimaiag.com",
|
||||||
|
"app-container-port": "3000",
|
||||||
|
"security-scan-enabled": "false"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
method: 'post',
|
||||||
|
url: 'https://gitea-admin-argo-workflow-api-app.dev.maimaiag.com/api/v1/workflows/from-template',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
data : data
|
||||||
|
};
|
||||||
|
|
||||||
|
axios(config)
|
||||||
|
.then(function (response) {
|
||||||
|
|
||||||
|
let url = `https://gitea-admin-argo-workflow-api-app.dev.maimaiag.com/api/v1/workflows/${response.data.name}/log`
|
||||||
|
console.log(`打开 ${url} 查看日志`);
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
388
scripts/generate-api.cjs
Normal file
388
scripts/generate-api.cjs
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
/**
|
||||||
|
* 简化的 API 生成脚本
|
||||||
|
*
|
||||||
|
* 这个脚本现在主要负责:
|
||||||
|
* 1. 使用 @hey-api/openapi-ts 命令生成客户端代码
|
||||||
|
* 2. 环境配置通过 openapi-ts.config.ts 处理
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
// 从环境配置文件中读取 API_BASE_URL
|
||||||
|
function getApiBaseUrl() {
|
||||||
|
try {
|
||||||
|
// 首先尝试从 env/.env.dev 文件读取
|
||||||
|
const envDevPath = path.join(process.cwd(), 'env', '.env.dev');
|
||||||
|
if (fs.existsSync(envDevPath)) {
|
||||||
|
const envContent = fs.readFileSync(envDevPath, 'utf8');
|
||||||
|
const apiBaseUrlMatch = envContent.match(/API_BASE_URL=([^\r\n]+)/);
|
||||||
|
|
||||||
|
if (apiBaseUrlMatch && apiBaseUrlMatch[1]) {
|
||||||
|
return apiBaseUrlMatch[1].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果上面的文件不存在,尝试从 TypeScript 环境配置文件读取
|
||||||
|
const envConfigPath = path.join(process.cwd(), 'src', 'env', 'index.ts');
|
||||||
|
if (fs.existsSync(envConfigPath)) {
|
||||||
|
const envContent = fs.readFileSync(envConfigPath, 'utf8');
|
||||||
|
const devConfigMatch = envContent.match(/dev:\s*\{[\s\S]*?BACKEND_BASE_URL:\s*['"`]([^'"`]+)['"`]/);
|
||||||
|
|
||||||
|
if (devConfigMatch && devConfigMatch[1]) {
|
||||||
|
return devConfigMatch[1].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('无法找到 API_BASE_URL 或 BACKEND_BASE_URL 配置');
|
||||||
|
} catch (error) {
|
||||||
|
console.log(`读取环境配置失败: ${error.message}`);
|
||||||
|
return 'http://localhost:8080'; // 默认值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 API 基础 URL
|
||||||
|
const API_BASE_URL = getApiBaseUrl();
|
||||||
|
|
||||||
|
// 设置环境变量供后续使用
|
||||||
|
process.env.API_BASE_URL = API_BASE_URL;
|
||||||
|
|
||||||
|
// ANSI 颜色代码
|
||||||
|
const colors = {
|
||||||
|
reset: '\x1b[0m',
|
||||||
|
red: '\x1b[31m',
|
||||||
|
green: '\x1b[32m',
|
||||||
|
yellow: '\x1b[33m',
|
||||||
|
blue: '\x1b[34m',
|
||||||
|
magenta: '\x1b[35m',
|
||||||
|
cyan: '\x1b[36m',
|
||||||
|
white: '\x1b[37m'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 日志函数
|
||||||
|
function log(message, color = 'white') {
|
||||||
|
console.log(`${colors[color]}${message}${colors.reset}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function logSuccess(message) {
|
||||||
|
log(`✓ ${message}`, 'green');
|
||||||
|
}
|
||||||
|
|
||||||
|
function logError(message) {
|
||||||
|
log(`✗ ${message}`, 'red');
|
||||||
|
}
|
||||||
|
|
||||||
|
function logWarning(message) {
|
||||||
|
log(`⚠ ${message}`, 'yellow');
|
||||||
|
}
|
||||||
|
|
||||||
|
function logInfo(message) {
|
||||||
|
log(`ℹ ${message}`, 'blue');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示环境配置信息
|
||||||
|
logInfo(`当前环境: ${process.env.NODE_ENV || 'development'}`);
|
||||||
|
logInfo(`API 服务器: ${API_BASE_URL}`);
|
||||||
|
logInfo(`已从 env/.env.dev 读取 API_BASE_URL 配置`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查自定义文件是否存在
|
||||||
|
* 如果某些文件已经被自定义,我们不希望覆盖它们
|
||||||
|
*/
|
||||||
|
function checkCustomFiles() {
|
||||||
|
const customFiles = [
|
||||||
|
'client.gen.ts' // 客户端文件通常是自定义的
|
||||||
|
];
|
||||||
|
|
||||||
|
const outputDir = path.join(process.cwd(), 'src', 'lib', 'api');
|
||||||
|
const existingCustomFiles = [];
|
||||||
|
|
||||||
|
for (const file of customFiles) {
|
||||||
|
const filePath = path.join(outputDir, file);
|
||||||
|
if (fs.existsSync(filePath)) {
|
||||||
|
// 检查文件是否包含自定义内容的标识
|
||||||
|
const content = fs.readFileSync(filePath, 'utf8');
|
||||||
|
|
||||||
|
// 检查是否有自定义配置的标识
|
||||||
|
const customIndicators = [
|
||||||
|
'getBaseUrl',
|
||||||
|
'createDynamicClient',
|
||||||
|
'getCurrentClientConfig',
|
||||||
|
// 可以添加更多自定义标识
|
||||||
|
];
|
||||||
|
|
||||||
|
const hasCustomContent = customIndicators.some(indicator =>
|
||||||
|
content.includes(indicator)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasCustomContent) {
|
||||||
|
existingCustomFiles.push(file);
|
||||||
|
logWarning(`检测到自定义文件: ${file}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return existingCustomFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备份自定义文件
|
||||||
|
*/
|
||||||
|
function backupCustomFiles(customFiles) {
|
||||||
|
if (customFiles.length === 0) return;
|
||||||
|
|
||||||
|
logInfo('备份自定义文件...');
|
||||||
|
const outputDir = path.join(process.cwd(), 'src', 'lib', 'api');
|
||||||
|
const backupDir = path.join(process.cwd(), 'src', 'lib', 'api', 'backup');
|
||||||
|
|
||||||
|
// 创建备份目录
|
||||||
|
if (!fs.existsSync(backupDir)) {
|
||||||
|
fs.mkdirSync(backupDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||||
|
const timestampedBackupDir = path.join(backupDir, `backup-${timestamp}`);
|
||||||
|
fs.mkdirSync(timestampedBackupDir);
|
||||||
|
|
||||||
|
for (const file of customFiles) {
|
||||||
|
const srcPath = path.join(outputDir, file);
|
||||||
|
const destPath = path.join(timestampedBackupDir, file);
|
||||||
|
fs.copyFileSync(srcPath, destPath);
|
||||||
|
logInfo(` 备份: ${file} -> backup/${timestamp}/${file}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
logSuccess(`自定义文件已备份到: backup/${timestamp}/`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复自定义文件
|
||||||
|
*/
|
||||||
|
function restoreCustomFiles(customFiles) {
|
||||||
|
if (customFiles.length === 0) return;
|
||||||
|
|
||||||
|
logInfo('恢复自定义文件...');
|
||||||
|
const outputDir = path.join(process.cwd(), 'src', 'lib', 'api');
|
||||||
|
const backupDir = path.join(process.cwd(), 'src', 'lib', 'api', 'backup');
|
||||||
|
|
||||||
|
// 找到最新的备份目录
|
||||||
|
const backupDirs = fs.existsSync(backupDir)
|
||||||
|
? fs.readdirSync(backupDir)
|
||||||
|
.filter(name => name.startsWith('backup-'))
|
||||||
|
.sort()
|
||||||
|
.reverse()
|
||||||
|
: [];
|
||||||
|
|
||||||
|
if (backupDirs.length === 0) {
|
||||||
|
logWarning('没有找到备份文件,跳过恢复');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const latestBackupDir = path.join(backupDir, backupDirs[0]);
|
||||||
|
|
||||||
|
for (const file of customFiles) {
|
||||||
|
const srcPath = path.join(latestBackupDir, file);
|
||||||
|
const destPath = path.join(outputDir, file);
|
||||||
|
|
||||||
|
if (fs.existsSync(srcPath)) {
|
||||||
|
fs.copyFileSync(srcPath, destPath);
|
||||||
|
logInfo(` 恢复: ${file}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logSuccess('自定义文件已恢复');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载并保存 openapi.json 文件到本地
|
||||||
|
*/
|
||||||
|
function downloadOpenApiJson() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const https = require('https');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const fileUrl = `${API_BASE_URL}/openapi.json`;
|
||||||
|
const outputPath = path.join(process.cwd(), 'scripts', 'openapi.json');
|
||||||
|
|
||||||
|
logInfo(`下载 OpenAPI 规范文件: ${fileUrl}`);
|
||||||
|
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
// 创建 HTTPS 代理(如果需要,可以忽略 SSL 证书验证)
|
||||||
|
const agent = new https.Agent({
|
||||||
|
rejectUnauthorized: false // 跳过 SSL 证书验证
|
||||||
|
});
|
||||||
|
|
||||||
|
https.get(fileUrl, { agent }, (response) => {
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = '';
|
||||||
|
|
||||||
|
response.on('data', (chunk) => {
|
||||||
|
data += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
response.on('end', () => {
|
||||||
|
try {
|
||||||
|
// 验证 JSON 格式
|
||||||
|
JSON.parse(data);
|
||||||
|
|
||||||
|
// 写入文件
|
||||||
|
fs.writeFileSync(outputPath, data, 'utf8');
|
||||||
|
const executionTime = Date.now() - startTime;
|
||||||
|
logSuccess(`OpenAPI 规范已保存到: scripts/openapi.json (${executionTime}ms)`);
|
||||||
|
resolve();
|
||||||
|
} catch (error) {
|
||||||
|
reject(new Error(`JSON 格式错误: ${error.message}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).on('error', (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 openapi-ts 命令生成客户端代码
|
||||||
|
*/
|
||||||
|
function generateWithOpenApiTS() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
logInfo('使用 @hey-api/openapi-ts 生成客户端代码...');
|
||||||
|
|
||||||
|
const { exec } = require('child_process');
|
||||||
|
const command = 'npx @hey-api/openapi-ts';
|
||||||
|
|
||||||
|
logInfo(`执行命令: ${command}`);
|
||||||
|
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
exec(command, { cwd: process.cwd() }, (error, stdout, stderr) => {
|
||||||
|
const executionTime = Date.now() - startTime;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
logError(`openapi-ts 执行失败 (${executionTime}ms)`);
|
||||||
|
logError(`错误信息: ${error.message}`);
|
||||||
|
if (stderr) {
|
||||||
|
logError(`stderr: ${stderr}`);
|
||||||
|
}
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stderr) {
|
||||||
|
logWarning(`stderr: ${stderr}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
logSuccess(`openapi-ts 执行成功 (${executionTime}ms)`);
|
||||||
|
if (stdout) {
|
||||||
|
logInfo(`输出: ${stdout}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证生成的文件
|
||||||
|
*/
|
||||||
|
function validateGeneratedFiles() {
|
||||||
|
try {
|
||||||
|
logInfo('验证生成的文件...');
|
||||||
|
const outputDir = path.join(process.cwd(), 'src', 'lib', 'api');
|
||||||
|
|
||||||
|
if (!fs.existsSync(outputDir)) {
|
||||||
|
throw new Error('输出目录不存在');
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = fs.readdirSync(outputDir);
|
||||||
|
logInfo(`输出目录包含 ${files.length} 个文件:`);
|
||||||
|
|
||||||
|
const requiredFiles = ['types.gen.ts', 'sdk.gen.ts', 'index.ts'];
|
||||||
|
const generatedFiles = [];
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const filePath = path.join(outputDir, file);
|
||||||
|
const stats = fs.statSync(filePath);
|
||||||
|
|
||||||
|
// 只显示文件,不显示目录
|
||||||
|
if (stats.isFile()) {
|
||||||
|
const size = (stats.size / 1024).toFixed(2);
|
||||||
|
logInfo(` 📄 ${file} (${size} KB)`);
|
||||||
|
generatedFiles.push(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查必要文件
|
||||||
|
const missingFiles = requiredFiles.filter(file => !generatedFiles.includes(file));
|
||||||
|
if (missingFiles.length > 0) {
|
||||||
|
logWarning(`缺少期望的文件: ${missingFiles.join(', ')}`);
|
||||||
|
} else {
|
||||||
|
logSuccess('所有期望的文件都已生成');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
logError(`验证生成的文件失败: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主函数
|
||||||
|
*/
|
||||||
|
async function main() {
|
||||||
|
const startTime = Date.now();
|
||||||
|
|
||||||
|
log('='.repeat(60), 'cyan');
|
||||||
|
log('API 客户端代码生成脚本', 'cyan');
|
||||||
|
log('基于 @hey-api/openapi-ts', 'cyan');
|
||||||
|
log('='.repeat(60), 'cyan');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 检查是否有自定义文件
|
||||||
|
const customFiles = checkCustomFiles();
|
||||||
|
|
||||||
|
if (customFiles.length > 0) {
|
||||||
|
logInfo('检测到自定义文件,将在生成前进行备份');
|
||||||
|
backupCustomFiles(customFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载 openapi.json 文件到本地
|
||||||
|
await downloadOpenApiJson();
|
||||||
|
|
||||||
|
// 使用 openapi-ts 生成代码
|
||||||
|
await generateWithOpenApiTS();
|
||||||
|
|
||||||
|
// 恢复自定义文件
|
||||||
|
if (customFiles.length > 0) {
|
||||||
|
restoreCustomFiles(customFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证生成的文件
|
||||||
|
if (!validateGeneratedFiles()) {
|
||||||
|
logWarning('文件验证发现问题,但生成过程已完成');
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalTime = Date.now() - startTime;
|
||||||
|
logSuccess(`API 客户端代码生成完成!总耗时: ${totalTime}ms`);
|
||||||
|
logSuccess('生成的文件位于 src/lib/api/ 目录');
|
||||||
|
|
||||||
|
if (customFiles.length > 0) {
|
||||||
|
logInfo('自定义文件已保持不变,避免覆盖手动配置');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
const totalTime = Date.now() - startTime;
|
||||||
|
logError(`脚本执行失败 (${totalTime}ms): ${error.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行主函数
|
||||||
|
if (require.main === module) {
|
||||||
|
main();
|
||||||
|
}
|
||||||
1
scripts/openapi.json
Normal file
1
scripts/openapi.json
Normal file
File diff suppressed because one or more lines are too long
70
scripts/setup-dev-tools.js
Normal file
70
scripts/setup-dev-tools.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
|
// 读取开发工具配置
|
||||||
|
const configPath = path.join(__dirname, '../.dev-tools-config.json');
|
||||||
|
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||||
|
|
||||||
|
// 获取命令行参数
|
||||||
|
const args = process.argv.slice(2);
|
||||||
|
const enableAll = args.includes('--enable');
|
||||||
|
const disableAll = args.includes('--disable');
|
||||||
|
|
||||||
|
console.log('🔧 开发工具设置脚本');
|
||||||
|
console.log('====================');
|
||||||
|
|
||||||
|
// 更新配置文件
|
||||||
|
function updateConfig(config) {
|
||||||
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
||||||
|
console.log('✅ 配置文件已更新');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查工具状态
|
||||||
|
function checkToolStatus(toolName, toolConfig) {
|
||||||
|
return toolConfig.enabled ? '✅ 已启用' : '❌ 已禁用';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置工具状态
|
||||||
|
function setToolStatus(toolName, enabled) {
|
||||||
|
config.tools[toolName].enabled = enabled;
|
||||||
|
const status = enabled ? '启用' : '禁用';
|
||||||
|
console.log(`${enabled ? '✅' : '❌'} ${toolName}: ${status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主逻辑
|
||||||
|
if (enableAll) {
|
||||||
|
console.log('🔓 启用所有开发工具...');
|
||||||
|
Object.keys(config.tools).forEach(toolName => {
|
||||||
|
setToolStatus(toolName, true);
|
||||||
|
});
|
||||||
|
updateConfig(config);
|
||||||
|
console.log('\n🎉 所有开发工具已启用!运行以下命令使用:');
|
||||||
|
console.log(' npm run lint # ESLint检查');
|
||||||
|
console.log(' npm run lint:fix # ESLint自动修复');
|
||||||
|
console.log(' npm run format # Prettier格式化');
|
||||||
|
console.log(' npm run format:check # Prettier检查');
|
||||||
|
} else if (disableAll) {
|
||||||
|
console.log('🔒 禁用所有开发工具...');
|
||||||
|
Object.keys(config.tools).forEach(toolName => {
|
||||||
|
setToolStatus(toolName, false);
|
||||||
|
});
|
||||||
|
updateConfig(config);
|
||||||
|
console.log('\n🛌 所有开发工具已禁用!');
|
||||||
|
} else {
|
||||||
|
console.log('📊 当前开发工具状态:');
|
||||||
|
Object.entries(config.tools).forEach(([toolName, toolConfig]) => {
|
||||||
|
console.log(` ${checkToolStatus(toolName, toolConfig)} ${toolName} - ${toolConfig.description}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('\n📖 使用说明:');
|
||||||
|
console.log(' npm run scripts:setup # 查看当前状态');
|
||||||
|
console.log(' npm run scripts:enable # 启用所有工具');
|
||||||
|
console.log(' npm run scripts:disable # 禁用所有工具');
|
||||||
|
console.log('\n💡 提示:也可以直接编辑 .dev-tools-config.json 文件来单独控制每个工具');
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/basic/customers/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/basic/customers/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function CustomersPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">客户信息</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/basic/customers
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/basic/materials/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/basic/materials/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function MaterialsPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">物料信息</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/basic/materials
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/basic/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/basic/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function BasicPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">基础信息管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/basic
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/basic/suppliers/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/basic/suppliers/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function SuppliersPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">供应商信息</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/basic/suppliers
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/basic/tools/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/basic/tools/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ToolsPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">农具信息</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/basic/tools
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/equipment/archive/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/equipment/archive/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ArchivePage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">设备档案</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/equipment/archive
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function DepreciationPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">设备折旧</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/equipment/depreciation
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/equipment/dispatch/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/equipment/dispatch/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function DispatchPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">设备调度</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/equipment/dispatch
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/equipment/disposal/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/equipment/disposal/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function DisposalPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">设备处置</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/equipment/disposal
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function MaintenancePage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">设备维护</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/equipment/maintenance
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/equipment/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/equipment/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function EquipmentPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">农资农具管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/equipment
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/inventory/check/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/inventory/check/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function CheckPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">库存盘点</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/inventory/check
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/inventory/detail/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/inventory/detail/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function DetailPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">库存明细</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/inventory/detail
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/inventory/in/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/inventory/in/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function InPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">入库管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/inventory/in
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/inventory/location/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/inventory/location/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function LocationPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">库位管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/inventory/location
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/inventory/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/inventory/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function InventoryPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">库存管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/inventory
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/inventory/suggest/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/inventory/suggest/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function SuggestPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">补货建议</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/inventory/suggest
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/inventory/warning/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/inventory/warning/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function WarningPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">库存预警</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/inventory/warning
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
7
src/app/(app)/agricultural-asset/layout.tsx
Normal file
7
src/app/(app)/agricultural-asset/layout.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export default function AgriculturalAssetLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
return <>{children}</>
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function AgriculturalAssetPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">农业资产管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/purchase/order/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/purchase/order/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function OrderPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">采购订单</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/purchase/order
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/purchase/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/purchase/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function PurchasePage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">采购管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/purchase
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/purchase/plan/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/purchase/plan/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function PlanPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">采购计划</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/purchase/plan
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/report/consumption/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/report/consumption/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ConsumptionPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">消耗报表</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/report/consumption
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/report/inventory/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/report/inventory/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function InventoryReportPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">库存报表</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/report/inventory
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/report/overview/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/report/overview/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function OverviewPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">总览报表</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/report/overview
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/report/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/report/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ReportPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">可视化报表</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/report
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/requisition/apply/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/requisition/apply/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ApplyPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">领用申请</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/requisition/apply
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ApprovalPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">领用审批</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/requisition/approval
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function CheckoutPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">领用发放</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/requisition/checkout
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/requisition/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/requisition/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function RequisitionPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">物资领用</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/requisition
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/requisition/record/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/requisition/record/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function RecordPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">领用记录</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/requisition/record
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/return/history/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/return/history/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function HistoryPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">归还历史</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/return/history
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/return/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/return/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ReturnPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">物资归还</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/return
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/return/process/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/return/process/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ProcessPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">归还处理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/return/process
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/return/register/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/return/register/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function RegisterPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">归还登记</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/return/register
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
18
src/app/(app)/agricultural-asset/return/settlement/page.tsx
Normal file
18
src/app/(app)/agricultural-asset/return/settlement/page.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function SettlementPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">归还结算</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-asset/return/settlement
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ClassificationPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">农机分类管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/archive/classification
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
src/app/(app)/agricultural-machinery/archive/entry/page.tsx
Normal file
30
src/app/(app)/agricultural-machinery/archive/entry/page.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { FileText } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function AgriculturalMachineryEntryPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<FileText className="w-6 h-6 text-blue-600" />
|
||||||
|
<h2 className="text-xl font-semibold">农机录入维护</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机设备信息录入、编辑和维护管理界面。支持农机基本信息、技术参数、购置信息等全面管理。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/archive/entry
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 农机设备信息录入、档案编辑、状态更新、设备台账管理
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
src/app/(app)/agricultural-machinery/archive/page.tsx
Normal file
30
src/app/(app)/agricultural-machinery/archive/page.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Package } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function ArchivePage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Package className="w-6 h-6 text-blue-600" />
|
||||||
|
<h2 className="text-xl font-semibold">农机档案</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机档案管理模块用于管理农业机械的基础信息和档案资料。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/archive
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong>农机信息录入、分类管理、二维码生成等
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
src/app/(app)/agricultural-machinery/archive/qrcode/page.tsx
Normal file
30
src/app/(app)/agricultural-machinery/archive/qrcode/page.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { QrCode } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function AgriculturalMachineryQrCodePage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<QrCode className="w-6 h-6 text-purple-600" />
|
||||||
|
<h2 className="text-xl font-semibold">农机二维码管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机设备二维码生成和管理平台。支持设备身份识别、信息追溯、移动端扫描查询等功能。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/archive/qrcode
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 二维码生成、批量打印、扫描验证、设备信息追溯
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function AnalysisPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">作业数据分析</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/data-analysis/analysis
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ComparisonPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">历史数据对比</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/data-analysis/comparison
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
src/app/(app)/agricultural-machinery/data-analysis/page.tsx
Normal file
30
src/app/(app)/agricultural-machinery/data-analysis/page.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { PieChart } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function DataAnalysisPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<PieChart className="w-6 h-6 text-cyan-600" />
|
||||||
|
<h2 className="text-xl font-semibold">数据管理与分析报告</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
数据管理与分析报告模块用于农机作业数据的分析、统计和报告生成。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/data-analysis
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong>作业数据分析、历史数据对比、报告生成等
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { User } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function DriverInfoManagementPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<User className="w-6 h-6 text-orange-600" />
|
||||||
|
<h2 className="text-xl font-semibold">驾驶员信息管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机驾驶员档案信息管理系统。包括驾驶员基本信息、资质证书、培训记录、考核情况等。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/driver-archive/info
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 驾驶员档案管理、资质认证、培训记录、证书到期提醒
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
src/app/(app)/agricultural-machinery/driver-archive/page.tsx
Normal file
30
src/app/(app)/agricultural-machinery/driver-archive/page.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { User } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function DriverArchivePage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<User className="w-6 h-6 text-green-600" />
|
||||||
|
<h2 className="text-xl font-semibold">驾驶员档案</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
驾驶员档案管理模块用于管理农机驾驶员的基本信息、资质认证和工作记录。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/driver-archive
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong>驾驶员信息管理、资质审核、任务分配等
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Calendar } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function DriverTaskManagementPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Calendar className="w-6 h-6 text-indigo-600" />
|
||||||
|
<h2 className="text-xl font-semibold">驾驶员任务管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
驾驶员作业任务分配和执行管理系统。支持任务派发、进度跟踪、绩效评估等功能。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/driver-archive/task
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 任务分配、作业安排、进度监控、绩效考核、工时统计
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
35
src/app/(app)/agricultural-machinery/error.tsx
Normal file
35
src/app/(app)/agricultural-machinery/error.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
|
export default function AgriculturalMachineryError({
|
||||||
|
error,
|
||||||
|
reset,
|
||||||
|
}: {
|
||||||
|
error: Error & { digest?: string }
|
||||||
|
reset: () => void
|
||||||
|
}) {
|
||||||
|
useEffect(() => {
|
||||||
|
console.error('农机管理系统错误:', error)
|
||||||
|
}, [error])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-6xl mb-4">🚙</div>
|
||||||
|
<h2 className="text-2xl font-bold text-red-800 mb-4">
|
||||||
|
农机系统出现了错误
|
||||||
|
</h2>
|
||||||
|
<p className="text-red-600 mb-6">
|
||||||
|
{error.message || '未知系统错误'}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={reset}
|
||||||
|
className="px-6 py-3 bg-red-600 text-white rounded-md hover:bg-red-700 transition-colors"
|
||||||
|
>
|
||||||
|
重新加载
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function AlertRulesPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">故障预警规则</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/fault-diagnosis/alert-rules
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function HealthPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">设备健康管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/fault-diagnosis/health
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Zap } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function FaultDiagnosisPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Zap className="w-6 h-6 text-red-600" />
|
||||||
|
<h2 className="text-xl font-semibold">远程诊断与故障预警</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
远程诊断与故障预警模块用于农机设备的健康监测、故障预警和远程诊断。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/fault-diagnosis
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong>故障预警规则、预警管理、设备健康监控等
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function ParameterPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">设备参数监控</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/fault-diagnosis/parameter
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function WarningPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">故障预警管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/fault-diagnosis/warning
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
7
src/app/(app)/agricultural-machinery/layout.tsx
Normal file
7
src/app/(app)/agricultural-machinery/layout.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export default function AgriculturalMachineryLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
return <>{children}</>
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Cog } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function LoadDeviceManagementPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Cog className="w-6 h-6 text-red-600" />
|
||||||
|
<h2 className="text-xl font-semibold">负载设备管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机负载设备的日常管理和维护系统。支持设备状态监控、维护计划、备件管理等。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/load-management/device
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 设备台账、维护管理、故障记录、备件库存、状态监控
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Database } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function LoadDeviceLibraryPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Database className="w-6 h-6 text-emerald-600" />
|
||||||
|
<h2 className="text-xl font-semibold">负载设备库</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机负载设备信息库管理系统。建立完整的负载设备档案,支持设备查询和对比分析。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/load-management/library
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 设备信息库、技术规格、性能参数、设备选型推荐
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Settings } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function LoadManagementPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Settings className="w-6 h-6 text-orange-600" />
|
||||||
|
<h2 className="text-xl font-semibold">农机负载管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机负载管理模块用于管理农机设备的负载配置、参数设置和设备库管理。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/load-management
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong>负载类型管理、参数配置、设备库管理等
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Settings } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function LoadParameterManagementPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Settings className="w-6 h-6 text-amber-600" />
|
||||||
|
<h2 className="text-xl font-semibold">负载参数管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机负载设备参数配置和优化管理。支持作业参数调整、性能优化、标准配置等。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/load-management/parameter
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 参数配置、性能调优、作业标准设置、参数模板管理
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Package } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function LoadTypeManagementPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Package className="w-6 h-6 text-cyan-600" />
|
||||||
|
<h2 className="text-xl font-semibold">负载类型管理</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机负载设备类型分类和管理系统。支持播种、施肥、收割等各类作业负载的类型定义。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/load-management/type
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 负载类型定义、作业分类、设备规格配置、类型参数设置
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
10
src/app/(app)/agricultural-machinery/loading.tsx
Normal file
10
src/app/(app)/agricultural-machinery/loading.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
export default function AgriculturalMachineryLoading() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-green-600 mx-auto mb-4"></div>
|
||||||
|
<p className="text-gray-600">正在加载农机管理系统...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { MapPin } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function RealTimeLocationMonitoringPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<MapPin className="w-6 h-6 text-blue-600" />
|
||||||
|
<h2 className="text-xl font-semibold">实时定位监控</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机设备实时GPS定位和轨迹监控系统。提供地图可视化、位置追踪、历史轨迹回放等功能。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/monitoring/location
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> GPS定位、地图显示、实时轨迹、位置历史、电子围栏
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { BarChart3 } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function OperationDataMonitoringPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<BarChart3 className="w-6 h-6 text-orange-600" />
|
||||||
|
<h2 className="text-xl font-semibold">作业数据监控</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机作业数据采集和分析监控。实时收集作业数据,监控作业质量和效率指标。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/monitoring/operation
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 数据采集、作业监控、质量分析、效率统计、报表生成
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
30
src/app/(app)/agricultural-machinery/monitoring/page.tsx
Normal file
30
src/app/(app)/agricultural-machinery/monitoring/page.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Navigation } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function MonitoringPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Navigation className="w-6 h-6 text-purple-600" />
|
||||||
|
<h2 className="text-xl font-semibold">设备实时监控与定位</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
设备实时监控与定位模块用于实时监控农机设备的位置、状态和作业数据。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/monitoring
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong>实时定位监控、作业状态监控、数据监控等
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Activity } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function WorkStatusMonitoringPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Activity className="w-6 h-6 text-green-600" />
|
||||||
|
<h2 className="text-xl font-semibold">作业状态监控</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
农机设备作业状态实时监控系统。跟踪设备运行状态、作业进度、工作效率等关键指标。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/monitoring/status
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong> 状态监控、作业跟踪、效率分析、异常报警、状态统计
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
93
src/app/(app)/agricultural-machinery/page.tsx
Normal file
93
src/app/(app)/agricultural-machinery/page.tsx
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
export default function AgriculturalMachineryPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
|
<h2 className="text-xl font-semibold text-gray-800 mb-4">
|
||||||
|
智能农机管理系统
|
||||||
|
</h2>
|
||||||
|
<p className="text-gray-600 mb-6">
|
||||||
|
管理农机设备档案、监控实时状态、优化调度方案
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
<Link
|
||||||
|
href="/agricultural-machinery/archive/machinery-entry"
|
||||||
|
className="block p-4 bg-green-50 rounded-lg hover:bg-green-100 transition-colors"
|
||||||
|
>
|
||||||
|
<h3 className="font-semibold text-green-900 mb-2">
|
||||||
|
📋 农机档案录入与维护
|
||||||
|
</h3>
|
||||||
|
<p className="text-green-700 text-sm">
|
||||||
|
农机设备信息管理
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href="/agricultural-machinery/monitoring/real-time-location-tracking"
|
||||||
|
className="block p-4 bg-blue-50 rounded-lg hover:bg-blue-100 transition-colors"
|
||||||
|
>
|
||||||
|
<h3 className="font-semibold text-blue-900 mb-2">
|
||||||
|
📍 实时位置追踪
|
||||||
|
</h3>
|
||||||
|
<p className="text-blue-700 text-sm">
|
||||||
|
农机设备定位监控
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link
|
||||||
|
href="/agricultural-machinery/scheduling/task-assignment"
|
||||||
|
className="block p-4 bg-purple-50 rounded-lg hover:bg-purple-100 transition-colors"
|
||||||
|
>
|
||||||
|
<h3 className="font-semibold text-purple-900 mb-2">
|
||||||
|
📅 任务分配
|
||||||
|
</h3>
|
||||||
|
<p className="text-purple-700 text-sm">
|
||||||
|
农机作业任务分配
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
|
<h3 className="text-lg font-semibold text-gray-800 mb-4">
|
||||||
|
📊 农机状态概览
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<span className="text-gray-600">运行中</span>
|
||||||
|
<span className="text-green-600 font-semibold">12 台</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<span className="text-gray-600">空闲中</span>
|
||||||
|
<span className="text-gray-600 font-semibold">8 台</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<span className="text-gray-600">维护中</span>
|
||||||
|
<span className="text-yellow-600 font-semibold">3 台</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white rounded-lg shadow p-6">
|
||||||
|
<h3 className="text-lg font-semibold text-gray-800 mb-4">
|
||||||
|
🔧 快速操作
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<button className="w-full px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700 transition-colors">
|
||||||
|
添加新农机
|
||||||
|
</button>
|
||||||
|
<button className="w-full px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors">
|
||||||
|
生成报表
|
||||||
|
</button>
|
||||||
|
<button className="w-full px-4 py-2 bg-purple-600 text-white rounded hover:bg-purple-700 transition-colors">
|
||||||
|
批量操作
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function CockpitPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">作业驾驶舱</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/precision-operation/cockpit
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function DispatchPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">作业计划调度</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/precision-operation/dispatch
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
import { Target } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function PrecisionOperationPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Target className="w-6 h-6 text-indigo-600" />
|
||||||
|
<h2 className="text-xl font-semibold">精准作业管理与支持</h2>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<p className="text-muted-foreground">
|
||||||
|
精准作业管理与支持模块用于管理农机的精准作业、路径规划和作业调度。
|
||||||
|
</p>
|
||||||
|
<div className="p-3 bg-muted rounded-lg">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/precision-operation
|
||||||
|
</p>
|
||||||
|
<p className="text-sm mt-1">
|
||||||
|
<strong>主要功能:</strong>作业记录管理、路径规划、作业调度、作业驾驶舱等
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { Card } from '@/components/ui/card';
|
||||||
|
|
||||||
|
export default function RecordPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
<Card className="p-6">
|
||||||
|
<h2 className="text-xl font-semibold">作业记录管理</h2>
|
||||||
|
<div className="p-3 bg-muted rounded-lg mt-3">
|
||||||
|
<p className="text-sm">
|
||||||
|
<strong>页面路径:</strong> /agricultural-machinery/precision-operation/record
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user