# 通用CRUD操作人ID字段配置规范

## 概述

本规范定义了如何在通用CRUD模块中自动处理操作人ID字段，确保创建和更新操作时自动记录操作用户信息。

## 新增功能

通用CRUD模块已支持自动注入操作人ID字段，包含以下功能：

1. **创建时自动记录创建人ID**
2. **更新时自动记录更新人ID**
3. **灵活配置字段名称**
4. **向后兼容现有实现**

## 配置方式

### 1. 在CrudOptions中配置用户跟踪

```typescript
import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
import { YourEntity } from '@d8d/server/modules/your-module/your-entity.entity';
import { YourEntitySchema, CreateYourEntityDto, UpdateYourEntityDto } from '@d8d/server/modules/your-module/your-entity.entity';
import { authMiddleware } from '@/server/middleware/auth.middleware';

const yourEntityRoutes = createCrudRoutes({
  entity: YourEntity,
  createSchema: CreateYourEntityDto,
  updateSchema: UpdateYourEntityDto,
  getSchema: YourEntitySchema,
  listSchema: YourEntitySchema,
  middleware: [authMiddleware],
  // 用户跟踪配置
  userTracking: {
    createdByField: 'createdBy',    // 创建人ID字段名，默认 'createdBy'
    updatedByField: 'updatedBy'     // 更新人ID字段名，默认 'updatedBy'
  }
});
```

### 2. 实体类定义要求

实体必须包含与配置对应的字段：

```typescript
@Entity('your_entities')
export class YourEntity {
  @PrimaryGeneratedColumn({ unsigned: true })
  id!: number;

  // 业务字段...
  
  @Column({ name: 'created_by', type: 'int', nullable: true, comment: '创建用户ID' })
  createdBy?: number;
  
  @Column({ name: 'updated_by', type: 'int', nullable: true, comment: '更新用户ID' })
  updatedBy?: number;
  
  @CreateDateColumn({ name: 'created_at' })
  createdAt!: Date;
  
  @UpdateDateColumn({ name: 'updated_at' })
  updatedAt!: Date;
}
```

### 3. 字段命名约定

| 配置字段名 | 推荐数据库字段名 | 类型 | 说明 |
|------------|------------------|------|------|
| createdByField | created_by | int/string | 创建人用户ID |
| updatedByField | updated_by | int/string | 更新人用户ID |

## 配置示例

### 示例1：使用默认字段名

```typescript
const routes = createCrudRoutes({
  entity: MyEntity,
  createSchema: CreateMyEntityDto,
  updateSchema: UpdateMyEntityDto,
  getSchema: MyEntitySchema,
  listSchema: MyEntitySchema,
  userTracking: {} // 使用默认字段名 createdBy 和 updatedBy
});
```

### 示例2：自定义字段名

```typescript
const routes = createCrudRoutes({
  entity: MyEntity,
  createSchema: CreateMyEntityDto,
  updateSchema: UpdateMyEntityDto,
  getSchema: MyEntitySchema,
  listSchema: MyEntitySchema,
  userTracking: {
    createdByField: 'created_user_id',
    updatedByField: 'modified_user_id'
  }
});
```

### 示例3：只记录创建人

```typescript
const routes = createCrudRoutes({
  entity: MyEntity,
  createSchema: CreateMyEntityDto,
  updateSchema: UpdateMyEntityDto,
  getSchema: MyEntitySchema,
  listSchema: MyEntitySchema,
  userTracking: {
    createdByField: 'created_by',
    updatedByField: undefined // 不记录更新人
  }
});
```

### 示例4：兼容现有字段名

```typescript
const routes = createCrudRoutes({
  entity: Linkman,
  createSchema: CreateLinkmanDto,
  updateSchema: UpdateLinkmanDto,
  getSchema: LinkmanSchema,
  listSchema: LinkmanSchema,
  userTracking: {
    createdByField: 'createdUserId', // 匹配现有字段
    updatedByField: 'updatedUserId'  // 匹配现有字段
  }
});
```

## 工作原理

1. **创建操作**：
   - 当用户创建新记录时，系统自动从认证上下文中提取用户ID
   - 将用户ID注入到配置的创建人字段中
   - 如果未配置createdByField，则跳过此步骤

2. **更新操作**：
   - 当用户更新记录时，系统自动从认证上下文中提取用户ID
   - 将用户ID注入到配置的更新人字段中
   - 如果未配置updatedByField，则跳过此步骤

3. **向后兼容**：
   - 未配置userTracking时，保持原有行为不变
   - 所有现有代码无需修改即可继续运行

## 注意事项

1. **认证要求**：必须在路由中添加`authMiddleware`才能获取用户信息
2. **字段类型**：用户ID字段应支持存储用户ID的数据类型（通常为int或varchar）
3. **数据库字段**：确保实体类中定义的数据库字段名与配置一致
4. **空值处理**：如果用户未登录，相关字段将保持为null

## 最佳实践

1. **统一命名**：在项目中统一使用相同的字段命名约定
2. **索引优化**：为操作人ID字段添加数据库索引以提高查询性能
3. **关联查询**：可以通过relations配置加载操作人详情
4. **审计功能**：结合时间戳字段实现完整的操作审计

## 常见问题

### Q: 如何支持字符串类型的用户ID？
A: 实体类字段类型设置为varchar即可，系统会自动处理字符串类型

### Q: 可以配置不同的用户ID字段吗？
A: 可以，通过createdByField和updatedByField分别配置

### Q: 会影响现有实体吗？
A: 不会，只有配置了userTracking的实体才会启用此功能

### Q: 如何获取操作人详情？
A: 在relations中配置用户关联关系即可：
```typescript
const routes = createCrudRoutes({
  entity: YourEntity,
  relations: ['createdByUser', 'updatedByUser'],
  // ...其他配置
});