# 编码标准
## 版本信息
| 版本 | 日期 | 描述 | 作者 |
|------|------|------|------|
| 3.0 | 2025-12-26 | 拆分测试策略到独立文档,保留编码标准 | James (Claude Code) |
| 2.5 | 2025-12-26 | 添加Mini UI包开发规范章节 | Bob (Scrum Master) |
| 2.4 | 2025-09-20 | 与主架构文档版本一致 | Winston |
## 现有标准合规性
### 代码风格
- **TypeScript严格模式**: 所有项目必须启用严格类型检查
- **一致的缩进**: 使用2个空格缩进
- **命名约定**:
- 文件名: kebab-case (如: `user.service.ts`)
- 类名: PascalCase (如: `UserService`)
- 函数/变量: camelCase (如: `getUserById`)
- 常量: UPPER_SNAKE_CASE (如: `API_BASE_URL`)
- 接口: PascalCase,无I前缀 (如: `User`)
### Linting规则
- **ESLint**: 已配置ESLint,支持TypeScript和React
- **Prettier**: 统一代码格式化
- **提交前检查**: 使用husky进行pre-commit钩子检查
### 文档风格
- **代码注释**: 关键逻辑必须添加注释说明
- **JSDoc**: 公共API必须包含JSDoc注释
- **README**: 每个包必须有独立的README说明用途和使用方法
## 开发规范引用
### UI包开发
开发Web UI包时,**必须**参考并遵循[UI包开发规范](./ui-package-standards.md),该规范基于史诗008(AllIn UI模块移植)的经验总结。
**关键检查点**:
1. **API路径映射验证**: 开发前必须验证故事中的API路径映射与实际后端路由定义的一致性
2. **类型推断最佳实践**: 必须使用RPC推断类型,而不是直接导入schema类型
3. **测试选择器优化**: 必须为关键交互元素添加`data-testid`属性
4. **表单组件模式**: 必须使用条件渲染两个独立的Form组件
5. **API调用一致性**: 必须根据实际路由名称修正API调用
**常见错误避免**:
- ❌ 不要直接导入schema类型(可能导致Date/string类型不匹配)
- ❌ 不要使用`getByText()`查找可能重复的文本元素
- ❌ 不要在单个Form组件上动态切换props
- ❌ 不要使用故事中描述但实际不存在的路由名称
**参考实现**:
- 广告管理UI包:`packages/advertisement-management-ui`
- 平台管理UI包:`allin-packages/platform-management-ui`
- 渠道管理UI包:`allin-packages/channel-management-ui`(史诗008.002)
### Mini UI包开发
开发Mini UI包(Taro小程序UI包)时,**必须**参考并遵循[Mini UI包开发规范](./mini-ui-package-standards.md),该规范基于史诗011(用人方小程序)和史诗017(人才小程序)的实施经验总结。
**关键检查点**:
#### 1. Taro小程序布局规范
- **View组件默认横向布局**: View容器内的子元素默认是横向布局(`flex-row`),必须显式添加 `flex flex-col` 类才能实现垂直布局
- **Text组件默认内联显示**: Text组件默认是内联显示(类似span),需要使用`flex flex-col`强制垂直排列
**正确示例**:
```typescript
// ✅ 正确: 使用 flex flex-col 实现垂直布局
姓名: 张三
性别: 男
年龄: 35
// ❌ 错误: 缺少 flex flex-col,子元素会横向排列
姓名: 张三
性别: 男
年龄: 35
```
#### 2. 图标使用规范
- **必须使用Heroicons图标类**: 不要使用emoji或文本符号
- **图标类命名格式**: `i-heroicons-{icon-name}-{size}-{style}`
- **必须添加尺寸类**: 如 `w-5 h-5`、`text-lg` 等
**正确示例**:
```typescript
// ✅ 正确: 使用Heroicons图标类
// ❌ 错误: 使用emoji
🔔
👤
←
```
**常用图标**:
- `chevron-left-20-solid` - 左箭头(返回按钮)
- `user-20-solid` - 用户
- `bell-20-solid` - 通知铃
- `document-text-20-solid` - 文档
- `chart-bar-20-solid` - 图表
- `calendar-20-solid` - 日历
- `phone-20-solid` - 电话
- `lock-closed-20-solid` - 锁
- `qr-code-20-solid` - 二维码
#### 3. Navbar导航栏集成规范
- **TabBar页面(一级)**: 使用Navbar无返回按钮(`leftIcon=""`、`leftText=""`)
- **非TabBar页面(二级)**: 使用Navbar带返回按钮(`leftIcon="i-heroicons-chevron-left-20-solid"`)
- **Navbar组件来源**: `@d8d/mini-shared-ui-components/components/navbar`
#### 4. API客户端模式
- **每个UI包独立管理**: 每个Mini UI包包含自己的API客户端和RPC类型
- **使用相对路径导入**: UI包内部必须使用相对路径,不要使用别名
- **RPC推断类型**: 必须使用RPC推断类型,而不是直接导入schema类型
**常见错误避免**:
- ❌ 不要忘记添加 `flex flex-col` 实现垂直布局
- ❌ 不要使用emoji代替Heroicons图标
- ❌ 不要忘记为图标添加尺寸类(`w-5 h-5`、`text-lg`等)
- ❌ 不要在Mini UI包内部导入中使用别名(`@/`、`~/`等)
- ❌ 不要使用Vitest作为Mini项目的测试框架(应使用Jest)
**参考实现**:
- 用人方小程序UI包:`mini-ui-packages/yongren-dashboard-ui`
- 人才小程序UI包:`mini-ui-packages/rencai-dashboard-ui`
- 共享组件包:`mini-ui-packages/mini-shared-ui-components`
### 后端模块包开发
开发后端模块包时,**必须**参考并遵循[后端模块包开发规范](./backend-module-package-standards.md)。
**核心要求**:
1. 模块化架构: entities / services / schemas / routes
2. 依赖注入: 使用构造函数注入
3. 错误处理: 统一的错误处理机制
4. 日志记录: 使用结构化日志
## 类型安全
### TypeScript配置
```json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
}
}
```
### 类型定义
```typescript
// ✅ 推荐: 使用interface定义对象形状
interface User {
id: number;
username: string;
email: string;
createdAt: Date;
}
// ✅ 推荐: 使用type定义联合类型
type Status = 'pending' | 'active' | 'inactive';
// ✅ 推荐: 使用泛型增强类型复用
interface ApiResponse {
status: number;
data: T;
message?: string;
}
```
## 错误处理
### 统一错误处理
```typescript
// 定义自定义错误类
class ValidationError extends Error {
constructor(public errors: Record) {
super('验证失败');
this.name = 'ValidationError';
}
}
// 使用自定义错误
function validateUser(data: unknown): User {
const result = userSchema.safeParse(data);
if (!result.success) {
throw new ValidationError(result.error.flatten().fieldErrors);
}
return result.data;
}
```
### 错误日志
```typescript
import { logger } from '@d8d/shared-utils/logger';
try {
await userService.createUser(userData);
} catch (error) {
logger.error('创建用户失败', {
error: error.message,
stack: error.stack,
userData: JSON.stringify(userData)
});
throw error;
}
```
## 安全最佳实践
### 输入验证
```typescript
// ✅ 使用Schema验证
import { userSchema } from './schemas/user.schema';
const validatedData = await userSchema.parseAsync(inputData);
// ❌ 不要直接信任用户输入
const user = { username: req.body.username }; // 不安全
```
### 敏感数据处理
```typescript
// ✅ 从响应中排除敏感字段
function sanitizeUser(user: User): Partial {
const { password, ...sanitized } = user;
return sanitized;
}
// ✅ 日志中不记录敏感信息
logger.info('用户登录', { userId: user.id }); // 正确
logger.info('用户登录', { user }); // 错误 - 会记录密码
```
### SQL注入防护
```typescript
// ✅ 使用TypeORM参数化查询
const users = await userRepo.find({
where: { username: username }
});
// ❌ 不要拼接SQL字符串
const query = `SELECT * FROM users WHERE username = '${username}'`; // 危险
```
## 性能优化
### 数据库查询优化
```typescript
// ✅ 只查询需要的字段
const users = await userRepo.find({
select: ['id', 'username', 'email']
});
// ✅ 使用索引字段查询
const user = await userRepo.findOne({
where: { email: userEmail } // email字段应有索引
});
// ❌ 避免N+1查询
const orders = await orderRepo.find({
relations: ['user', 'products'] // 使用join而不是循环查询
});
```
### 缓存策略
```typescript
// ✅ 使用Redis缓存
import { cacheGet, cacheSet } from '@d8d/shared-utils/redis.util';
async function getUserById(id: number) {
const cached = await cacheGet(`user:${id}`);
if (cached) return JSON.parse(cached);
const user = await userRepo.findOne({ where: { id } });
await cacheSet(`user:${id}`, JSON.stringify(user), 3600);
return user;
}
```
## 代码组织
### 文件结构
```
packages/user-module/
├── src/
│ ├── entities/ # 数据实体
│ ├── services/ # 业务逻辑
│ ├── schemas/ # 验证Schema
│ ├── routes/ # API路由
│ ├── middleware/ # 中间件
│ ├── utils/ # 工具函数
│ └── index.ts # 包入口
├── tests/ # 测试文件
├── README.md # 包说明
└── package.json
```
### 导出规范
```typescript
// index.ts - 统一导出
export * from './entities';
export * from './services';
export { userRoutes } from './routes';
export { userSchema } from './schemas';
```
## 相关文档
### 测试规范
- [测试策略概述](./testing-strategy.md)
- [Web UI包测试规范](./web-ui-testing-standards.md)
- [Web Server包测试规范](./web-server-testing-standards.md)
- [后端模块包测试规范](./backend-module-testing-standards.md)
- [Mini UI包测试规范](./mini-ui-testing-standards.md)
### 开发规范
- [UI包开发规范](./ui-package-standards.md)
- [Mini UI包开发规范](./mini-ui-package-standards.md)
- [后端模块包开发规范](./backend-module-package-standards.md)
- [API设计规范](./api-design-integration.md)
---
**文档状态**: 正式版
**下次评审**: 2026-01-26