|
@@ -0,0 +1,103 @@
|
|
|
|
|
+import { z } from 'zod';
|
|
|
|
|
+import { DisabledStatus } from '@/share/types';
|
|
|
|
|
+import { ActivityType } from '../activities/activity.entity';
|
|
|
|
|
+
|
|
|
|
|
+// 路线创建Schema
|
|
|
|
|
+export const createRouteSchema = z.object({
|
|
|
|
|
+ name: z.string().min(1, '路线名称不能为空').max(255, '路线名称不能超过255个字符'),
|
|
|
|
|
+ description: z.string().max(1000, '路线描述不能超过1000个字符').optional().nullable(),
|
|
|
|
|
+ startPoint: z.string().min(1, '出发地不能为空').max(255, '出发地不能超过255个字符'),
|
|
|
|
|
+ endPoint: z.string().min(1, '目的地不能为空').max(255, '目的地不能超过255个字符'),
|
|
|
|
|
+ pickupPoint: z.string().min(1, '上车点不能为空').max(255, '上车点不能超过255个字符'),
|
|
|
|
|
+ dropoffPoint: z.string().min(1, '下车点不能为空').max(255, '下车点不能超过255个字符'),
|
|
|
|
|
+ departureTime: z.string().datetime('出发时间格式不正确'),
|
|
|
|
|
+ vehicleType: z.string().min(1, '车型不能为空').max(50, '车型不能超过50个字符'),
|
|
|
|
|
+ price: z.number().min(0, '价格不能为负数').max(99999999.99, '价格不能超过99999999.99'),
|
|
|
|
|
+ seatCount: z.number().int().min(1, '座位数至少为1').max(1000, '座位数不能超过1000'),
|
|
|
|
|
+ availableSeats: z.number().int().min(0, '可用座位数不能为负数').max(1000, '可用座位数不能超过1000'),
|
|
|
|
|
+ activityId: z.number().int().positive('活动ID必须为正整数'),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 路线更新Schema
|
|
|
|
|
+export const updateRouteSchema = z.object({
|
|
|
|
|
+ name: z.string().min(1, '路线名称不能为空').max(255, '路线名称不能超过255个字符').optional(),
|
|
|
|
|
+ description: z.string().max(1000, '路线描述不能超过1000个字符').optional().nullable(),
|
|
|
|
|
+ startPoint: z.string().min(1, '出发地不能为空').max(255, '出发地不能超过255个字符').optional(),
|
|
|
|
|
+ endPoint: z.string().min(1, '目的地不能为空').max(255, '目的地不能超过255个字符').optional(),
|
|
|
|
|
+ pickupPoint: z.string().min(1, '上车点不能为空').max(255, '上车点不能超过255个字符').optional(),
|
|
|
|
|
+ dropoffPoint: z.string().min(1, '下车点不能为空').max(255, '下车点不能超过255个字符').optional(),
|
|
|
|
|
+ departureTime: z.string().datetime('出发时间格式不正确').optional(),
|
|
|
|
|
+ vehicleType: z.string().min(1, '车型不能为空').max(50, '车型不能超过50个字符').optional(),
|
|
|
|
|
+ price: z.number().min(0, '价格不能为负数').max(99999999.99, '价格不能超过99999999.99').optional(),
|
|
|
|
|
+ seatCount: z.number().int().min(1, '座位数至少为1').max(1000, '座位数不能超过1000').optional(),
|
|
|
|
|
+ availableSeats: z.number().int().min(0, '可用座位数不能为负数').max(1000, '可用座位数不能超过1000').optional(),
|
|
|
|
|
+ activityId: z.number().int().positive('活动ID必须为正整数').optional(),
|
|
|
|
|
+ isDisabled: z.nativeEnum(DisabledStatus).optional(),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 路线获取Schema
|
|
|
|
|
+export const getRouteSchema = z.object({
|
|
|
|
|
+ id: z.number().int().positive('ID必须为正整数'),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 路线列表查询Schema
|
|
|
|
|
+export const listRoutesSchema = z.object({
|
|
|
|
|
+ keyword: z.string().optional(),
|
|
|
|
|
+ vehicleType: z.string().optional(),
|
|
|
|
|
+ minPrice: z.coerce.number().min(0).optional(),
|
|
|
|
|
+ maxPrice: z.coerce.number().min(0).optional(),
|
|
|
|
|
+ activityId: z.coerce.number().int().positive().optional(),
|
|
|
|
|
+ isDisabled: z.coerce.number().int().optional(),
|
|
|
|
|
+ page: z.coerce.number().int().min(1).default(1),
|
|
|
|
|
+ pageSize: z.coerce.number().int().min(1).max(100).default(20),
|
|
|
|
|
+ sortBy: z.enum(['name', 'price', 'departureTime', 'createdAt']).default('createdAt'),
|
|
|
|
|
+ sortOrder: z.enum(['ASC', 'DESC']).default('DESC'),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 路线列表返回Schema
|
|
|
|
|
+export const routeListResponseSchema = z.object({
|
|
|
|
|
+ id: z.number().int().positive('ID必须为正整数'),
|
|
|
|
|
+ name: z.string().min(1, '路线名称不能为空').max(255, '路线名称不能超过255个字符'),
|
|
|
|
|
+ description: z.string().max(1000, '路线描述不能超过1000个字符').optional().nullable(),
|
|
|
|
|
+ startPoint: z.string().min(1, '出发地不能为空').max(255, '出发地不能超过255个字符'),
|
|
|
|
|
+ endPoint: z.string().min(1, '目的地不能为空').max(255, '目的地不能超过255个字符'),
|
|
|
|
|
+ pickupPoint: z.string().min(1, '上车点不能为空').max(255, '上车点不能超过255个字符'),
|
|
|
|
|
+ dropoffPoint: z.string().min(1, '下车点不能为空').max(255, '下车点不能超过255个字符'),
|
|
|
|
|
+ departureTime: z.coerce.string(),
|
|
|
|
|
+ vehicleType: z.string().min(1, '车型不能为空').max(50, '车型不能超过50个字符'),
|
|
|
|
|
+ price: z.coerce.number().min(0, '价格不能为负数').max(99999999.99, '价格不能超过99999999.99'),
|
|
|
|
|
+ seatCount: z.number().int().min(1, '座位数至少为1').max(1000, '座位数不能超过1000'),
|
|
|
|
|
+ availableSeats: z.number().int().min(0, '可用座位数不能为负数').max(1000, '可用座位数不能超过1000'),
|
|
|
|
|
+ activityId: z.number().int().positive('活动ID必须为正整数'),
|
|
|
|
|
+ isDisabled: z.nativeEnum(DisabledStatus),
|
|
|
|
|
+ createdAt: z.coerce.string(),
|
|
|
|
|
+ updatedAt: z.coerce.string(),
|
|
|
|
|
+ createdBy: z.number().int().optional(),
|
|
|
|
|
+ updatedBy: z.number().int().optional(),
|
|
|
|
|
+ activity: z.object({
|
|
|
|
|
+ id: z.number().int().positive('活动ID必须为正整数'),
|
|
|
|
|
+ name: z.string().min(1, '活动名称不能为空').max(255, '活动名称不能超过255个字符'),
|
|
|
|
|
+ type: z.nativeEnum(ActivityType, {
|
|
|
|
|
+ message: '活动类型必须是departure(去程)或return(返程)'
|
|
|
|
|
+ }),
|
|
|
|
|
+ }).optional(),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 路线删除Schema
|
|
|
|
|
+export const deleteRouteSchema = z.object({
|
|
|
|
|
+ id: z.number().int().positive('ID必须为正整数'),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 路线启用/禁用Schema
|
|
|
|
|
+export const toggleRouteStatusSchema = z.object({
|
|
|
|
|
+ id: z.number().int().positive('ID必须为正整数'),
|
|
|
|
|
+ isDisabled: z.nativeEnum(DisabledStatus),
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 导出类型
|
|
|
|
|
+export type CreateRouteInput = z.infer<typeof createRouteSchema>;
|
|
|
|
|
+export type UpdateRouteInput = z.infer<typeof updateRouteSchema>;
|
|
|
|
|
+export type GetRouteInput = z.infer<typeof getRouteSchema>;
|
|
|
|
|
+export type ListRoutesInput = z.infer<typeof listRoutesSchema>;
|
|
|
|
|
+export type DeleteRouteInput = z.infer<typeof deleteRouteSchema>;
|
|
|
|
|
+export type ToggleRouteStatusInput = z.infer<typeof toggleRouteStatusSchema>;
|