Files
access-manage/src/modules/employees/employee.schema.ts
T
2026-05-26 11:06:13 +08:00

64 lines
2.3 KiB
TypeScript

import { z } from "zod";
import { EMPLOYEE_STATUS } from "./employee.types";
// 查询参数里的空字符串统一当作“未传”,方便前端表单清空筛选条件。
const emptyStringToUndefined = (value: unknown) => {
if (typeof value === "string" && value.trim() === "") {
return undefined;
}
return value;
};
const phoneSchema = z
.string()
.trim()
// 这里先按中国大陆手机号做校验;如果你的店里有港澳台或海外员工,可以改成更宽松的规则。
.regex(/^1[3-9]\d{9}$/, "手机号格式不正确");
const roleIdsSchema = z
.array(z.coerce.number().int().positive())
// 角色过多通常说明权限模型需要重新设计,这里先给出合理上限。
.max(20, "一个员工不建议绑定过多角色")
.default([]);
export const idParamSchema = z.object({
id: z.coerce.number().int().positive()
});
export const listEmployeesQuerySchema = z.object({
// z.coerce 用于把 query string 转成数字,例如 ?page=1。
storeId: z.preprocess(emptyStringToUndefined, z.coerce.number().int().positive().optional()),
status: z.preprocess(emptyStringToUndefined, z.enum(EMPLOYEE_STATUS).optional()),
keyword: z.preprocess(emptyStringToUndefined, z.string().trim().min(1).max(100).optional()),
page: z.coerce.number().int().min(1).default(1),
pageSize: z.coerce.number().int().min(1).max(100).default(20)
});
export const createEmployeeBodySchema = z.object({
storeId: z.coerce.number().int().positive(),
name: z.string().trim().min(1).max(50),
phone: phoneSchema,
status: z.enum(EMPLOYEE_STATUS).default("ACTIVE"),
remark: z.string().trim().max(500).nullable().optional(),
roleIds: roleIdsSchema
});
export const updateEmployeeBodySchema = z
.object({
storeId: z.coerce.number().int().positive().optional(),
name: z.string().trim().min(1).max(50).optional(),
phone: phoneSchema.optional(),
status: z.enum(EMPLOYEE_STATUS).optional(),
remark: z.string().trim().max(500).nullable().optional(),
roleIds: roleIdsSchema.optional()
})
// PATCH 不允许提交空对象,否则调用方无法判断到底修改了什么。
.refine((value) => Object.keys(value).length > 0, {
message: "至少需要提交一个要修改的字段"
});
export const updateEmployeeStatusBodySchema = z.object({
status: z.enum(EMPLOYEE_STATUS)
});