route.schema.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import { z } from 'zod';
  2. import { DisabledStatus } from '@/share/types';
  3. import { locationInfoSchema } from '@/server/modules/locations/location.schema';
  4. // 车型枚举
  5. export enum VehicleType {
  6. BUS = 'bus', // 大巴
  7. MINIBUS = 'minibus', // 中巴
  8. CAR = 'car' // 小车
  9. }
  10. // 活动类型枚举
  11. export enum ActivityType {
  12. DEPARTURE = 'departure', // 去程活动
  13. RETURN = 'return' // 返程活动
  14. }
  15. // 路线创建Schema
  16. export const createRouteSchema = z.object({
  17. name: z.string().min(1, '路线名称不能为空').max(255, '路线名称不能超过255个字符'),
  18. description: z.string().max(1000, '路线描述不能超过1000个字符').optional().nullable(),
  19. startLocationId: z.number().int().positive('出发地点ID必须为正整数'),
  20. endLocationId: z.number().int().positive('目的地点ID必须为正整数'),
  21. pickupPoint: z.string().min(1, '上车点不能为空').max(255, '上车点不能超过255个字符'),
  22. dropoffPoint: z.string().min(1, '下车点不能为空').max(255, '下车点不能超过255个字符'),
  23. departureTime: z.coerce.date(),
  24. vehicleType: z.enum([VehicleType.BUS, VehicleType.MINIBUS, VehicleType.CAR], {
  25. message: '车型必须是有效的类型(bus/minibus/car)'
  26. }),
  27. price: z.number().min(0, '价格不能为负数').max(99999999.99, '价格不能超过99999999.99'),
  28. seatCount: z.number().int().min(1, '座位数至少为1').max(1000, '座位数不能超过1000'),
  29. availableSeats: z.number().int().min(0, '可用座位数不能为负数').max(1000, '可用座位数不能超过1000'),
  30. activityId: z.number().int().positive('活动ID必须为正整数'),
  31. });
  32. // 路线更新Schema
  33. export const updateRouteSchema = z.object({
  34. name: z.string().min(1, '路线名称不能为空').max(255, '路线名称不能超过255个字符').optional(),
  35. description: z.string().max(1000, '路线描述不能超过1000个字符').optional().nullable(),
  36. startLocationId: z.number().int().positive('出发地点ID必须为正整数').optional(),
  37. endLocationId: z.number().int().positive('目的地点ID必须为正整数').optional(),
  38. pickupPoint: z.string().min(1, '上车点不能为空').max(255, '上车点不能超过255个字符').optional(),
  39. dropoffPoint: z.string().min(1, '下车点不能为空').max(255, '下车点不能超过255个字符').optional(),
  40. departureTime: z.coerce.date(),
  41. vehicleType: z.enum([VehicleType.BUS, VehicleType.MINIBUS, VehicleType.CAR], {
  42. message: '车型必须是有效的类型(bus/minibus/car)'
  43. }).optional(),
  44. price: z.number().min(0, '价格不能为负数').max(99999999.99, '价格不能超过99999999.99').optional(),
  45. seatCount: z.number().int().min(1, '座位数至少为1').max(1000, '座位数不能超过1000').optional(),
  46. availableSeats: z.number().int().min(0, '可用座位数不能为负数').max(1000, '可用座位数不能超过1000').optional(),
  47. activityId: z.number().int().positive('活动ID必须为正整数').optional(),
  48. isDisabled: z.nativeEnum(DisabledStatus).optional(),
  49. });
  50. // 路线获取Schema
  51. export const getRouteSchema = z.object({
  52. id: z.number().int().positive('ID必须为正整数'),
  53. name: z.string().min(1, '路线名称不能为空').max(255, '路线名称不能超过255个字符'),
  54. description: z.string().max(1000, '路线描述不能超过1000个字符').optional().nullable(),
  55. startLocationId: z.number().int().positive('出发地点ID必须为正整数'),
  56. endLocationId: z.number().int().positive('目的地点ID必须为正整数'),
  57. startLocation: locationInfoSchema.optional().nullable(),
  58. endLocation: locationInfoSchema.optional().nullable(),
  59. pickupPoint: z.string().min(1, '上车点不能为空').max(255, '上车点不能超过255个字符'),
  60. dropoffPoint: z.string().min(1, '下车点不能为空').max(255, '下车点不能超过255个字符'),
  61. departureTime: z.coerce.date(),
  62. vehicleType: z.enum([VehicleType.BUS, VehicleType.MINIBUS, VehicleType.CAR], {
  63. message: '车型必须是有效的类型(bus/minibus/car)'
  64. }),
  65. price: z.coerce.number().min(0, '价格不能为负数').max(99999999.99, '价格不能超过99999999.99'),
  66. seatCount: z.number().int().min(1, '座位数至少为1').max(1000, '座位数不能超过1000'),
  67. availableSeats: z.number().int().min(0, '可用座位数不能为负数').max(1000, '可用座位数不能超过1000'),
  68. activityId: z.number().int().positive('活动ID必须为正整数'),
  69. isDisabled: z.nativeEnum(DisabledStatus),
  70. createdAt: z.coerce.date(),
  71. updatedAt: z.coerce.date(),
  72. createdBy: z.number().int().nullable(),
  73. updatedBy: z.number().int().nullable(),
  74. });
  75. // 路线列表查询Schema
  76. export const listRoutesSchema = z.object({
  77. keyword: z.string().optional(),
  78. vehicleType: z.string().optional(),
  79. routeType: z.enum(['departure', 'return']).optional(),
  80. minPrice: z.coerce.number().min(0).optional(),
  81. maxPrice: z.coerce.number().min(0).optional(),
  82. activityId: z.coerce.number().int().positive().optional(),
  83. isDisabled: z.coerce.number().int().optional(),
  84. page: z.coerce.number().int().min(1).default(1),
  85. pageSize: z.coerce.number().int().min(1).max(100).default(20),
  86. sortBy: z.enum(['name', 'price', 'departureTime', 'createdAt']).default('createdAt'),
  87. sortOrder: z.enum(['ASC', 'DESC']).default('DESC'),
  88. });
  89. // 路线列表返回Schema
  90. export const routeListResponseSchema = z.object({
  91. id: z.number().int().positive('ID必须为正整数'),
  92. name: z.string().min(1, '路线名称不能为空').max(255, '路线名称不能超过255个字符'),
  93. description: z.string().max(1000, '路线描述不能超过1000个字符').optional().nullable(),
  94. startLocationId: z.number().int().positive('出发地点ID必须为正整数'),
  95. endLocationId: z.number().int().positive('目的地点ID必须为正整数'),
  96. startLocation: locationInfoSchema.optional().nullable(),
  97. endLocation: locationInfoSchema.optional().nullable(),
  98. pickupPoint: z.string().min(1, '上车点不能为空').max(255, '上车点不能超过255个字符'),
  99. dropoffPoint: z.string().min(1, '下车点不能为空').max(255, '下车点不能超过255个字符'),
  100. departureTime: z.coerce.date(),
  101. vehicleType: z.enum([VehicleType.BUS, VehicleType.MINIBUS, VehicleType.CAR], {
  102. message: '车型必须是有效的类型(bus/minibus/car)'
  103. }),
  104. price: z.coerce.number().min(0, '价格不能为负数').max(99999999.99, '价格不能超过99999999.99'),
  105. seatCount: z.number().int().min(1, '座位数至少为1').max(1000, '座位数不能超过1000'),
  106. availableSeats: z.number().int().min(0, '可用座位数不能为负数').max(1000, '可用座位数不能超过1000'),
  107. activityId: z.number().int().positive('活动ID必须为正整数'),
  108. routeType: z.enum(['departure', 'return']),
  109. isDisabled: z.nativeEnum(DisabledStatus),
  110. createdAt: z.coerce.date(),
  111. updatedAt: z.coerce.date(),
  112. createdBy: z.number().int().nullable(),
  113. updatedBy: z.number().int().nullable(),
  114. activity: z.object({
  115. id: z.number().int().positive('活动ID必须为正整数'),
  116. name: z.string().min(1, '活动名称不能为空').max(255, '活动名称不能超过255个字符'),
  117. type: z.enum([ActivityType.DEPARTURE, ActivityType.RETURN], {
  118. message: '活动类型必须是departure(去程)或return(返程)'
  119. }),
  120. }).optional(),
  121. });
  122. // 路线删除Schema
  123. export const deleteRouteSchema = z.object({
  124. id: z.number().int().positive('ID必须为正整数'),
  125. });
  126. // 路线启用/禁用Schema
  127. export const toggleRouteStatusSchema = z.object({
  128. id: z.number().int().positive('ID必须为正整数'),
  129. isDisabled: z.nativeEnum(DisabledStatus),
  130. });
  131. // 导出类型
  132. export type CreateRouteInput = z.infer<typeof createRouteSchema>;
  133. export type UpdateRouteInput = z.infer<typeof updateRouteSchema>;
  134. export type GetRouteInput = z.infer<typeof getRouteSchema>;
  135. export type ListRoutesInput = z.infer<typeof listRoutesSchema>;
  136. export type DeleteRouteInput = z.infer<typeof deleteRouteSchema>;
  137. export type ToggleRouteStatusInput = z.infer<typeof toggleRouteStatusSchema>;