|
|
@@ -0,0 +1,185 @@
|
|
|
+# 通用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 '@/server/modules/your-module/your-entity.entity';
|
|
|
+import { YourEntitySchema, CreateYourEntityDto, UpdateYourEntityDto } from '@/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'],
|
|
|
+ // ...其他配置
|
|
|
+});
|