1322 lines
32 KiB
Markdown
1322 lines
32 KiB
Markdown
|
|
# 宁夏智慧养殖监管平台 开发指南
|
|||
|
|
|
|||
|
|
## 版本历史
|
|||
|
|
|
|||
|
|
| 版本 | 日期 | 作者 | 描述 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| v1.0 | 2025-01-18 | 开发团队 | 初始版本 |
|
|||
|
|
| v2.0 | 2025-01-19 | 开发团队 | 全面重构,增加多端开发指南和最佳实践 |
|
|||
|
|
|
|||
|
|
## 1. 开发环境概述
|
|||
|
|
|
|||
|
|
### 1.1 系统要求
|
|||
|
|
|
|||
|
|
**基础环境:**
|
|||
|
|
- **操作系统**: macOS 10.15+, Windows 10+, Ubuntu 18.04+
|
|||
|
|
- **Node.js**: 18.0+ (推荐使用 LTS 版本)
|
|||
|
|
- **npm**: 8.0+ 或 **yarn**: 1.22+ 或 **pnpm**: 7.0+
|
|||
|
|
- **MySQL**: 8.0+
|
|||
|
|
- **Git**: 2.25+
|
|||
|
|
- **内存**: 8GB+ (推荐 16GB)
|
|||
|
|
- **存储**: 20GB+ 可用空间
|
|||
|
|
|
|||
|
|
**开发工具推荐:**
|
|||
|
|
- **IDE**: Visual Studio Code (推荐插件见下文)
|
|||
|
|
- **API测试**: Postman 或 Insomnia
|
|||
|
|
- **数据库管理**: MySQL Workbench, phpMyAdmin, 或 DBeaver
|
|||
|
|
- **版本控制**: Git + GitHub Desktop (可选)
|
|||
|
|
- **终端**: iTerm2 (macOS), Windows Terminal, 或 Hyper
|
|||
|
|
|
|||
|
|
### 1.2 VSCode 推荐插件
|
|||
|
|
|
|||
|
|
**必装插件:**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"recommendations": [
|
|||
|
|
"ms-vscode.vscode-eslint",
|
|||
|
|
"esbenp.prettier-vscode",
|
|||
|
|
"bradlc.vscode-tailwindcss",
|
|||
|
|
"vue.volar",
|
|||
|
|
"ms-vscode.vscode-json",
|
|||
|
|
"formulahendry.auto-rename-tag",
|
|||
|
|
"christian-kohler.path-intellisense",
|
|||
|
|
"ms-vscode.vscode-typescript-next",
|
|||
|
|
"ms-vscode.vscode-mysql",
|
|||
|
|
"humao.rest-client"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**配置文件 (.vscode/settings.json):**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"editor.formatOnSave": true,
|
|||
|
|
"editor.codeActionsOnSave": {
|
|||
|
|
"source.fixAll.eslint": true
|
|||
|
|
},
|
|||
|
|
"emmet.includeLanguages": {
|
|||
|
|
"vue-html": "html"
|
|||
|
|
},
|
|||
|
|
"files.associations": {
|
|||
|
|
"*.vue": "vue"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 2. 项目架构详解
|
|||
|
|
|
|||
|
|
### 2.1 整体项目结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
nxxmdata/
|
|||
|
|
├── README.md # 项目主文档
|
|||
|
|
├── package.json # 根目录依赖管理
|
|||
|
|
├── .gitignore # Git忽略文件
|
|||
|
|
├── docs/ # 项目文档
|
|||
|
|
│ ├── API.md # API设计文档
|
|||
|
|
│ ├── 数据库设计文档.md # 数据库设计
|
|||
|
|
│ ├── DEVELOPMENT.md # 开发指南(本文档)
|
|||
|
|
│ ├── DEPLOYMENT.md # 部署文档
|
|||
|
|
│ └── config/ # 配置文档
|
|||
|
|
│ ├── PRD.md # 产品需求文档
|
|||
|
|
│ └── arch.md # 系统架构文档
|
|||
|
|
├── backend/ # 后端服务
|
|||
|
|
│ ├── package.json # 后端依赖
|
|||
|
|
│ ├── server.js # 服务入口
|
|||
|
|
│ ├── config/ # 配置文件
|
|||
|
|
│ ├── controllers/ # 控制器层
|
|||
|
|
│ ├── models/ # 数据模型层
|
|||
|
|
│ ├── routes/ # 路由层
|
|||
|
|
│ ├── middleware/ # 中间件
|
|||
|
|
│ ├── utils/ # 工具函数
|
|||
|
|
│ └── tests/ # 后端测试
|
|||
|
|
├── admin-system/ # 管理后台
|
|||
|
|
│ ├── package.json # 前端依赖
|
|||
|
|
│ ├── vite.config.js # Vite配置
|
|||
|
|
│ ├── src/ # 源代码
|
|||
|
|
│ │ ├── main.js # 应用入口
|
|||
|
|
│ │ ├── App.vue # 根组件
|
|||
|
|
│ │ ├── components/ # 公共组件
|
|||
|
|
│ │ ├── views/ # 页面组件
|
|||
|
|
│ │ ├── router/ # 路由配置
|
|||
|
|
│ │ ├── store/ # 状态管理
|
|||
|
|
│ │ ├── api/ # API接口
|
|||
|
|
│ │ ├── utils/ # 工具函数
|
|||
|
|
│ │ └── assets/ # 静态资源
|
|||
|
|
│ └── public/ # 公共资源
|
|||
|
|
├── website/ # 官网和大屏
|
|||
|
|
│ └── data-screen/ # 数据大屏
|
|||
|
|
│ ├── package.json
|
|||
|
|
│ ├── src/
|
|||
|
|
│ └── public/
|
|||
|
|
└── mini-app/ # 小程序矩阵
|
|||
|
|
├── government-mini-program/ # 政府端小程序
|
|||
|
|
├── insurance_mini_program/ # 保险端小程序
|
|||
|
|
└── bank-backend/ # 银行端后台
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.2 后端架构 (backend/)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
backend/
|
|||
|
|
├── server.js # 应用入口文件
|
|||
|
|
├── package.json # 依赖管理
|
|||
|
|
├── .env.example # 环境变量模板
|
|||
|
|
├── config/ # 配置文件目录
|
|||
|
|
│ ├── database.js # 数据库配置
|
|||
|
|
│ ├── database-simple.js # 简化数据库配置
|
|||
|
|
│ ├── swagger.js # API文档配置
|
|||
|
|
│ ├── performance-config.js # 性能监控配置
|
|||
|
|
│ └── permissions.js # 权限配置
|
|||
|
|
├── controllers/ # 控制器层
|
|||
|
|
│ ├── farmController.js # 农场业务逻辑
|
|||
|
|
│ ├── deviceController.js # 设备业务逻辑
|
|||
|
|
│ ├── userController.js # 用户业务逻辑
|
|||
|
|
│ ├── animalController.js # 动物业务逻辑
|
|||
|
|
│ ├── alertController.js # 预警业务逻辑
|
|||
|
|
│ └── dashboardController.js # 仪表板业务逻辑
|
|||
|
|
├── models/ # 数据模型层
|
|||
|
|
│ ├── index.js # 模型索引和关联
|
|||
|
|
│ ├── BaseModel.js # 基础模型类
|
|||
|
|
│ ├── Farm.js # 农场模型
|
|||
|
|
│ ├── Animal.js # 动物模型
|
|||
|
|
│ ├── Device.js # 设备模型
|
|||
|
|
│ ├── User.js # 用户模型
|
|||
|
|
│ ├── Alert.js # 预警模型
|
|||
|
|
│ └── ... # 其他业务模型
|
|||
|
|
├── routes/ # 路由层
|
|||
|
|
│ ├── index.js # 路由入口
|
|||
|
|
│ ├── farms.js # 农场路由
|
|||
|
|
│ ├── devices.js # 设备路由
|
|||
|
|
│ ├── users.js # 用户路由
|
|||
|
|
│ └── auth.js # 认证路由
|
|||
|
|
├── middleware/ # 中间件
|
|||
|
|
│ ├── auth.js # 认证中间件
|
|||
|
|
│ ├── validation.js # 数据验证中间件
|
|||
|
|
│ ├── errorHandler.js # 错误处理中间件
|
|||
|
|
│ └── logger.js # 日志中间件
|
|||
|
|
├── utils/ # 工具函数
|
|||
|
|
│ ├── response.js # 响应格式化
|
|||
|
|
│ ├── validation.js # 数据验证工具
|
|||
|
|
│ ├── encryption.js # 加密工具
|
|||
|
|
│ └── dateUtils.js # 日期工具
|
|||
|
|
└── tests/ # 测试文件
|
|||
|
|
├── unit/ # 单元测试
|
|||
|
|
├── integration/ # 集成测试
|
|||
|
|
└── fixtures/ # 测试数据
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.3 前端架构 (admin-system/)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
admin-system/
|
|||
|
|
├── package.json # 依赖管理
|
|||
|
|
├── vite.config.js # Vite构建配置
|
|||
|
|
├── index.html # HTML模板
|
|||
|
|
├── .env.example # 环境变量模板
|
|||
|
|
├── src/ # 源代码目录
|
|||
|
|
│ ├── main.js # 应用入口
|
|||
|
|
│ ├── App.vue # 根组件
|
|||
|
|
│ ├── components/ # 公共组件
|
|||
|
|
│ │ ├── common/ # 通用组件
|
|||
|
|
│ │ │ ├── Header.vue # 页面头部
|
|||
|
|
│ │ │ ├── Sidebar.vue # 侧边栏
|
|||
|
|
│ │ │ ├── Footer.vue # 页面底部
|
|||
|
|
│ │ │ └── Loading.vue # 加载组件
|
|||
|
|
│ │ ├── charts/ # 图表组件
|
|||
|
|
│ │ │ ├── LineChart.vue # 折线图
|
|||
|
|
│ │ │ ├── BarChart.vue # 柱状图
|
|||
|
|
│ │ │ └── PieChart.vue # 饼图
|
|||
|
|
│ │ └── forms/ # 表单组件
|
|||
|
|
│ │ ├── FarmForm.vue # 农场表单
|
|||
|
|
│ │ └── DeviceForm.vue # 设备表单
|
|||
|
|
│ ├── views/ # 页面组件
|
|||
|
|
│ │ ├── Dashboard/ # 仪表板页面
|
|||
|
|
│ │ ├── Farms/ # 农场管理页面
|
|||
|
|
│ │ ├── Devices/ # 设备管理页面
|
|||
|
|
│ │ ├── Animals/ # 动物管理页面
|
|||
|
|
│ │ ├── Alerts/ # 预警管理页面
|
|||
|
|
│ │ └── Settings/ # 系统设置页面
|
|||
|
|
│ ├── router/ # 路由配置
|
|||
|
|
│ │ ├── index.js # 路由主文件
|
|||
|
|
│ │ └── modules/ # 路由模块
|
|||
|
|
│ ├── store/ # 状态管理 (Pinia)
|
|||
|
|
│ │ ├── index.js # Store入口
|
|||
|
|
│ │ ├── modules/ # Store模块
|
|||
|
|
│ │ │ ├── user.js # 用户状态
|
|||
|
|
│ │ │ ├── farm.js # 农场状态
|
|||
|
|
│ │ │ └── device.js # 设备状态
|
|||
|
|
│ ├── api/ # API接口
|
|||
|
|
│ │ ├── index.js # API配置
|
|||
|
|
│ │ ├── farm.js # 农场API
|
|||
|
|
│ │ ├── device.js # 设备API
|
|||
|
|
│ │ └── user.js # 用户API
|
|||
|
|
│ ├── utils/ # 工具函数
|
|||
|
|
│ │ ├── request.js # HTTP请求封装
|
|||
|
|
│ │ ├── auth.js # 认证工具
|
|||
|
|
│ │ ├── format.js # 格式化工具
|
|||
|
|
│ │ └── constants.js # 常量定义
|
|||
|
|
│ ├── styles/ # 样式文件
|
|||
|
|
│ │ ├── index.css # 主样式文件
|
|||
|
|
│ │ ├── variables.css # CSS变量
|
|||
|
|
│ │ └── components/ # 组件样式
|
|||
|
|
│ └── assets/ # 静态资源
|
|||
|
|
│ ├── images/ # 图片资源
|
|||
|
|
│ ├── icons/ # 图标资源
|
|||
|
|
│ └── fonts/ # 字体资源
|
|||
|
|
└── public/ # 公共资源
|
|||
|
|
├── favicon.ico # 网站图标
|
|||
|
|
└── logo.png # 项目Logo
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 3. 开发环境搭建
|
|||
|
|
|
|||
|
|
### 3.1 环境准备
|
|||
|
|
|
|||
|
|
#### 3.1.1 安装 Node.js
|
|||
|
|
```bash
|
|||
|
|
# 使用 nvm 管理 Node.js 版本 (推荐)
|
|||
|
|
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
|||
|
|
nvm install 18
|
|||
|
|
nvm use 18
|
|||
|
|
|
|||
|
|
# 或直接从官网下载安装
|
|||
|
|
# https://nodejs.org/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.2 安装 MySQL
|
|||
|
|
```bash
|
|||
|
|
# macOS (使用 Homebrew)
|
|||
|
|
brew install mysql
|
|||
|
|
brew services start mysql
|
|||
|
|
|
|||
|
|
# Ubuntu
|
|||
|
|
sudo apt update
|
|||
|
|
sudo apt install mysql-server
|
|||
|
|
sudo systemctl start mysql
|
|||
|
|
|
|||
|
|
# Windows
|
|||
|
|
# 从官网下载安装包: https://dev.mysql.com/downloads/mysql/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.1.3 配置 MySQL
|
|||
|
|
```sql
|
|||
|
|
-- 创建数据库
|
|||
|
|
CREATE DATABASE nxxmdata CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|||
|
|
|
|||
|
|
-- 创建用户 (可选,用于生产环境)
|
|||
|
|
CREATE USER 'nxxmdata_user'@'localhost' IDENTIFIED BY 'your_password';
|
|||
|
|
GRANT ALL PRIVILEGES ON nxxmdata.* TO 'nxxmdata_user'@'localhost';
|
|||
|
|
FLUSH PRIVILEGES;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 项目初始化
|
|||
|
|
|
|||
|
|
#### 3.2.1 克隆项目
|
|||
|
|
```bash
|
|||
|
|
git clone <repository-url>
|
|||
|
|
cd nxxmdata
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2.2 安装依赖
|
|||
|
|
```bash
|
|||
|
|
# 安装根目录依赖 (如果有)
|
|||
|
|
npm install
|
|||
|
|
|
|||
|
|
# 安装后端依赖
|
|||
|
|
cd backend
|
|||
|
|
npm install
|
|||
|
|
|
|||
|
|
# 安装管理后台依赖
|
|||
|
|
cd ../admin-system
|
|||
|
|
npm install
|
|||
|
|
|
|||
|
|
# 安装官网大屏依赖
|
|||
|
|
cd ../website/data-screen
|
|||
|
|
npm install
|
|||
|
|
|
|||
|
|
# 返回根目录
|
|||
|
|
cd ../..
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2.3 环境变量配置
|
|||
|
|
|
|||
|
|
**后端环境变量 (backend/.env):**
|
|||
|
|
```env
|
|||
|
|
# 服务器配置
|
|||
|
|
PORT=5350
|
|||
|
|
NODE_ENV=development
|
|||
|
|
|
|||
|
|
# 数据库配置
|
|||
|
|
DB_HOST=localhost
|
|||
|
|
DB_PORT=3306
|
|||
|
|
DB_NAME=nxxmdata
|
|||
|
|
DB_USER=root
|
|||
|
|
DB_PASSWORD=your_password
|
|||
|
|
|
|||
|
|
# JWT配置
|
|||
|
|
JWT_SECRET=your_jwt_secret_key
|
|||
|
|
JWT_EXPIRES_IN=24h
|
|||
|
|
JWT_REFRESH_EXPIRES_IN=7d
|
|||
|
|
|
|||
|
|
# Redis配置 (可选)
|
|||
|
|
REDIS_HOST=localhost
|
|||
|
|
REDIS_PORT=6379
|
|||
|
|
REDIS_PASSWORD=
|
|||
|
|
|
|||
|
|
# 文件上传配置
|
|||
|
|
UPLOAD_PATH=./uploads
|
|||
|
|
MAX_FILE_SIZE=10485760
|
|||
|
|
|
|||
|
|
# 第三方服务配置
|
|||
|
|
BAIDU_MAP_AK=your_baidu_map_ak
|
|||
|
|
WECHAT_APP_ID=your_wechat_app_id
|
|||
|
|
WECHAT_APP_SECRET=your_wechat_app_secret
|
|||
|
|
|
|||
|
|
# 日志配置
|
|||
|
|
LOG_LEVEL=debug
|
|||
|
|
LOG_FILE=./logs/app.log
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**前端环境变量 (admin-system/.env):**
|
|||
|
|
```env
|
|||
|
|
# API配置
|
|||
|
|
VITE_API_BASE_URL=http://localhost:5350/api
|
|||
|
|
VITE_API_TIMEOUT=10000
|
|||
|
|
|
|||
|
|
# 应用配置
|
|||
|
|
VITE_APP_TITLE=宁夏智慧养殖监管平台
|
|||
|
|
VITE_APP_VERSION=2.0.0
|
|||
|
|
|
|||
|
|
# 地图配置
|
|||
|
|
VITE_BAIDU_MAP_AK=your_baidu_map_ak
|
|||
|
|
|
|||
|
|
# 开发配置
|
|||
|
|
VITE_MOCK_ENABLED=false
|
|||
|
|
VITE_DEBUG_ENABLED=true
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.2.4 数据库初始化
|
|||
|
|
```bash
|
|||
|
|
# 进入后端目录
|
|||
|
|
cd backend
|
|||
|
|
|
|||
|
|
# 运行数据库迁移 (如果有迁移文件)
|
|||
|
|
npm run db:migrate
|
|||
|
|
|
|||
|
|
# 或者直接导入SQL文件
|
|||
|
|
mysql -u root -p nxxmdata < ../database/schema.sql
|
|||
|
|
mysql -u root -p nxxmdata < ../database/seed.sql
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.3 启动开发服务器
|
|||
|
|
|
|||
|
|
#### 3.3.1 使用单独终端启动
|
|||
|
|
```bash
|
|||
|
|
# Terminal 1: 启动后端服务
|
|||
|
|
cd backend
|
|||
|
|
npm run dev
|
|||
|
|
|
|||
|
|
# Terminal 2: 启动管理后台
|
|||
|
|
cd admin-system
|
|||
|
|
npm run dev
|
|||
|
|
|
|||
|
|
# Terminal 3: 启动数据大屏 (可选)
|
|||
|
|
cd website/data-screen
|
|||
|
|
npm run dev
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 3.3.2 使用 concurrently 同时启动 (推荐)
|
|||
|
|
```bash
|
|||
|
|
# 在根目录安装 concurrently
|
|||
|
|
npm install -g concurrently
|
|||
|
|
|
|||
|
|
# 创建启动脚本 (package.json)
|
|||
|
|
{
|
|||
|
|
"scripts": {
|
|||
|
|
"dev": "concurrently \"npm run dev:backend\" \"npm run dev:admin\" \"npm run dev:screen\"",
|
|||
|
|
"dev:backend": "cd backend && npm run dev",
|
|||
|
|
"dev:admin": "cd admin-system && npm run dev",
|
|||
|
|
"dev:screen": "cd website/data-screen && npm run dev"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 一键启动所有服务
|
|||
|
|
npm run dev
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.4 访问地址
|
|||
|
|
|
|||
|
|
启动成功后,可以通过以下地址访问:
|
|||
|
|
|
|||
|
|
- **后端API**: http://localhost:5350
|
|||
|
|
- **API文档**: http://localhost:5350/api-docs
|
|||
|
|
- **管理后台**: http://localhost:3000
|
|||
|
|
- **数据大屏**: http://localhost:3001
|
|||
|
|
|
|||
|
|
## 4. 开发规范
|
|||
|
|
|
|||
|
|
### 4.1 代码规范
|
|||
|
|
|
|||
|
|
#### 4.1.1 JavaScript/TypeScript 规范
|
|||
|
|
```javascript
|
|||
|
|
// 使用 ESLint + Prettier 配置
|
|||
|
|
// .eslintrc.js
|
|||
|
|
module.exports = {
|
|||
|
|
env: {
|
|||
|
|
browser: true,
|
|||
|
|
es2021: true,
|
|||
|
|
node: true
|
|||
|
|
},
|
|||
|
|
extends: [
|
|||
|
|
'eslint:recommended',
|
|||
|
|
'@vue/eslint-config-prettier'
|
|||
|
|
],
|
|||
|
|
parserOptions: {
|
|||
|
|
ecmaVersion: 'latest',
|
|||
|
|
sourceType: 'module'
|
|||
|
|
},
|
|||
|
|
rules: {
|
|||
|
|
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
|||
|
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
|||
|
|
'vue/multi-word-component-names': 'off'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.1.2 Vue 组件规范
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<!-- 使用语义化的HTML标签 -->
|
|||
|
|
<div class="farm-list">
|
|||
|
|
<header class="farm-list__header">
|
|||
|
|
<h1 class="farm-list__title">{{ title }}</h1>
|
|||
|
|
</header>
|
|||
|
|
|
|||
|
|
<main class="farm-list__content">
|
|||
|
|
<!-- 组件内容 -->
|
|||
|
|
</main>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { defineComponent, ref, onMounted } from 'vue'
|
|||
|
|
import { useFarmStore } from '@/store/modules/farm'
|
|||
|
|
|
|||
|
|
export default defineComponent({
|
|||
|
|
name: 'FarmList', // 组件名使用 PascalCase
|
|||
|
|
|
|||
|
|
props: {
|
|||
|
|
title: {
|
|||
|
|
type: String,
|
|||
|
|
default: '农场列表'
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
emits: ['update', 'delete'],
|
|||
|
|
|
|||
|
|
setup(props, { emit }) {
|
|||
|
|
const farmStore = useFarmStore()
|
|||
|
|
const loading = ref(false)
|
|||
|
|
|
|||
|
|
const loadFarms = async () => {
|
|||
|
|
loading.value = true
|
|||
|
|
try {
|
|||
|
|
await farmStore.fetchFarms()
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('加载农场列表失败:', error)
|
|||
|
|
} finally {
|
|||
|
|
loading.value = false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onMounted(() => {
|
|||
|
|
loadFarms()
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
loading,
|
|||
|
|
loadFarms
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
/* 使用 BEM 命名规范 */
|
|||
|
|
.farm-list {
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.farm-list__header {
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.farm-list__title {
|
|||
|
|
font-size: 24px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.farm-list__content {
|
|||
|
|
/* 内容样式 */
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.1.3 API 接口规范
|
|||
|
|
```javascript
|
|||
|
|
// api/farm.js
|
|||
|
|
import request from '@/utils/request'
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 农场API接口
|
|||
|
|
*/
|
|||
|
|
export const farmApi = {
|
|||
|
|
/**
|
|||
|
|
* 获取农场列表
|
|||
|
|
* @param {Object} params - 查询参数
|
|||
|
|
* @param {number} params.page - 页码
|
|||
|
|
* @param {number} params.limit - 每页数量
|
|||
|
|
* @param {string} params.keyword - 搜索关键词
|
|||
|
|
* @returns {Promise} API响应
|
|||
|
|
*/
|
|||
|
|
getFarms(params = {}) {
|
|||
|
|
return request({
|
|||
|
|
url: '/farms',
|
|||
|
|
method: 'GET',
|
|||
|
|
params
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 创建农场
|
|||
|
|
* @param {Object} data - 农场数据
|
|||
|
|
* @returns {Promise} API响应
|
|||
|
|
*/
|
|||
|
|
createFarm(data) {
|
|||
|
|
return request({
|
|||
|
|
url: '/farms',
|
|||
|
|
method: 'POST',
|
|||
|
|
data
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 更新农场信息
|
|||
|
|
* @param {number} id - 农场ID
|
|||
|
|
* @param {Object} data - 更新数据
|
|||
|
|
* @returns {Promise} API响应
|
|||
|
|
*/
|
|||
|
|
updateFarm(id, data) {
|
|||
|
|
return request({
|
|||
|
|
url: `/farms/${id}`,
|
|||
|
|
method: 'PUT',
|
|||
|
|
data
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 删除农场
|
|||
|
|
* @param {number} id - 农场ID
|
|||
|
|
* @returns {Promise} API响应
|
|||
|
|
*/
|
|||
|
|
deleteFarm(id) {
|
|||
|
|
return request({
|
|||
|
|
url: `/farms/${id}`,
|
|||
|
|
method: 'DELETE'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 Git 工作流规范
|
|||
|
|
|
|||
|
|
#### 4.2.1 分支命名规范
|
|||
|
|
```bash
|
|||
|
|
# 主分支
|
|||
|
|
main/master # 生产环境分支
|
|||
|
|
develop # 开发环境分支
|
|||
|
|
|
|||
|
|
# 功能分支
|
|||
|
|
feature/farm-management # 新功能开发
|
|||
|
|
feature/device-monitoring # 设备监控功能
|
|||
|
|
|
|||
|
|
# 修复分支
|
|||
|
|
bugfix/login-error # Bug修复
|
|||
|
|
hotfix/security-patch # 紧急修复
|
|||
|
|
|
|||
|
|
# 发布分支
|
|||
|
|
release/v2.0.0 # 版本发布
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.2.2 提交信息规范
|
|||
|
|
```bash
|
|||
|
|
# 提交信息格式
|
|||
|
|
<type>(<scope>): <subject>
|
|||
|
|
|
|||
|
|
# 类型说明
|
|||
|
|
feat: 新功能
|
|||
|
|
fix: Bug修复
|
|||
|
|
docs: 文档更新
|
|||
|
|
style: 代码格式调整
|
|||
|
|
refactor: 代码重构
|
|||
|
|
test: 测试相关
|
|||
|
|
chore: 构建过程或辅助工具的变动
|
|||
|
|
|
|||
|
|
# 示例
|
|||
|
|
feat(farm): 添加农场地图显示功能
|
|||
|
|
fix(device): 修复设备状态更新问题
|
|||
|
|
docs(api): 更新API文档
|
|||
|
|
style(component): 调整组件样式格式
|
|||
|
|
refactor(utils): 重构日期处理工具函数
|
|||
|
|
test(farm): 添加农场模块单元测试
|
|||
|
|
chore(build): 更新构建配置
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.3 数据库开发规范
|
|||
|
|
|
|||
|
|
#### 4.3.1 模型定义规范
|
|||
|
|
```javascript
|
|||
|
|
// models/Farm.js
|
|||
|
|
const { DataTypes } = require('sequelize')
|
|||
|
|
const BaseModel = require('./BaseModel')
|
|||
|
|
const { sequelize } = require('../config/database')
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 农场模型
|
|||
|
|
* @class Farm
|
|||
|
|
* @extends BaseModel
|
|||
|
|
*/
|
|||
|
|
class Farm extends BaseModel {
|
|||
|
|
/**
|
|||
|
|
* 获取农场统计信息
|
|||
|
|
* @returns {Promise<Object>} 统计信息
|
|||
|
|
*/
|
|||
|
|
async getStatistics() {
|
|||
|
|
// 业务逻辑实现
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 验证农场数据
|
|||
|
|
* @param {Object} data - 农场数据
|
|||
|
|
* @returns {Object} 验证结果
|
|||
|
|
*/
|
|||
|
|
static validateData(data) {
|
|||
|
|
// 数据验证逻辑
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 模型字段定义
|
|||
|
|
Farm.init({
|
|||
|
|
id: {
|
|||
|
|
type: DataTypes.INTEGER,
|
|||
|
|
primaryKey: true,
|
|||
|
|
autoIncrement: true,
|
|||
|
|
comment: '农场ID'
|
|||
|
|
},
|
|||
|
|
name: {
|
|||
|
|
type: DataTypes.STRING(100),
|
|||
|
|
allowNull: false,
|
|||
|
|
comment: '农场名称'
|
|||
|
|
},
|
|||
|
|
type: {
|
|||
|
|
type: DataTypes.STRING(50),
|
|||
|
|
allowNull: false,
|
|||
|
|
comment: '农场类型'
|
|||
|
|
},
|
|||
|
|
location: {
|
|||
|
|
type: DataTypes.JSON,
|
|||
|
|
allowNull: false,
|
|||
|
|
defaultValue: {},
|
|||
|
|
comment: '地理位置信息'
|
|||
|
|
},
|
|||
|
|
status: {
|
|||
|
|
type: DataTypes.ENUM('active', 'inactive', 'maintenance'),
|
|||
|
|
defaultValue: 'active',
|
|||
|
|
comment: '农场状态'
|
|||
|
|
}
|
|||
|
|
}, {
|
|||
|
|
sequelize,
|
|||
|
|
tableName: 'farms',
|
|||
|
|
modelName: 'Farm',
|
|||
|
|
timestamps: true,
|
|||
|
|
createdAt: 'created_at',
|
|||
|
|
updatedAt: 'updated_at',
|
|||
|
|
comment: '农场信息表'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
module.exports = Farm
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 4.3.2 控制器规范
|
|||
|
|
```javascript
|
|||
|
|
// controllers/farmController.js
|
|||
|
|
const { Farm, Animal, Device } = require('../models')
|
|||
|
|
const { successResponse, errorResponse } = require('../utils/response')
|
|||
|
|
const { validateFarmData } = require('../utils/validation')
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 农场控制器
|
|||
|
|
* @class FarmController
|
|||
|
|
*/
|
|||
|
|
class FarmController {
|
|||
|
|
/**
|
|||
|
|
* 获取农场列表
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
async getFarms(req, res) {
|
|||
|
|
try {
|
|||
|
|
const { page = 1, limit = 20, keyword = '' } = req.query
|
|||
|
|
|
|||
|
|
const whereClause = {}
|
|||
|
|
if (keyword) {
|
|||
|
|
whereClause.name = { [Op.like]: `%${keyword}%` }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const { count, rows } = await Farm.findAndCountAll({
|
|||
|
|
where: whereClause,
|
|||
|
|
limit: parseInt(limit),
|
|||
|
|
offset: (parseInt(page) - 1) * parseInt(limit),
|
|||
|
|
order: [['created_at', 'DESC']],
|
|||
|
|
include: [
|
|||
|
|
{
|
|||
|
|
model: Animal,
|
|||
|
|
as: 'animals',
|
|||
|
|
attributes: ['id']
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
model: Device,
|
|||
|
|
as: 'devices',
|
|||
|
|
attributes: ['id', 'status']
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
return successResponse(res, {
|
|||
|
|
farms: rows,
|
|||
|
|
pagination: {
|
|||
|
|
total: count,
|
|||
|
|
page: parseInt(page),
|
|||
|
|
limit: parseInt(limit),
|
|||
|
|
pages: Math.ceil(count / limit)
|
|||
|
|
}
|
|||
|
|
}, '获取农场列表成功')
|
|||
|
|
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('获取农场列表失败:', error)
|
|||
|
|
return errorResponse(res, '获取农场列表失败', 500)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 创建农场
|
|||
|
|
* @param {Object} req - 请求对象
|
|||
|
|
* @param {Object} res - 响应对象
|
|||
|
|
*/
|
|||
|
|
async createFarm(req, res) {
|
|||
|
|
try {
|
|||
|
|
// 数据验证
|
|||
|
|
const validation = validateFarmData(req.body)
|
|||
|
|
if (!validation.isValid) {
|
|||
|
|
return errorResponse(res, validation.errors, 400)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const farm = await Farm.create(req.body)
|
|||
|
|
|
|||
|
|
return successResponse(res, { farm }, '创建农场成功', 201)
|
|||
|
|
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('创建农场失败:', error)
|
|||
|
|
return errorResponse(res, '创建农场失败', 500)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = new FarmController()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 5. 调试与测试
|
|||
|
|
|
|||
|
|
### 5.1 后端调试
|
|||
|
|
|
|||
|
|
#### 5.1.1 使用 VSCode 调试
|
|||
|
|
```json
|
|||
|
|
// .vscode/launch.json
|
|||
|
|
{
|
|||
|
|
"version": "0.2.0",
|
|||
|
|
"configurations": [
|
|||
|
|
{
|
|||
|
|
"name": "Debug Backend",
|
|||
|
|
"type": "node",
|
|||
|
|
"request": "launch",
|
|||
|
|
"program": "${workspaceFolder}/backend/server.js",
|
|||
|
|
"env": {
|
|||
|
|
"NODE_ENV": "development"
|
|||
|
|
},
|
|||
|
|
"console": "integratedTerminal",
|
|||
|
|
"restart": true,
|
|||
|
|
"runtimeExecutable": "nodemon",
|
|||
|
|
"skipFiles": ["<node_internals>/**"]
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 5.1.2 日志调试
|
|||
|
|
```javascript
|
|||
|
|
// utils/logger.js
|
|||
|
|
const winston = require('winston')
|
|||
|
|
|
|||
|
|
const logger = winston.createLogger({
|
|||
|
|
level: process.env.LOG_LEVEL || 'info',
|
|||
|
|
format: winston.format.combine(
|
|||
|
|
winston.format.timestamp(),
|
|||
|
|
winston.format.errors({ stack: true }),
|
|||
|
|
winston.format.json()
|
|||
|
|
),
|
|||
|
|
transports: [
|
|||
|
|
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
|
|||
|
|
new winston.transports.File({ filename: 'logs/combined.log' })
|
|||
|
|
]
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
if (process.env.NODE_ENV !== 'production') {
|
|||
|
|
logger.add(new winston.transports.Console({
|
|||
|
|
format: winston.format.simple()
|
|||
|
|
}))
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
module.exports = logger
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 前端调试
|
|||
|
|
|
|||
|
|
#### 5.2.1 Vue DevTools
|
|||
|
|
```bash
|
|||
|
|
# 安装 Vue DevTools 浏览器扩展
|
|||
|
|
# Chrome: https://chrome.google.com/webstore/detail/vuejs-devtools/
|
|||
|
|
# Firefox: https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 5.2.2 网络请求调试
|
|||
|
|
```javascript
|
|||
|
|
// utils/request.js
|
|||
|
|
import axios from 'axios'
|
|||
|
|
|
|||
|
|
const request = axios.create({
|
|||
|
|
baseURL: import.meta.env.VITE_API_BASE_URL,
|
|||
|
|
timeout: import.meta.env.VITE_API_TIMEOUT || 10000
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 请求拦截器
|
|||
|
|
request.interceptors.request.use(
|
|||
|
|
config => {
|
|||
|
|
// 开发环境下打印请求信息
|
|||
|
|
if (import.meta.env.DEV) {
|
|||
|
|
console.log('🚀 API Request:', {
|
|||
|
|
url: config.url,
|
|||
|
|
method: config.method,
|
|||
|
|
params: config.params,
|
|||
|
|
data: config.data
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加认证token
|
|||
|
|
const token = localStorage.getItem('token')
|
|||
|
|
if (token) {
|
|||
|
|
config.headers.Authorization = `Bearer ${token}`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return config
|
|||
|
|
},
|
|||
|
|
error => {
|
|||
|
|
console.error('❌ Request Error:', error)
|
|||
|
|
return Promise.reject(error)
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// 响应拦截器
|
|||
|
|
request.interceptors.response.use(
|
|||
|
|
response => {
|
|||
|
|
// 开发环境下打印响应信息
|
|||
|
|
if (import.meta.env.DEV) {
|
|||
|
|
console.log('✅ API Response:', {
|
|||
|
|
url: response.config.url,
|
|||
|
|
status: response.status,
|
|||
|
|
data: response.data
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return response.data
|
|||
|
|
},
|
|||
|
|
error => {
|
|||
|
|
console.error('❌ Response Error:', error)
|
|||
|
|
|
|||
|
|
// 处理认证错误
|
|||
|
|
if (error.response?.status === 401) {
|
|||
|
|
localStorage.removeItem('token')
|
|||
|
|
window.location.href = '/login'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return Promise.reject(error)
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
export default request
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.3 单元测试
|
|||
|
|
|
|||
|
|
#### 5.3.1 后端测试 (Jest)
|
|||
|
|
```javascript
|
|||
|
|
// tests/unit/models/Farm.test.js
|
|||
|
|
const { Farm } = require('../../../models')
|
|||
|
|
const { sequelize } = require('../../../config/database')
|
|||
|
|
|
|||
|
|
describe('Farm Model', () => {
|
|||
|
|
beforeAll(async () => {
|
|||
|
|
await sequelize.sync({ force: true })
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
afterAll(async () => {
|
|||
|
|
await sequelize.close()
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
describe('创建农场', () => {
|
|||
|
|
it('应该成功创建农场', async () => {
|
|||
|
|
const farmData = {
|
|||
|
|
name: '测试农场',
|
|||
|
|
type: '养牛场',
|
|||
|
|
location: { lat: 38.4517, lng: 106.2309 }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const farm = await Farm.create(farmData)
|
|||
|
|
|
|||
|
|
expect(farm.id).toBeDefined()
|
|||
|
|
expect(farm.name).toBe(farmData.name)
|
|||
|
|
expect(farm.type).toBe(farmData.type)
|
|||
|
|
expect(farm.status).toBe('active')
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
it('应该验证必填字段', async () => {
|
|||
|
|
await expect(Farm.create({})).rejects.toThrow()
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 5.3.2 前端测试 (Vitest + Vue Test Utils)
|
|||
|
|
```javascript
|
|||
|
|
// tests/unit/components/FarmList.test.js
|
|||
|
|
import { describe, it, expect, vi } from 'vitest'
|
|||
|
|
import { mount } from '@vue/test-utils'
|
|||
|
|
import { createPinia } from 'pinia'
|
|||
|
|
import FarmList from '@/components/FarmList.vue'
|
|||
|
|
|
|||
|
|
describe('FarmList', () => {
|
|||
|
|
it('应该渲染农场列表', async () => {
|
|||
|
|
const pinia = createPinia()
|
|||
|
|
|
|||
|
|
const wrapper = mount(FarmList, {
|
|||
|
|
global: {
|
|||
|
|
plugins: [pinia]
|
|||
|
|
},
|
|||
|
|
props: {
|
|||
|
|
title: '测试农场列表'
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
expect(wrapper.find('.farm-list__title').text()).toBe('测试农场列表')
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
it('应该处理加载状态', async () => {
|
|||
|
|
// 测试加载状态逻辑
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 6. 性能优化
|
|||
|
|
|
|||
|
|
### 6.1 后端性能优化
|
|||
|
|
|
|||
|
|
#### 6.1.1 数据库查询优化
|
|||
|
|
```javascript
|
|||
|
|
// 使用索引优化查询
|
|||
|
|
const farms = await Farm.findAll({
|
|||
|
|
where: {
|
|||
|
|
status: 'active' // 确保 status 字段有索引
|
|||
|
|
},
|
|||
|
|
include: [
|
|||
|
|
{
|
|||
|
|
model: Animal,
|
|||
|
|
as: 'animals',
|
|||
|
|
attributes: ['id', 'name'], // 只查询需要的字段
|
|||
|
|
where: {
|
|||
|
|
status: 1
|
|||
|
|
},
|
|||
|
|
required: false // LEFT JOIN
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
attributes: ['id', 'name', 'type', 'location'], // 只查询需要的字段
|
|||
|
|
order: [['created_at', 'DESC']],
|
|||
|
|
limit: 20 // 分页查询
|
|||
|
|
})
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 6.1.2 缓存策略
|
|||
|
|
```javascript
|
|||
|
|
// utils/cache.js
|
|||
|
|
const Redis = require('redis')
|
|||
|
|
const client = Redis.createClient({
|
|||
|
|
host: process.env.REDIS_HOST || 'localhost',
|
|||
|
|
port: process.env.REDIS_PORT || 6379
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 缓存装饰器
|
|||
|
|
* @param {string} key - 缓存键
|
|||
|
|
* @param {number} ttl - 过期时间(秒)
|
|||
|
|
*/
|
|||
|
|
function cache(key, ttl = 300) {
|
|||
|
|
return function(target, propertyName, descriptor) {
|
|||
|
|
const method = descriptor.value
|
|||
|
|
|
|||
|
|
descriptor.value = async function(...args) {
|
|||
|
|
const cacheKey = `${key}:${JSON.stringify(args)}`
|
|||
|
|
|
|||
|
|
// 尝试从缓存获取
|
|||
|
|
const cached = await client.get(cacheKey)
|
|||
|
|
if (cached) {
|
|||
|
|
return JSON.parse(cached)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 执行原方法
|
|||
|
|
const result = await method.apply(this, args)
|
|||
|
|
|
|||
|
|
// 存入缓存
|
|||
|
|
await client.setex(cacheKey, ttl, JSON.stringify(result))
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 使用示例
|
|||
|
|
class FarmService {
|
|||
|
|
@cache('farm:list', 300)
|
|||
|
|
async getFarms(params) {
|
|||
|
|
// 查询逻辑
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.2 前端性能优化
|
|||
|
|
|
|||
|
|
#### 6.2.1 组件懒加载
|
|||
|
|
```javascript
|
|||
|
|
// router/index.js
|
|||
|
|
import { createRouter, createWebHistory } from 'vue-router'
|
|||
|
|
|
|||
|
|
const routes = [
|
|||
|
|
{
|
|||
|
|
path: '/farms',
|
|||
|
|
name: 'Farms',
|
|||
|
|
component: () => import('@/views/Farms/index.vue'), // 懒加载
|
|||
|
|
meta: {
|
|||
|
|
title: '农场管理'
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
path: '/devices',
|
|||
|
|
name: 'Devices',
|
|||
|
|
component: () => import('@/views/Devices/index.vue'),
|
|||
|
|
meta: {
|
|||
|
|
title: '设备管理'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 6.2.2 图片优化
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<div class="image-container">
|
|||
|
|
<!-- 使用 WebP 格式,降级到 JPEG -->
|
|||
|
|
<picture>
|
|||
|
|
<source srcset="/images/farm.webp" type="image/webp">
|
|||
|
|
<img
|
|||
|
|
src="/images/farm.jpg"
|
|||
|
|
alt="农场图片"
|
|||
|
|
loading="lazy"
|
|||
|
|
@load="onImageLoad"
|
|||
|
|
@error="onImageError"
|
|||
|
|
>
|
|||
|
|
</picture>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
export default {
|
|||
|
|
methods: {
|
|||
|
|
onImageLoad() {
|
|||
|
|
// 图片加载成功处理
|
|||
|
|
},
|
|||
|
|
onImageError(event) {
|
|||
|
|
// 图片加载失败,使用默认图片
|
|||
|
|
event.target.src = '/images/default-farm.jpg'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 7. 常见问题解决
|
|||
|
|
|
|||
|
|
### 7.1 开发环境问题
|
|||
|
|
|
|||
|
|
#### 7.1.1 端口占用问题
|
|||
|
|
```bash
|
|||
|
|
# 查看端口占用
|
|||
|
|
lsof -i :5350
|
|||
|
|
netstat -tulpn | grep :5350
|
|||
|
|
|
|||
|
|
# 杀死占用进程
|
|||
|
|
kill -9 <PID>
|
|||
|
|
|
|||
|
|
# 或者修改端口配置
|
|||
|
|
# backend/.env
|
|||
|
|
PORT=5351
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 7.1.2 数据库连接问题
|
|||
|
|
```javascript
|
|||
|
|
// 检查数据库连接
|
|||
|
|
const { sequelize } = require('./config/database')
|
|||
|
|
|
|||
|
|
async function testConnection() {
|
|||
|
|
try {
|
|||
|
|
await sequelize.authenticate()
|
|||
|
|
console.log('✅ 数据库连接成功')
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('❌ 数据库连接失败:', error)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
testConnection()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 7.1.3 跨域问题
|
|||
|
|
```javascript
|
|||
|
|
// backend/server.js
|
|||
|
|
const cors = require('cors')
|
|||
|
|
|
|||
|
|
app.use(cors({
|
|||
|
|
origin: [
|
|||
|
|
'http://localhost:3000', // 管理后台
|
|||
|
|
'http://localhost:3001' // 数据大屏
|
|||
|
|
],
|
|||
|
|
credentials: true
|
|||
|
|
}))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.2 构建部署问题
|
|||
|
|
|
|||
|
|
#### 7.2.1 构建失败
|
|||
|
|
```bash
|
|||
|
|
# 清理缓存
|
|||
|
|
npm cache clean --force
|
|||
|
|
rm -rf node_modules package-lock.json
|
|||
|
|
npm install
|
|||
|
|
|
|||
|
|
# 检查 Node.js 版本
|
|||
|
|
node --version
|
|||
|
|
npm --version
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 7.2.2 环境变量问题
|
|||
|
|
```bash
|
|||
|
|
# 检查环境变量是否正确加载
|
|||
|
|
echo $NODE_ENV
|
|||
|
|
echo $PORT
|
|||
|
|
|
|||
|
|
# 在代码中打印环境变量
|
|||
|
|
console.log('Environment:', process.env.NODE_ENV)
|
|||
|
|
console.log('Port:', process.env.PORT)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 8. 开发工具推荐
|
|||
|
|
|
|||
|
|
### 8.1 VSCode 扩展
|
|||
|
|
|
|||
|
|
**必装扩展:**
|
|||
|
|
- **Vue Language Features (Volar)**: Vue 3 支持
|
|||
|
|
- **ESLint**: 代码检查
|
|||
|
|
- **Prettier**: 代码格式化
|
|||
|
|
- **Auto Rename Tag**: 自动重命名标签
|
|||
|
|
- **Bracket Pair Colorizer**: 括号配对着色
|
|||
|
|
- **GitLens**: Git 增强
|
|||
|
|
- **Thunder Client**: API 测试
|
|||
|
|
- **MySQL**: 数据库管理
|
|||
|
|
|
|||
|
|
**可选扩展:**
|
|||
|
|
- **Tailwind CSS IntelliSense**: Tailwind 支持
|
|||
|
|
- **Vue VSCode Snippets**: Vue 代码片段
|
|||
|
|
- **JavaScript (ES6) code snippets**: JS 代码片段
|
|||
|
|
- **Path Intellisense**: 路径智能提示
|
|||
|
|
- **Import Cost**: 导入成本显示
|
|||
|
|
|
|||
|
|
### 8.2 浏览器工具
|
|||
|
|
|
|||
|
|
**开发工具:**
|
|||
|
|
- **Vue DevTools**: Vue 调试工具
|
|||
|
|
- **React DevTools**: React 调试工具(如果使用)
|
|||
|
|
- **Redux DevTools**: Redux 调试工具(如果使用)
|
|||
|
|
- **Lighthouse**: 性能分析工具
|
|||
|
|
|
|||
|
|
### 8.3 命令行工具
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 全局安装常用工具
|
|||
|
|
npm install -g @vue/cli # Vue CLI
|
|||
|
|
npm install -g nodemon # 自动重启服务
|
|||
|
|
npm install -g pm2 # 进程管理
|
|||
|
|
npm install -g concurrently # 并发执行命令
|
|||
|
|
npm install -g http-server # 静态文件服务器
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 9. 团队协作
|
|||
|
|
|
|||
|
|
### 9.1 代码审查
|
|||
|
|
|
|||
|
|
**审查清单:**
|
|||
|
|
- [ ] 代码符合项目规范
|
|||
|
|
- [ ] 功能实现正确
|
|||
|
|
- [ ] 性能考虑合理
|
|||
|
|
- [ ] 安全性检查
|
|||
|
|
- [ ] 测试覆盖充分
|
|||
|
|
- [ ] 文档更新及时
|
|||
|
|
|
|||
|
|
### 9.2 发布流程
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 1. 功能开发完成
|
|||
|
|
git checkout develop
|
|||
|
|
git pull origin develop
|
|||
|
|
|
|||
|
|
# 2. 创建发布分支
|
|||
|
|
git checkout -b release/v2.1.0
|
|||
|
|
|
|||
|
|
# 3. 版本号更新
|
|||
|
|
npm version minor
|
|||
|
|
|
|||
|
|
# 4. 构建测试
|
|||
|
|
npm run build
|
|||
|
|
npm run test
|
|||
|
|
|
|||
|
|
# 5. 合并到主分支
|
|||
|
|
git checkout main
|
|||
|
|
git merge release/v2.1.0
|
|||
|
|
|
|||
|
|
# 6. 创建标签
|
|||
|
|
git tag v2.1.0
|
|||
|
|
git push origin main --tags
|
|||
|
|
|
|||
|
|
# 7. 部署到生产环境
|
|||
|
|
npm run deploy:prod
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 10. 学习资源
|
|||
|
|
|
|||
|
|
### 10.1 官方文档
|
|||
|
|
|
|||
|
|
- **Vue 3**: https://vuejs.org/
|
|||
|
|
- **Node.js**: https://nodejs.org/
|
|||
|
|
- **Express**: https://expressjs.com/
|
|||
|
|
- **Sequelize**: https://sequelize.org/
|
|||
|
|
- **MySQL**: https://dev.mysql.com/doc/
|
|||
|
|
|
|||
|
|
### 10.2 推荐教程
|
|||
|
|
|
|||
|
|
- **Vue 3 官方教程**: https://vuejs.org/tutorial/
|
|||
|
|
- **Node.js 最佳实践**: https://github.com/goldbergyoni/nodebestpractices
|
|||
|
|
- **JavaScript 现代教程**: https://javascript.info/
|
|||
|
|
- **MDN Web 文档**: https://developer.mozilla.org/
|
|||
|
|
|
|||
|
|
### 10.3 社区资源
|
|||
|
|
|
|||
|
|
- **Vue 社区**: https://vue-community.org/
|
|||
|
|
- **Node.js 社区**: https://nodejs.org/en/community/
|
|||
|
|
- **Stack Overflow**: https://stackoverflow.com/
|
|||
|
|
- **GitHub**: https://github.com/
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**文档维护说明:**
|
|||
|
|
本开发指南应随着项目的发展和技术栈的更新及时维护。如有问题或建议,请提交 Issue 或 Pull Request。
|
|||
|
|
|
|||
|
|
**联系方式:**
|
|||
|
|
- 技术负责人:[技术负责人邮箱]
|
|||
|
|
- 项目经理:[项目经理邮箱]
|
|||
|
|
- 技术支持群:[技术支持群号]
|