# 开发指南 ## 概述 本文档为开发者提供宁夏智慧养殖监管平台的详细开发指南,包括开发环境搭建、代码规范、开发流程、调试技巧等内容。 ## 开发环境搭建 ### 系统要求 - **Node.js**: 18.0+ (推荐使用 LTS 版本) - **npm**: 8.0+ 或 **yarn**: 1.22+ - **MySQL**: 8.0+ - **Git**: 2.25+ - **编辑器**: VSCode (推荐) ### 工具推荐 - **API测试**: Postman 或 Insomnia - **数据库管理**: MySQL Workbench 或 phpMyAdmin - **版本控制**: Git + GitHub/GitLab - **终端**: iTerm2 (macOS) 或 Windows Terminal ### 环境搭建步骤 #### 1. 克隆项目 ```bash git clone cd nxxmdata ``` #### 2. 安装依赖 ```bash # 后端依赖 cd backend npm install # 前端依赖 - 管理后台 cd ../admin-system/frontend npm install # 前端依赖 - 官网大屏 cd ../../website/data-screen npm install # 微信小程序(可选) cd ../../mini_program/farm-monitor-dashboard npm install ``` #### 3. 数据库配置 ```bash # 创建数据库 mysql -u root -p CREATE DATABASE nxxmdata CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 导入数据结构 cd backend mysql -u root -p nxxmdata < ../create_tables.sql ``` #### 4. 环境变量配置 ```bash # 后端环境变量 cp backend/.env.example backend/.env # 编辑 .env 文件,配置数据库连接等信息 # 前端环境变量 cp admin-system/frontend/.env.example admin-system/frontend/.env # 配置API基础URL等 ``` #### 5. 启动开发服务器 ```bash # 启动后端 (Terminal 1) cd backend npm run dev # 启动管理后台前端 (Terminal 2) cd admin-system/frontend npm run dev # 启动官网大屏 (Terminal 3) cd website/data-screen npm run dev ``` ## 项目结构详解 ### 后端架构 (`backend/`) ``` backend/ ├── config/ # 配置文件 │ ├── database.js # 数据库配置 │ ├── swagger.js # API文档配置 │ └── performance-config.js # 性能监控配置 ├── controllers/ # 控制器层 │ ├── farmController.js # 农场业务逻辑 │ ├── deviceController.js # 设备业务逻辑 │ └── userController.js # 用户业务逻辑 ├── models/ # 数据模型层 │ ├── Farm.js # 农场模型 │ ├── Device.js # 设备模型 │ └── User.js # 用户模型 ├── routes/ # 路由层 │ ├── farms.js # 农场相关路由 │ ├── devices.js # 设备相关路由 │ └── auth.js # 认证相关路由 ├── middleware/ # 中间件 │ ├── auth.js # 认证中间件 │ └── performance-middleware.js # 性能监控中间件 ├── utils/ # 工具类 │ ├── logger.js # 日志工具 │ └── performance-monitor.js # 性能监控工具 ├── migrations/ # 数据库迁移 ├── seeds/ # 种子数据 ├── logs/ # 日志文件 └── server.js # 服务器入口 ``` ### 前端架构 (`admin-system/frontend/`) ``` frontend/ ├── src/ │ ├── components/ # 可复用组件 │ │ ├── BaiduMap.vue # 百度地图组件 │ │ ├── EChart.vue # 图表组件 │ │ └── Dashboard.vue # 仪表盘组件 │ ├── views/ # 页面组件 │ │ ├── Home.vue # 首页 │ │ ├── MapView.vue # 地图视图 │ │ └── Analytics.vue # 数据分析 │ ├── stores/ # 状态管理 (Pinia) │ │ ├── user.js # 用户状态 │ │ └── data.js # 数据状态 │ ├── router/ # 路由配置 │ │ ├── index.js # 路由实例 │ │ └── routes.js # 路由定义 │ ├── utils/ # 工具函数 │ │ └── api.js # API调用封装 │ ├── styles/ # 样式文件 │ └── config/ # 配置文件 ├── public/ # 静态资源 └── vite.config.js # Vite配置 ``` ## 开发规范 ### 代码风格规范 #### JavaScript/Vue.js 规范 ```javascript // 1. 使用 ES6+ 语法 const apiUrl = process.env.VITE_API_BASE_URL; // 2. 函数命名使用驼峰命名 function getUserInfo() {} // 3. 常量使用大写字母和下划线 const API_BASE_URL = 'http://localhost:5350/api'; // 4. 类名使用 PascalCase class UserService {} // 5. 文件名使用 kebab-case // user-service.js, farm-detail.vue ``` #### Vue.js 组件规范 ```vue ``` #### Node.js 后端规范 ```javascript // 1. 使用严格模式 'use strict'; // 2. 模块导入顺序:内置模块 -> 第三方模块 -> 本地模块 const path = require('path'); const express = require('express'); const { Farm } = require('../models'); // 3. 异步函数使用 async/await const getFarms = async (req, res) => { try { // 4. 输入验证 const { page = 1, limit = 10 } = req.query; // 5. 业务逻辑 const farms = await Farm.findAll({ limit: parseInt(limit), offset: (parseInt(page) - 1) * parseInt(limit) }); // 6. 统一响应格式 res.json({ success: true, data: farms, message: '获取成功' }); } catch (error) { // 7. 错误处理 res.status(500).json({ success: false, error: { message: error.message } }); } }; module.exports = { getFarms }; ``` ### Git 工作流规范 #### 分支命名规范 ```bash # 功能分支 feature/user-management feature/device-monitoring # 修复分支 fix/login-error fix/map-display-issue # 发布分支 release/v1.0.0 # 热修复分支 hotfix/security-patch ``` #### 提交信息规范 ```bash # 格式: type(scope): description # 类型 (type): # feat: 新功能 # fix: 修复bug # docs: 文档更新 # style: 代码格式调整 # refactor: 重构 # test: 测试相关 # chore: 构建过程或辅助工具的变动 # 示例: git commit -m "feat(user): add user registration functionality" git commit -m "fix(map): resolve baidu map display issue" git commit -m "docs(api): update API documentation" ``` ### 数据库设计规范 #### 表命名规范 ```sql -- 表名使用小写字母和下划线 CREATE TABLE users (...); CREATE TABLE user_roles (...); CREATE TABLE device_sensors (...); -- 字段名使用小写字母和下划线 ALTER TABLE users ADD COLUMN created_at DATETIME; ALTER TABLE users ADD COLUMN updated_at DATETIME; -- 索引命名 CREATE INDEX idx_users_email ON users(email); CREATE INDEX idx_farms_location ON farms(location); ``` #### 模型定义规范 ```javascript // models/User.js const { DataTypes } = require('sequelize'); module.exports = (sequelize) => { const User = sequelize.define('User', { id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, comment: '用户唯一标识' }, username: { type: DataTypes.STRING(50), allowNull: false, unique: true, comment: '用户名' }, email: { type: DataTypes.STRING(100), allowNull: false, unique: true, validate: { isEmail: true }, comment: '邮箱地址' } }, { tableName: 'users', timestamps: true, underscored: true, comment: '用户表' }); // 定义关联关系 User.associate = (models) => { User.belongsToMany(models.Role, { through: models.UserRole, foreignKey: 'user_id', otherKey: 'role_id' }); }; return User; }; ``` ## 开发流程 ### 功能开发流程 #### 1. 需求分析 - 理解业务需求 - 确认技术方案 - 评估开发时间 #### 2. 设计阶段 ```bash # 数据库设计 # 1. 创建或修改表结构 # 2. 更新模型定义 # 3. 编写迁移脚本 # API设计 # 1. 定义路由 # 2. 设计请求/响应格式 # 3. 更新API文档 # 前端设计 # 1. UI组件设计 # 2. 状态管理设计 # 3. 路由规划 ``` #### 3. 开发阶段 ```bash # 创建功能分支 git checkout -b feature/new-feature # 后端开发 # 1. 创建/修改模型 # 2. 编写控制器逻辑 # 3. 添加路由 # 4. 编写单元测试 # 前端开发 # 1. 创建Vue组件 # 2. 实现业务逻辑 # 3. 添加样式 # 4. 集成API # 提交代码 git add . git commit -m "feat: implement new feature" git push origin feature/new-feature ``` #### 4. 测试阶段 ```bash # 单元测试 npm test # 集成测试 npm run test:integration # 端到端测试 npm run test:e2e # 手动测试 # 1. 功能测试 # 2. 兼容性测试 # 3. 性能测试 ``` #### 5. 代码审查 - 创建 Pull Request - 代码审查 - 修改反馈问题 - 合并到主分支 ### 调试技巧 #### 后端调试 ##### 1. 使用 console.log 调试 ```javascript // 在关键位置添加日志 console.log('User data:', userData); console.log('Database query result:', result); // 使用 JSON.stringify 查看对象 console.log('Request body:', JSON.stringify(req.body, null, 2)); ``` ##### 2. 使用 Winston 日志 ```javascript const logger = require('../utils/logger'); // 不同级别的日志 logger.info('User logged in', { userId: user.id }); logger.warn('Invalid input', { input: req.body }); logger.error('Database error', { error: error.message }); ``` ##### 3. 使用 Node.js 调试器 ```bash # 启动调试模式 node --inspect-brk server.js # 在 Chrome 中打开 chrome://inspect # 连接到 Node.js 进程进行调试 ``` ##### 4. 数据库查询调试 ```javascript // 启用 Sequelize 日志 const sequelize = new Sequelize(config, { logging: console.log, // 显示 SQL 查询 benchmark: true // 显示查询时间 }); // 手动执行 SQL 查询 const [results, metadata] = await sequelize.query( 'SELECT * FROM users WHERE id = ?', { replacements: [userId] } ); ``` #### 前端调试 ##### 1. 使用 Vue DevTools ```bash # 安装 Vue DevTools 浏览器扩展 # 查看组件状态、props、events # 检查 Pinia store 状态 ``` ##### 2. 使用 console.log ```javascript // 在组件中添加调试信息 export default { setup() { const userData = ref(null); const fetchUser = async () => { console.log('Fetching user data...'); const response = await api.getUser(); console.log('User response:', response); userData.value = response.data; }; return { userData, fetchUser }; } } ``` ##### 3. 使用浏览器开发者工具 ```javascript // 在代码中设置断点 debugger; // 查看网络请求 // Network 标签页 -> 检查 API 请求和响应 // 查看控制台错误 // Console 标签页 -> 查看 JavaScript 错误 ``` ##### 4. API 调试 ```javascript // 创建 API 调试工具 const apiDebug = { log: (method, url, data, response) => { console.group(`API ${method.toUpperCase()} ${url}`); console.log('Request data:', data); console.log('Response:', response); console.groupEnd(); } }; // 在 API 调用中使用 const response = await axios.post('/api/farms', farmData); apiDebug.log('POST', '/api/farms', farmData, response.data); ``` ### 性能优化 #### 后端性能优化 ##### 1. 数据库查询优化 ```javascript // 使用索引 // 在经常查询的字段上添加索引 CREATE INDEX idx_farms_status ON farms(status); // 避免 N+1 查询 const farms = await Farm.findAll({ include: [{ model: Device, as: 'devices' }] }); // 使用分页 const farms = await Farm.findAndCountAll({ limit: 10, offset: (page - 1) * 10 }); // 只查询需要的字段 const farms = await Farm.findAll({ attributes: ['id', 'name', 'status'] }); ``` ##### 2. 缓存策略 ```javascript // 使用内存缓存 const cache = new Map(); const getCachedData = (key) => { if (cache.has(key)) { return cache.get(key); } return null; }; const setCachedData = (key, data, ttl = 300000) => { cache.set(key, data); setTimeout(() => cache.delete(key), ttl); }; ``` ##### 3. 异步处理 ```javascript // 使用 Promise.all 并行处理 const [farms, devices, users] = await Promise.all([ Farm.findAll(), Device.findAll(), User.findAll() ]); // 使用 stream 处理大量数据 const stream = Farm.findAll({ stream: true }); stream.on('data', (farm) => { // 处理单个农场数据 }); ``` #### 前端性能优化 ##### 1. 组件懒加载 ```javascript // router/routes.js const routes = [ { path: '/farms', component: () => import('../views/Farms.vue') // 懒加载 } ]; ``` ##### 2. 图片优化 ```vue ``` ##### 3. 虚拟滚动 ```vue ``` ### 测试指南 #### 单元测试 ##### 后端单元测试 (Jest) ```javascript // tests/controllers/farmController.test.js const { getFarms } = require('../../controllers/farmController'); const { Farm } = require('../../models'); jest.mock('../../models'); describe('Farm Controller', () => { describe('getFarms', () => { it('should return farms list', async () => { const mockFarms = [ { id: 1, name: 'Farm 1' }, { id: 2, name: 'Farm 2' } ]; Farm.findAll.mockResolvedValue(mockFarms); const req = { query: {} }; const res = { json: jest.fn(), status: jest.fn().mockReturnThis() }; await getFarms(req, res); expect(res.json).toHaveBeenCalledWith({ success: true, data: mockFarms, message: '获取成功' }); }); }); }); ``` ##### 前端单元测试 (Vitest) ```javascript // tests/components/FarmList.test.js import { mount } from '@vue/test-utils'; import FarmList from '@/components/FarmList.vue'; describe('FarmList', () => { it('renders farm list correctly', () => { const farms = [ { id: 1, name: 'Farm 1', status: 'active' }, { id: 2, name: 'Farm 2', status: 'inactive' } ]; const wrapper = mount(FarmList, { props: { farms } }); expect(wrapper.findAll('.farm-item')).toHaveLength(2); expect(wrapper.text()).toContain('Farm 1'); expect(wrapper.text()).toContain('Farm 2'); }); it('emits select event when farm is clicked', async () => { const farms = [{ id: 1, name: 'Farm 1', status: 'active' }]; const wrapper = mount(FarmList, { props: { farms } }); await wrapper.find('.farm-item').trigger('click'); expect(wrapper.emitted('select')).toBeTruthy(); expect(wrapper.emitted('select')[0]).toEqual([farms[0]]); }); }); ``` #### 集成测试 ```javascript // tests/integration/farms.test.js const request = require('supertest'); const app = require('../../server'); describe('Farms API', () => { it('GET /api/farms should return farms list', async () => { const response = await request(app) .get('/api/farms') .set('Authorization', 'Bearer valid_token') .expect(200); expect(response.body.success).toBe(true); expect(Array.isArray(response.body.data)).toBe(true); }); it('POST /api/farms should create new farm', async () => { const farmData = { name: 'Test Farm', type: 'cattle', longitude: 106.26667, latitude: 38.46667 }; const response = await request(app) .post('/api/farms') .set('Authorization', 'Bearer admin_token') .send(farmData) .expect(201); expect(response.body.success).toBe(true); expect(response.body.data.name).toBe(farmData.name); }); }); ``` ### 部署和运维 #### 本地开发部署 ```bash # 1. 启动所有服务 npm run dev:all # 2. 查看日志 tail -f backend/logs/app.log # 3. 数据库管理 npm run db:migrate npm run db:seed ``` #### 生产环境部署 ```bash # 1. 构建项目 npm run build # 2. 使用 PM2 部署 pm2 start ecosystem.config.js --env production # 3. 监控服务 pm2 monit pm2 logs ``` ## 常见问题解决 ### 开发环境问题 #### 1. 端口占用 ```bash # 查找占用端口的进程 lsof -i :5350 netstat -ano | findstr :5350 # Windows # 杀死进程 kill -9 taskkill /PID /F # Windows ``` #### 2. 依赖安装失败 ```bash # 清除 npm 缓存 npm cache clean --force # 删除 node_modules 重新安装 rm -rf node_modules package-lock.json npm install # 使用 yarn 代替 npm yarn install ``` #### 3. 数据库连接失败 ```bash # 检查 MySQL 服务状态 brew services list | grep mysql # macOS systemctl status mysql # Linux net start mysql # Windows # 测试数据库连接 mysql -u root -p -h localhost -P 3306 ``` ### 运行时问题 #### 1. API 请求失败 ```javascript // 检查网络请求 // 1. 打开浏览器开发者工具 // 2. 查看 Network 标签页 // 3. 检查请求状态码和响应内容 // 添加请求拦截器 axios.interceptors.request.use( config => { console.log('Request:', config); return config; }, error => { console.error('Request Error:', error); return Promise.reject(error); } ); ``` #### 2. 组件渲染问题 ```javascript // 检查 Vue 组件状态 // 1. 安装 Vue DevTools // 2. 检查组件 props 和 data // 3. 查看 computed 属性 // 4. 检查事件监听器 ``` ## 最佳实践 ### 代码组织 1. **模块化开发**: 将功能拆分成独立的模块 2. **组件复用**: 创建可复用的组件库 3. **状态管理**: 合理使用 Pinia 管理应用状态 4. **错误处理**: 统一的错误处理机制 5. **日志记录**: 详细的日志记录便于调试 ### 性能优化 1. **懒加载**: 组件和路由懒加载 2. **缓存策略**: 合理使用缓存提升性能 3. **数据库优化**: 优化查询语句和索引 4. **图片优化**: 压缩图片和使用适当格式 5. **打包优化**: 优化 Webpack/Vite 配置 ### 安全考虑 1. **输入验证**: 严格验证用户输入 2. **权限控制**: 实现细粒度的权限控制 3. **SQL注入防护**: 使用参数化查询 4. **XSS防护**: 过滤和转义用户输入 5. **CSRF防护**: 实现 CSRF Token 机制 ## 工具和资源 ### 开发工具 - **IDE**: VSCode - **API测试**: Postman - **数据库**: MySQL Workbench - **版本控制**: Git - **包管理**: npm/yarn ### 有用的 VSCode 插件 - **Vue Language Features (Volar)**: Vue 3 支持 - **ESLint**: 代码质量检查 - **Prettier**: 代码格式化 - **Auto Rename Tag**: 自动重命名标签 - **Bracket Pair Colorizer**: 括号高亮 - **GitLens**: Git 增强 ### 学习资源 - **Vue.js 官方文档**: https://vuejs.org/ - **Node.js 官方文档**: https://nodejs.org/ - **Sequelize 文档**: https://sequelize.org/ - **Ant Design Vue**: https://antdv.com/ - **ECharts 文档**: https://echarts.apache.org/ --- ## 联系支持 如有开发相关问题,请联系: - **技术支持**: dev-support@nxxmdata.com - **文档反馈**: docs@nxxmdata.com - **Bug 报告**: bugs@nxxmdata.com *最后更新: 2025年1月*