Files
nxxmdata/docs/development/代码规范.md
2025-09-19 23:46:15 +08:00

11 KiB
Raw Blame History

宁夏智慧养殖监管平台代码规范

版本历史

版本 日期 修改内容 修改人
v1.0 2024-01-20 初始版本,制定基础代码规范 开发团队

1. 概述

本文档规定了宁夏智慧养殖监管平台项目的代码编写规范,旨在提高代码质量、可读性和可维护性。

2. 通用规范

2.1 文件命名

  • 文件名: 使用小写字母和连字符,如 user-service.js
  • 目录名: 使用小写字母和连字符,如 user-management
  • 组件文件: 使用 PascalCaseUserProfile.vue

2.2 编码格式

  • 字符编码: UTF-8
  • 换行符: LF (Unix)
  • 缩进: 2个空格
  • 行尾: 不允许有多余空格

2.3 注释规范

/**
 * 函数功能描述
 * @param {string} param1 - 参数1描述
 * @param {number} param2 - 参数2描述
 * @returns {boolean} 返回值描述
 * @author 作者名
 * @since 版本号
 */
function exampleFunction(param1, param2) {
  // 单行注释说明
  return true;
}

3. JavaScript/Node.js 规范

3.1 变量命名

// 使用 camelCase
const userName = 'admin';
const userAge = 25;

// 常量使用 UPPER_SNAKE_CASE
const MAX_RETRY_COUNT = 3;
const API_BASE_URL = 'https://api.example.com';

// 私有变量使用下划线前缀
const _privateVariable = 'private';

3.2 函数定义

// 优先使用箭头函数
const getUserInfo = (userId) => {
  return userService.findById(userId);
};

// 异步函数
const fetchUserData = async (userId) => {
  try {
    const user = await userService.findById(userId);
    return user;
  } catch (error) {
    logger.error('获取用户数据失败', error);
    throw error;
  }
};

3.3 对象和数组

// 对象属性换行
const userConfig = {
  name: 'admin',
  role: 'administrator',
  permissions: ['read', 'write', 'delete'],
  settings: {
    theme: 'dark',
    language: 'zh-CN'
  }
};

// 数组解构
const [first, second, ...rest] = items;

// 对象解构
const { name, age, ...otherProps } = user;

3.4 错误处理

// 统一错误处理
const handleApiError = (error) => {
  if (error.response) {
    // 服务器响应错误
    logger.error('API响应错误', {
      status: error.response.status,
      data: error.response.data
    });
  } else if (error.request) {
    // 请求发送失败
    logger.error('请求发送失败', error.request);
  } else {
    // 其他错误
    logger.error('未知错误', error.message);
  }
  throw error;
};

4. Vue.js 规范

4.1 组件命名

// 组件名使用 PascalCase
export default {
  name: 'UserProfile',
  // ...
}

// 文件名: UserProfile.vue

4.2 组件结构

<template>
  <div class="user-profile">
    <!-- 模板内容 -->
  </div>
</template>

<script>
import { ref, computed, onMounted } from 'vue'

export default {
  name: 'UserProfile',
  props: {
    userId: {
      type: String,
      required: true
    }
  },
  emits: ['update', 'delete'],
  setup(props, { emit }) {
    // 响应式数据
    const user = ref(null)
    
    // 计算属性
    const displayName = computed(() => {
      return user.value ? user.value.name : '未知用户'
    })
    
    // 方法
    const loadUser = async () => {
      try {
        user.value = await userApi.getById(props.userId)
      } catch (error) {
        console.error('加载用户失败', error)
      }
    }
    
    // 生命周期
    onMounted(() => {
      loadUser()
    })
    
    return {
      user,
      displayName,
      loadUser
    }
  }
}
</script>

<style scoped>
.user-profile {
  padding: 16px;
}
</style>

4.3 Props 定义

props: {
  // 基础类型检查
  title: String,
  count: Number,
  isActive: Boolean,
  
  // 复杂类型检查
  user: {
    type: Object,
    required: true,
    validator: (value) => {
      return value && typeof value.id === 'string'
    }
  },
  
  // 带默认值
  size: {
    type: String,
    default: 'medium',
    validator: (value) => {
      return ['small', 'medium', 'large'].includes(value)
    }
  }
}

4.4 事件命名

// 使用 kebab-case
this.$emit('user-updated', userData)
this.$emit('form-submitted', formData)

// 在模板中
<UserForm @user-updated="handleUserUpdate" />

5. CSS/SCSS 规范

5.1 类名命名

/* 使用 BEM 命名法 */
.user-profile {
  /* 块 */
}

.user-profile__header {
  /* 元素 */
}

.user-profile__header--large {
  /* 修饰符 */
}

.user-profile__avatar {
  /* 元素 */
}

.user-profile__avatar--round {
  /* 修饰符 */
}

5.2 样式组织

// 变量定义
$primary-color: #1890ff;
$success-color: #52c41a;
$warning-color: #faad14;
$error-color: #f5222d;

// 混入定义
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

// 组件样式
.user-profile {
  padding: 16px;
  border-radius: 4px;
  background-color: #fff;
  
  &__header {
    @include flex-center;
    margin-bottom: 16px;
    font-size: 18px;
    font-weight: 600;
  }
  
  &__content {
    line-height: 1.6;
  }
}

6. API 接口规范

6.1 接口命名

// RESTful API 命名
GET    /api/users          // 获取用户列表
GET    /api/users/:id      // 获取单个用户
POST   /api/users          // 创建用户
PUT    /api/users/:id      // 更新用户
DELETE /api/users/:id      // 删除用户

// 复杂操作使用动词
POST   /api/users/:id/reset-password  // 重置密码
POST   /api/users/:id/change-status   // 更改状态

