user.schema.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { z } from '@hono/zod-openapi';
  2. import { DeleteStatus, DisabledStatus } from '@/share/types';
  3. import { RoleSchema } from './role.schema';
  4. // import { FileSchema } from '@/server/modules/files/file.schema';
  5. // 基础用户 schema(包含所有字段)
  6. export const UserSchema = z.object({
  7. id: z.number().int().positive().openapi({ description: '用户ID' }),
  8. username: z.string().min(3, '用户名至少3个字符').max(255, '用户名最多255个字符').openapi({
  9. example: 'admin',
  10. description: '用户名,3-255个字符'
  11. }),
  12. password: z.string().min(6, '密码至少6位').max(255, '密码最多255位').openapi({
  13. example: 'password123',
  14. description: '密码,最少6位'
  15. }),
  16. phone: z.string().max(255, '手机号最多255个字符').nullable().openapi({
  17. example: '13800138000',
  18. description: '手机号'
  19. }),
  20. email: z.email('请输入正确的邮箱格式').max(255, '邮箱最多255个字符').nullable().openapi({
  21. example: 'user@example.com',
  22. description: '邮箱'
  23. }),
  24. nickname: z.string().max(255, '昵称最多255个字符').nullable().openapi({
  25. example: '昵称',
  26. description: '用户昵称'
  27. }),
  28. name: z.string().max(255, '姓名最多255个字符').nullable().openapi({
  29. example: '张三',
  30. description: '真实姓名'
  31. }),
  32. avatarFileId: z.number().int().positive().nullable().openapi({
  33. example: 1,
  34. description: '头像文件ID'
  35. }),
  36. avatarFile: z.object({
  37. id: z.number().int().positive().openapi({ description: '文件ID' }),
  38. name: z.string().max(255).openapi({ description: '文件名', example: 'avatar.jpg' }),
  39. fullUrl: z.string().openapi({ description: '文件完整URL', example: 'https://example.com/avatar.jpg' }),
  40. type: z.string().nullable().openapi({ description: '文件类型', example: 'image/jpeg' }),
  41. size: z.number().nullable().openapi({ description: '文件大小(字节)', example: 102400 })
  42. }).nullable().optional().openapi({
  43. description: '头像文件信息'
  44. }),
  45. isDisabled: z.number().int().min(0).max(1).default(DisabledStatus.ENABLED).openapi({
  46. example: DisabledStatus.ENABLED,
  47. description: '是否禁用(0:启用,1:禁用)'
  48. }),
  49. isDeleted: z.number().int().min(0).max(1).default(DeleteStatus.NOT_DELETED).openapi({
  50. example: DeleteStatus.NOT_DELETED,
  51. description: '是否删除(0:未删除,1:已删除)'
  52. }),
  53. roles: z.array(RoleSchema).optional().openapi({
  54. example: [
  55. {
  56. id: 1,
  57. name: 'admin',
  58. description: '管理员',
  59. permissions: ['user:create'],
  60. createdAt: new Date(),
  61. updatedAt: new Date()
  62. }
  63. ],
  64. description: '用户角色列表'
  65. }),
  66. createdAt: z.coerce.date().openapi({ description: '创建时间' }),
  67. updatedAt: z.coerce.date().openapi({ description: '更新时间' })
  68. });
  69. // 创建用户请求 schema
  70. export const CreateUserDto = z.object({
  71. username: z.string().min(3, '用户名至少3个字符').max(255, '用户名最多255个字符').openapi({
  72. example: 'admin',
  73. description: '用户名,3-255个字符'
  74. }),
  75. password: z.string().min(6, '密码至少6位').max(255, '密码最多255位').openapi({
  76. example: 'password123',
  77. description: '密码,最少6位'
  78. }),
  79. phone: z.string().max(255, '手机号最多255个字符').nullable().optional().openapi({
  80. example: '13800138000',
  81. description: '手机号'
  82. }),
  83. email: z.email('请输入正确的邮箱格式').max(255, '邮箱最多255个字符').nullable().optional().openapi({
  84. example: 'user@example.com',
  85. description: '邮箱'
  86. }),
  87. nickname: z.string().max(255, '昵称最多255个字符').nullable().optional().openapi({
  88. example: '昵称',
  89. description: '用户昵称'
  90. }),
  91. name: z.string().max(255, '姓名最多255个字符').nullable().optional().openapi({
  92. example: '张三',
  93. description: '真实姓名'
  94. }),
  95. avatarFileId: z.number().int().positive().nullable().optional().openapi({
  96. example: 1,
  97. description: '头像文件ID'
  98. }),
  99. isDisabled: z.number().int().min(0, '状态值只能是0或1').max(1, '状态值只能是0或1').default(DisabledStatus.ENABLED).optional().openapi({
  100. example: DisabledStatus.ENABLED,
  101. description: '是否禁用(0:启用,1:禁用)'
  102. })
  103. });
  104. // 更新用户请求 schema
  105. export const UpdateUserDto = z.object({
  106. username: z.string().min(3, '用户名至少3个字符').max(255, '用户名最多255个字符').optional().openapi({
  107. example: 'admin',
  108. description: '用户名,3-255个字符'
  109. }),
  110. password: z.string().min(6, '密码至少6位').max(255, '密码最多255位').optional().openapi({
  111. example: 'password123',
  112. description: '密码,最少6位'
  113. }),
  114. phone: z.string().max(255, '手机号最多255个字符').nullable().optional().openapi({
  115. example: '13800138000',
  116. description: '手机号'
  117. }),
  118. email: z.email('请输入正确的邮箱格式').max(255, '邮箱最多255个字符').nullable().optional().openapi({
  119. example: 'user@example.com',
  120. description: '邮箱'
  121. }),
  122. nickname: z.string().max(255, '昵称最多255个字符').nullable().optional().openapi({
  123. example: '昵称',
  124. description: '用户昵称'
  125. }),
  126. name: z.string().max(255, '姓名最多255个字符').nullable().optional().openapi({
  127. example: '张三',
  128. description: '真实姓名'
  129. }),
  130. avatarFileId: z.number().int().positive().nullable().optional().openapi({
  131. example: 1,
  132. description: '头像文件ID'
  133. }),
  134. isDisabled: z.number().int().min(0, '状态值只能是0或1').max(1, '状态值只能是0或1').optional().openapi({
  135. example: DisabledStatus.ENABLED,
  136. description: '是否禁用(0:启用,1:禁用)'
  137. })
  138. });
  139. // 用户列表响应 schema
  140. export const UserListResponse = z.object({
  141. data: z.array(UserSchema),
  142. pagination: z.object({
  143. total: z.number().openapi({
  144. example: 100,
  145. description: '总记录数'
  146. }),
  147. current: z.number().openapi({
  148. example: 1,
  149. description: '当前页码'
  150. }),
  151. pageSize: z.number().openapi({
  152. example: 10,
  153. description: '每页数量'
  154. })
  155. })
  156. });
  157. // 类型导出
  158. export type User = z.infer<typeof UserSchema>;
  159. export type CreateUserRequest = z.infer<typeof CreateUserDto>;
  160. export type UpdateUserRequest = z.infer<typeof UpdateUserDto>;
  161. export type UserListResponseType = z.infer<typeof UserListResponse>;