area.schema.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import { z } from 'zod';
  2. import { DisabledStatus } from '../../share/types';
  3. import { AreaLevel } from './area.entity';
  4. // 省市区创建Schema
  5. export const createAreaSchema = z.object({
  6. parentId: z.number().int().min(0, '父级ID不能为负数').default(0),
  7. name: z.string().min(1, '区域名称不能为空').max(100, '区域名称不能超过100个字符'),
  8. level: z.nativeEnum(AreaLevel, {
  9. message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
  10. }),
  11. code: z.string().min(1, '行政区划代码不能为空').max(20, '行政区划代码不能超过20个字符'),
  12. isDisabled: z.nativeEnum(DisabledStatus).default(DisabledStatus.ENABLED),
  13. }).refine((data) => {
  14. // 验证层级和父级ID的关系
  15. if (data.level === AreaLevel.PROVINCE && data.parentId !== 0) {
  16. return false;
  17. }
  18. if (data.level !== AreaLevel.PROVINCE && data.parentId === 0) {
  19. return false;
  20. }
  21. return true;
  22. }, {
  23. message: '层级和父级ID关系不正确:省/直辖市(parentId=0),市/区县(parentId>0)',
  24. path: ['parentId'],
  25. });
  26. // 省市区更新Schema
  27. export const updateAreaSchema = z.object({
  28. parentId: z.number().int().min(0, '父级ID不能为负数').optional(),
  29. name: z.string().min(1, '区域名称不能为空').max(100, '区域名称不能超过100个字符').optional(),
  30. level: z.nativeEnum(AreaLevel, {
  31. message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
  32. }).optional(),
  33. code: z.string().min(1, '行政区划代码不能为空').max(20, '行政区划代码不能超过20个字符').optional(),
  34. isDisabled: z.nativeEnum(DisabledStatus).optional(),
  35. }).refine((data) => {
  36. // 验证层级和父级ID的关系
  37. if (data.level && data.parentId !== undefined) {
  38. if (data.level === AreaLevel.PROVINCE && data.parentId !== 0) {
  39. return false;
  40. }
  41. if (data.level !== AreaLevel.PROVINCE && data.parentId === 0) {
  42. return false;
  43. }
  44. }
  45. return true;
  46. }, {
  47. message: '层级和父级ID关系不正确:省/直辖市(parentId=0),市/区县(parentId>0)',
  48. path: ['parentId'],
  49. });
  50. // 省市区获取Schema
  51. export const getAreaSchema = z.object({
  52. id: z.number().int().positive('ID必须为正整数'),
  53. parentId: z.number().int().min(0, '父级ID不能为负数'),
  54. name: z.string().min(1, '区域名称不能为空').max(100, '区域名称不能超过100个字符'),
  55. level: z.nativeEnum(AreaLevel, {
  56. message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
  57. }),
  58. code: z.string().min(1, '行政区划代码不能为空').max(20, '行政区划代码不能超过20个字符'),
  59. isDisabled: z.nativeEnum(DisabledStatus),
  60. isDeleted: z.number().int(),
  61. createdAt: z.coerce.date(),
  62. updatedAt: z.coerce.date(),
  63. createdBy: z.number().int().nullable(),
  64. updatedBy: z.number().int().nullable(),
  65. });
  66. // 省市区列表查询Schema
  67. export const listAreasSchema = z.object({
  68. keyword: z.string().optional(),
  69. level: z.nativeEnum(AreaLevel).optional(),
  70. parentId: z.coerce.number().int().min(0).optional(),
  71. isDisabled: z.coerce.number().int().optional(),
  72. page: z.coerce.number().int().min(1).default(1),
  73. pageSize: z.coerce.number().int().min(1).max(100).default(20),
  74. sortBy: z.enum(['name', 'level', 'code', 'createdAt']).default('createdAt'),
  75. sortOrder: z.enum(['ASC', 'DESC']).default('DESC'),
  76. });
  77. // 省市区列表返回Schema
  78. export const areaListResponseSchema = z.object({
  79. id: z.number().int().positive('ID必须为正整数'),
  80. parentId: z.coerce.number().int().min(0, '父级ID不能为负数').nullable(),
  81. name: z.string().min(1, '区域名称不能为空').max(100, '区域名称不能超过100个字符'),
  82. level: z.nativeEnum(AreaLevel, {
  83. message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
  84. }),
  85. code: z.string().min(1, '行政区划代码不能为空').max(20, '行政区划代码不能超过20个字符'),
  86. isDisabled: z.nativeEnum(DisabledStatus),
  87. isDeleted: z.number().int(),
  88. createdAt: z.coerce.date(),
  89. updatedAt: z.coerce.date(),
  90. createdBy: z.number().int().nullable(),
  91. updatedBy: z.number().int().nullable(),
  92. });
  93. // 省市区删除Schema
  94. export const deleteAreaSchema = z.object({
  95. id: z.number().int().positive('ID必须为正整数'),
  96. });
  97. // 省市区启用/禁用Schema
  98. export const toggleAreaStatusSchema = z.object({
  99. id: z.number().int().positive('ID必须为正整数'),
  100. isDisabled: z.nativeEnum(DisabledStatus),
  101. });
  102. // 省市区层级查询Schema
  103. export const getAreasByLevelSchema = z.object({
  104. level: z.nativeEnum(AreaLevel, {
  105. message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
  106. }),
  107. });
  108. // 省市区子级查询Schema
  109. export const getChildAreasSchema = z.object({
  110. parentId: z.number().int().positive('父级ID必须为正整数'),
  111. });
  112. // 省市区路径查询Schema
  113. export const getAreaPathSchema = z.object({
  114. id: z.number().int().positive('区域ID必须为正整数'),
  115. });
  116. // 导出类型
  117. export type CreateAreaInput = z.infer<typeof createAreaSchema>;
  118. export type UpdateAreaInput = z.infer<typeof updateAreaSchema>;
  119. export type GetAreaInput = z.infer<typeof getAreaSchema>;
  120. export type ListAreasInput = z.infer<typeof listAreasSchema>;
  121. export type DeleteAreaInput = z.infer<typeof deleteAreaSchema>;
  122. export type ToggleAreaStatusInput = z.infer<typeof toggleAreaStatusSchema>;
  123. export type GetAreasByLevelInput = z.infer<typeof getAreasByLevelSchema>;
  124. export type GetChildAreasInput = z.infer<typeof getChildAreasSchema>;
  125. export type GetAreaPathInput = z.infer<typeof getAreaPathSchema>;