6.2 请求响应格式

// 统一响应格式
{
  "code": 200,
  "message": "操作成功",
  "data": {
    // 具体数据
  },
  "timestamp": "2024-01-20T10:30:00Z"
}

// 分页响应格式
{
  "code": 200,
  "message": "获取成功",
  "data": {
    "list": [...],
    "pagination": {
      "current": 1,
      "pageSize": 10,
      "total": 100,
      "totalPages": 10
    }
  }
}

// 错误响应格式
{
  "code": 400,
  "message": "参数错误",
  "error": {
    "field": "email",
    "reason": "邮箱格式不正确"
  },
  "timestamp": "2024-01-20T10:30:00Z"
}

7. 数据库规范

7.1 表命名

-- 表名使用复数形式,下划线分隔
users
farm_devices
alert_records
user_roles

-- 关联表使用两个表名组合
user_farm_bindings
device_alert_configs

7.2 字段命名

-- 字段名使用下划线分隔
CREATE TABLE users (
  id VARCHAR(36) PRIMARY KEY,
  user_name VARCHAR(50) NOT NULL,
  email VARCHAR(100) UNIQUE,
  phone_number VARCHAR(20),
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  is_active BOOLEAN DEFAULT TRUE
);

8. Git 提交规范

8.1 提交信息格式

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

<body>

<footer>

8.2 类型说明

  • feat: 新功能
  • fix: 修复bug
  • docs: 文档更新
  • style: 代码格式调整
  • refactor: 代码重构
  • test: 测试相关
  • chore: 构建过程或辅助工具的变动

8.3 提交示例

feat(user): 添加用户头像上传功能

- 支持jpg、png格式图片上传
- 添加图片压缩和裁剪功能
- 更新用户资料页面UI

Closes #123

9. 测试规范

9.1 单元测试

// 测试文件命名: *.test.js 或 *.spec.js
describe('UserService', () => {
  describe('getUserById', () => {
    it('应该返回正确的用户信息', async () => {
      // Arrange
      const userId = '123';
      const expectedUser = { id: '123', name: 'Test User' };
      
      // Act
      const result = await userService.getUserById(userId);
      
      // Assert
      expect(result).toEqual(expectedUser);
    });
    
    it('用户不存在时应该抛出错误', async () => {
      // Arrange
      const userId = 'nonexistent';
      
      // Act & Assert
      await expect(userService.getUserById(userId))
        .rejects.toThrow('用户不存在');
    });
  });
});

9.2 集成测试

describe('User API', () => {
  beforeEach(async () => {
    await setupTestDatabase();
  });
  
  afterEach(async () => {
    await cleanupTestDatabase();
  });
  
  it('POST /api/users 应该创建新用户', async () => {
    const userData = {
      name: 'Test User',
      email: 'test@example.com'
    };
    
    const response = await request(app)
      .post('/api/users')
      .send(userData)
      .expect(201);
    
    expect(response.body.data).toMatchObject(userData);
  });
});

10. 性能优化规范

10.1 前端优化

// 懒加载组件
const UserProfile = () => import('./components/UserProfile.vue');

// 防抖处理
import { debounce } from 'lodash-es';

const handleSearch = debounce((keyword) => {
  // 搜索逻辑
}, 300);

// 虚拟滚动
<VirtualList
  :items="largeDataSet"
  :item-height="50"
  :visible-count="10"
/>

10.2 后端优化

// 数据库查询优化
const users = await User.findAll({
  attributes: ['id', 'name', 'email'], // 只查询需要的字段
  include: [{
    model: Role,
    attributes: ['name']
  }],
  limit: 10,
  offset: (page - 1) * 10
});

// 缓存使用
const cacheKey = `user:${userId}`;
let user = await redis.get(cacheKey);

if (!user) {
  user = await User.findById(userId);
  await redis.setex(cacheKey, 3600, JSON.stringify(user));
} else {
  user = JSON.parse(user);
}

11. 安全规范

11.1 输入验证

// 使用验证库
const Joi = require('joi');

const userSchema = Joi.object({
  name: Joi.string().min(2).max(50).required(),
  email: Joi.string().email().required(),
  password: Joi.string().min(8).pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
});

const { error, value } = userSchema.validate(req.body);
if (error) {
  return res.status(400).json({ message: error.details[0].message });
}

11.2 SQL 注入防护

// 使用参数化查询
const user = await User.findOne({
  where: {
    email: req.body.email // Sequelize 自动转义
  }
});

// 原生查询使用占位符
const result = await sequelize.query(
  'SELECT * FROM users WHERE email = ?',
  {
    replacements: [email],
    type: QueryTypes.SELECT
  }
);

12. 代码审查清单

12.1 功能性检查

  • 功能是否按需求实现
  • 边界条件是否处理
  • 错误处理是否完善
  • 性能是否满足要求

12.2 代码质量检查

  • 命名是否清晰明确
  • 代码结构是否合理
  • 是否有重复代码
  • 注释是否充分

12.3 安全性检查

  • 输入验证是否完整
  • 权限控制是否正确
  • 敏感信息是否泄露
  • SQL注入防护是否到位

13. 工具配置

13.1 ESLint 配置

// .eslintrc.js
module.exports = {
  extends: [
    'eslint:recommended',
    '@vue/eslint-config-prettier'
  ],
  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'
  }
};

13.2 Prettier 配置

// .prettierrc.js
module.exports = {
  semi: true,
  singleQuote: true,
  tabWidth: 2,
  trailingComma: 'es5',
  printWidth: 80,
  endOfLine: 'lf'
};

注意: 本规范会根据项目发展持续更新,请团队成员定期查看最新版本。