user.entity.ts 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable, CreateDateColumn, UpdateDateColumn, OneToMany } from 'typeorm';
  2. import { Role, RoleSchema } from './role.entity';
  3. import { z } from '@hono/zod-openapi';
  4. import { DeleteStatus, DisabledStatus } from '@/share/types';
  5. import { UserType } from './user.enum';
  6. @Entity({ name: 'users' })
  7. export class UserEntity {
  8. @PrimaryGeneratedColumn({ unsigned: true, comment: '用户ID' })
  9. id!: number;
  10. @Column({ name: 'username', type: 'varchar', length: 255, unique: true, comment: '用户名' })
  11. username!: string;
  12. @Column({ name: 'password', type: 'varchar', length: 255, comment: '密码' })
  13. password!: string;
  14. @Column({ name: 'phone', type: 'varchar', length: 255, nullable: true, comment: '手机号' })
  15. phone!: string | null;
  16. @Column({ name: 'email', type: 'varchar', length: 255, nullable: true, comment: '邮箱' })
  17. email!: string | null;
  18. @Column({ name: 'nickname', type: 'varchar', length: 255, nullable: true, comment: '昵称' })
  19. nickname!: string | null;
  20. @Column({ name: 'name', type: 'varchar', length: 255, nullable: true, comment: '真实姓名' })
  21. name!: string | null;
  22. @Column({ name: 'avatar', type: 'varchar', length: 255, nullable: true, comment: '头像' })
  23. avatar!: string | null;
  24. @Column({ name: 'is_disabled', type: 'int', default: DisabledStatus.ENABLED, comment: '是否禁用(0:启用,1:禁用)' })
  25. isDisabled!: DisabledStatus;
  26. @Column({ name: 'is_deleted', type: 'int', default: DeleteStatus.NOT_DELETED, comment: '是否删除(0:未删除,1:已删除)' })
  27. isDeleted!: DeleteStatus;
  28. @Column({
  29. name: 'user_type',
  30. type: 'enum',
  31. enum: UserType,
  32. default: UserType.STUDENT,
  33. comment: '用户类型(teacher:老师,student:学生)'
  34. })
  35. userType!: UserType;
  36. @ManyToMany(() => Role)
  37. @JoinTable()
  38. roles!: Role[];
  39. @CreateDateColumn({ name: 'created_at', type: 'timestamp' })
  40. createdAt!: Date;
  41. @UpdateDateColumn({ name: 'updated_at', type: 'timestamp' })
  42. updatedAt!: Date;
  43. constructor(partial?: Partial<UserEntity>) {
  44. Object.assign(this, partial);
  45. }
  46. }
  47. export const UserSchema = z.object({
  48. id: z.number().int().positive().openapi({ description: '用户ID' }),
  49. username: z.string().min(3).max(255).openapi({
  50. example: 'admin',
  51. description: '用户名,3-255个字符'
  52. }),
  53. password: z.string().min(6).max(255).openapi({
  54. example: 'password123',
  55. description: '密码,最少6位'
  56. }),
  57. phone: z.string().max(255).nullable().openapi({
  58. example: '13800138000',
  59. description: '手机号'
  60. }),
  61. email: z.string().email().max(255).nullable().openapi({
  62. example: 'user@example.com',
  63. description: '邮箱'
  64. }),
  65. nickname: z.string().max(255).nullable().openapi({
  66. example: '昵称',
  67. description: '用户昵称'
  68. }),
  69. name: z.string().max(255).nullable().openapi({
  70. example: '张三',
  71. description: '真实姓名'
  72. }),
  73. avatar: z.string().max(255).nullable().openapi({
  74. example: 'https://example.com/avatar.jpg',
  75. description: '用户头像'
  76. }),
  77. isDisabled: z.number().int().min(0).max(1).default(DisabledStatus.ENABLED).openapi({
  78. example: DisabledStatus.ENABLED,
  79. description: '是否禁用(0:启用,1:禁用)'
  80. }),
  81. isDeleted: z.number().int().min(0).max(1).default(DeleteStatus.NOT_DELETED).openapi({
  82. example: DeleteStatus.NOT_DELETED,
  83. description: '是否删除(0:未删除,1:已删除)'
  84. }),
  85. roles: z.array(RoleSchema).optional().openapi({
  86. example: [
  87. { id: 1, name: 'admin',description:'管理员', permissions: ['user:create'] ,createdAt: new Date(), updatedAt: new Date() }
  88. ],
  89. description: '用户角色列表'
  90. }),
  91. userType: z.enum([UserType.TEACHER, UserType.STUDENT]).default(UserType.STUDENT).openapi({
  92. example: UserType.STUDENT,
  93. description: '用户类型(teacher:老师,student:学生)'
  94. }),
  95. createdAt: z.date().openapi({ description: '创建时间' }),
  96. updatedAt: z.date().openapi({ description: '更新时间' })
  97. });
  98. export const CreateUserDto = z.object({
  99. username: z.string().min(3).max(255).openapi({
  100. example: 'admin',
  101. description: '用户名,3-255个字符'
  102. }),
  103. password: z.string().min(6).max(255).openapi({
  104. example: 'password123',
  105. description: '密码,最少6位'
  106. }),
  107. phone: z.string().max(255).nullable().optional().openapi({
  108. example: '13800138000',
  109. description: '手机号'
  110. }),
  111. email: z.string().email().max(255).nullable().optional().openapi({
  112. example: 'user@example.com',
  113. description: '邮箱'
  114. }),
  115. nickname: z.string().max(255).nullable().optional().openapi({
  116. example: '昵称',
  117. description: '用户昵称'
  118. }),
  119. name: z.string().max(255).nullable().optional().openapi({
  120. example: '张三',
  121. description: '真实姓名'
  122. }),
  123. avatar: z.string().max(255).nullable().optional().openapi({
  124. example: 'https://example.com/avatar.jpg',
  125. description: '用户头像'
  126. }),
  127. isDisabled: z.number().int().min(0).max(1).default(DisabledStatus.ENABLED).openapi({
  128. example: DisabledStatus.ENABLED,
  129. description: '是否禁用(0:启用,1:禁用)'
  130. }),
  131. userType: z.enum([UserType.TEACHER, UserType.STUDENT]).default(UserType.STUDENT).openapi({
  132. example: UserType.STUDENT,
  133. description: '用户类型(teacher:老师,student:学生)'
  134. }),
  135. createdAt: z.date().openapi({ description: '创建时间' }),
  136. updatedAt: z.date().openapi({ description: '更新时间' })
  137. });
  138. export const UpdateUserDto = z.object({
  139. username: z.string().min(3).max(255).optional().openapi({
  140. example: 'admin',
  141. description: '用户名,3-255个字符'
  142. }),
  143. password: z.string().min(6).max(255).optional().openapi({
  144. example: 'password123',
  145. description: '密码,最少6位'
  146. }),
  147. phone: z.string().max(255).nullable().optional().openapi({
  148. example: '13800138000',
  149. description: '手机号'
  150. }),
  151. email: z.string().email().max(255).nullable().optional().openapi({
  152. example: 'user@example.com',
  153. description: '邮箱'
  154. }),
  155. nickname: z.string().max(255).nullable().optional().openapi({
  156. example: '昵称',
  157. description: '用户昵称'
  158. }),
  159. name: z.string().max(255).nullable().optional().openapi({
  160. example: '张三',
  161. description: '真实姓名'
  162. }),
  163. avatar: z.string().max(255).nullable().optional().openapi({
  164. example: 'https://example.com/avatar.jpg',
  165. description: '用户头像'
  166. }),
  167. isDisabled: z.number().int().min(0).max(1).optional().openapi({
  168. example: DisabledStatus.ENABLED,
  169. description: '是否禁用(0:启用,1:禁用)'
  170. }),
  171. userType: z.enum([UserType.TEACHER, UserType.STUDENT]).optional().openapi({
  172. example: UserType.STUDENT,
  173. description: '用户类型(teacher:老师,student:学生)'
  174. })
  175. });