|
|
@@ -0,0 +1,137 @@
|
|
|
+import { z } from 'zod';
|
|
|
+import { DisabledStatus } from '@d8d/shared-types';
|
|
|
+import { AreaLevel } from './area.entity';
|
|
|
+
|
|
|
+// 省市区创建Schema
|
|
|
+export const createAreaSchema = z.object({
|
|
|
+ parentId: z.number().int().min(0, '父级ID不能为负数').nullable().default(null),
|
|
|
+ name: z.string().min(1, '区域名称不能为空').max(100, '区域名称不能超过100个字符'),
|
|
|
+ level: z.nativeEnum(AreaLevel, {
|
|
|
+ message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
|
|
|
+ }),
|
|
|
+ code: z.string().min(1, '行政区划代码不能为空').max(20, '行政区划代码不能超过20个字符'),
|
|
|
+ isDisabled: z.nativeEnum(DisabledStatus).default(DisabledStatus.ENABLED),
|
|
|
+}).refine((data) => {
|
|
|
+ // 验证层级和父级ID的关系
|
|
|
+ if (data.level === AreaLevel.PROVINCE && data.parentId !== null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (data.level !== AreaLevel.PROVINCE && data.parentId === null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}, {
|
|
|
+ message: '层级和父级ID关系不正确:省/直辖市(parentId=null),市/区县(parentId>0)',
|
|
|
+ path: ['parentId'],
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区更新Schema
|
|
|
+export const updateAreaSchema = z.object({
|
|
|
+ parentId: z.number().int().min(0, '父级ID不能为负数').nullable().optional(),
|
|
|
+ name: z.string().min(1, '区域名称不能为空').max(100, '区域名称不能超过100个字符').optional(),
|
|
|
+ level: z.nativeEnum(AreaLevel, {
|
|
|
+ message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
|
|
|
+ }).optional(),
|
|
|
+ code: z.string().min(1, '行政区划代码不能为空').max(20, '行政区划代码不能超过20个字符').optional(),
|
|
|
+ isDisabled: z.nativeEnum(DisabledStatus).optional(),
|
|
|
+}).refine((data) => {
|
|
|
+ // 验证层级和父级ID的关系
|
|
|
+ // 只有当两个字段都有值且都不为undefined时才进行验证
|
|
|
+ if (data.level !== undefined && data.parentId !== undefined) {
|
|
|
+ if (data.level === AreaLevel.PROVINCE && data.parentId !== null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (data.level !== AreaLevel.PROVINCE && data.parentId === null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}, {
|
|
|
+ message: '层级和父级ID关系不正确:省/直辖市(parentId=null),市/区县(parentId>0)',
|
|
|
+ path: ['parentId'],
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区获取Schema
|
|
|
+export const getAreaSchema = z.object({
|
|
|
+ id: z.number().int().positive('ID必须为正整数'),
|
|
|
+ parentId: z.number().int().min(0, '父级ID不能为负数').nullable(),
|
|
|
+ name: z.string().min(1, '区域名称不能为空').max(100, '区域名称不能超过100个字符'),
|
|
|
+ level: z.nativeEnum(AreaLevel, {
|
|
|
+ message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
|
|
|
+ }),
|
|
|
+ code: z.string().min(1, '行政区划代码不能为空').max(20, '行政区划代码不能超过20个字符'),
|
|
|
+ isDisabled: z.nativeEnum(DisabledStatus),
|
|
|
+ isDeleted: z.number().int(),
|
|
|
+ createdAt: z.coerce.date(),
|
|
|
+ updatedAt: z.coerce.date(),
|
|
|
+ createdBy: z.number().int().nullable(),
|
|
|
+ updatedBy: z.number().int().nullable(),
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区列表查询Schema
|
|
|
+export const listAreasSchema = z.object({
|
|
|
+ keyword: z.string().optional(),
|
|
|
+ level: z.nativeEnum(AreaLevel).optional(),
|
|
|
+ parentId: z.coerce.number().int().min(0).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', 'level', 'code', 'createdAt']).default('createdAt'),
|
|
|
+ sortOrder: z.enum(['ASC', 'DESC']).default('DESC'),
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区列表返回Schema
|
|
|
+export const areaListResponseSchema = z.object({
|
|
|
+ id: z.number().int().positive('ID必须为正整数'),
|
|
|
+ parentId: z.coerce.number().int().min(0, '父级ID不能为负数').nullable(),
|
|
|
+ name: z.string().min(1, '区域名称不能为空').max(100, '区域名称不能超过100个字符'),
|
|
|
+ level: z.nativeEnum(AreaLevel, {
|
|
|
+ message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
|
|
|
+ }),
|
|
|
+ code: z.string().min(1, '行政区划代码不能为空').max(20, '行政区划代码不能超过20个字符'),
|
|
|
+ isDisabled: z.nativeEnum(DisabledStatus),
|
|
|
+ isDeleted: z.number().int(),
|
|
|
+ createdAt: z.coerce.date(),
|
|
|
+ updatedAt: z.coerce.date(),
|
|
|
+ createdBy: z.number().int().nullable(),
|
|
|
+ updatedBy: z.number().int().nullable(),
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区删除Schema
|
|
|
+export const deleteAreaSchema = z.object({
|
|
|
+ id: z.number().int().positive('ID必须为正整数'),
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区启用/禁用Schema
|
|
|
+export const toggleAreaStatusSchema = z.object({
|
|
|
+ id: z.number().int().positive('ID必须为正整数'),
|
|
|
+ isDisabled: z.nativeEnum(DisabledStatus),
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区层级查询Schema
|
|
|
+export const getAreasByLevelSchema = z.object({
|
|
|
+ level: z.nativeEnum(AreaLevel, {
|
|
|
+ message: '层级必须是1(省/直辖市)、2(市)或3(区/县)'
|
|
|
+ }),
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区子级查询Schema
|
|
|
+export const getChildAreasSchema = z.object({
|
|
|
+ parentId: z.number().int().positive('父级ID必须为正整数'),
|
|
|
+});
|
|
|
+
|
|
|
+// 省市区路径查询Schema
|
|
|
+export const getAreaPathSchema = z.object({
|
|
|
+ id: z.number().int().positive('区域ID必须为正整数'),
|
|
|
+});
|
|
|
+
|
|
|
+// 导出类型
|
|
|
+export type CreateAreaInput = z.infer<typeof createAreaSchema>;
|
|
|
+export type UpdateAreaInput = z.infer<typeof updateAreaSchema>;
|
|
|
+export type GetAreaInput = z.infer<typeof getAreaSchema>;
|
|
|
+export type ListAreasInput = z.infer<typeof listAreasSchema>;
|
|
|
+export type DeleteAreaInput = z.infer<typeof deleteAreaSchema>;
|
|
|
+export type ToggleAreaStatusInput = z.infer<typeof toggleAreaStatusSchema>;
|
|
|
+export type GetAreasByLevelInput = z.infer<typeof getAreasByLevelSchema>;
|
|
|
+export type GetChildAreasInput = z.infer<typeof getChildAreasSchema>;
|
|
|
+export type GetAreaPathInput = z.infer<typeof getAreaPathSchema>;
|