| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- import {
- z,
- ZodTypeAny,
- ZodString,
- ZodNumber,
- ZodBoolean,
- ZodEffects,
- } from 'zod';
- import { RegisterInfo } from '@/API/patient/workActions';
- import { Rule } from 'antd/es/form';
- import { PregnancyStatus } from '@/domain/patient/pregnancyStatus';
- type IgnoredKeys = 'views' | 'study_type' | 'modality' | 'patient_type'; // 这些字段不在表单中填写
- const registerInfoSchema: Record<
- keyof Omit<RegisterInfo, IgnoredKeys>,
- z.ZodTypeAny
- > = {
- accession_number: z.string().nonempty().regex(/^[a-zA-Z0-9_-]+$/, '只能输入数字、英文字符、下划线和连字符'),
- patient_name: z.string().nonempty(),
- patient_id: z.string().nonempty().regex(/^[a-zA-Z0-9_-]+$/, '只能输入数字、英文字符、下划线和连字符'),
- patient_size: z.string().nonempty(),
- patient_age: z.object({
- number: z.number(), // 必须是数字
- unit: z.string(), // 必须是字符串(根据你的需求,也可以是 z.enum(...) 等)
- }),
- patient_dob: z.string().nonempty(),
- patient_sex: z.string().optional(),
- ref_physician: z.string().optional(),
- operator_id: z.string().regex(/^[a-zA-Z0-9_-]*$/, '只能输入数字、英文字符、下划线和连字符').optional(),
- weight: z.number().optional(),
- thickness: z.number().optional(),
- length: z.number().optional(),
- comment: z.string().optional(),
- // views: z.array(z.object({
- // view_id: z.string(),
- // procedure_id: z.string()
- // })).optional()
- /**---下面是宠物专用字段--- */
- sex_neutered: z.string().optional(),
- chip_number: z.string().optional(),
- variety: z.string().optional(),
- owner_name: z.string().nonempty(),
- is_anaesthesia: z.boolean().optional(),
- is_sedation: z.boolean().optional(),
- /**---下面是人医专用字段--- */
- pregnancy_status: z.nativeEnum(PregnancyStatus).optional(),
- };
- const registerformSchema = z.object(registerInfoSchema);
- // 统一管理规则。规则表。描述要验证的字段【字段来源于被验证的数据结构UserInfo】,以及每个字段的"是否必填、必填标记、验证规则、提示信息、验证时机"
- export const registerFormFields = {
- accession_number: {
- label: 'Accession Number',
- required: true,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.accession_number),
- message: 'Accession Number is optional',
- trigger: ['onChange', 'onBlur'],
- },
- patient_id: {
- label: 'Patient ID',
- required: true,
- requiredLabel: 'Patient ID is required',
- validation: zodToAntdRules(registerformSchema.shape.patient_id),
- message: 'Patient ID is required',
- trigger: ['onChange', 'onBlur'],
- },
- patient_name: {
- label: 'Patient Name',
- required: true,
- requiredLabel: 'Patient Name is required',
- validation: zodToAntdRules(registerformSchema.shape.patient_name),
- message: 'Patient Name is required',
- trigger: ['onChange', 'onBlur'],
- },
- patient_size: {
- label: 'Patient Size',
- required: true,
- requiredLabel: 'Patient Size is required',
- validation: zodToAntdRules(registerformSchema.shape.patient_size),
- message: 'Patient Size is required',
- trigger: ['onChange', 'onBlur'],
- },
- patient_age: {
- label: 'Patient Age',
- required: true,
- requiredLabel: 'Patient Age is required',
- validation: [
- ...zodToAntdRules(registerformSchema.shape.patient_age),
- {
- validator: (_, value) => {
- if (!value || typeof value.number !== 'number') {
- return Promise.reject(new Error('请输入有效的年龄'));
- }
- if (value.number < 0) {
- return Promise.reject(new Error('年龄不能为负数'));
- }
- if (value.number > 200) {
- return Promise.reject(new Error('年龄超出合理范围(最大200)'));
- }
- if (!Number.isInteger(value.number)) {
- return Promise.reject(new Error('年龄必须为整数'));
- }
- return Promise.resolve();
- },
- },
- ],
- message: 'Patient Age is required',
- trigger: ['onChange', 'onBlur'],
- },
- patient_dob: {
- label: 'Patient DOB',
- required: true,
- requiredLabel: 'Patient DOB is required',
- validation: zodToAntdRules(registerformSchema.shape.patient_dob),
- message: 'Patient DOB is required',
- trigger: ['onChange', 'onBlur'],
- },
- patient_sex: {
- label: 'Patient Sex',
- required: false,
- requiredLabel: 'Patient Sex is required',
- validation: zodToAntdRules(registerformSchema.shape.patient_sex),
- message: 'Patient Sex is required',
- trigger: ['onChange', 'onBlur'],
- },
- // sex_neutered: {
- // label: 'Sex Neutered',
- // required: false,
- // requiredLabel: '',
- // validation: zodToAntdRules(registerformSchema.shape.sex_neutered),
- // message: 'Sex Neutered is optional',
- // trigger: ['onChange', 'onBlur'],
- // },
- pregnancy_status: {
- label: 'Pregnancy Status',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.pregnancy_status),
- message: 'Pregnancy Status is optional',
- trigger: ['onChange', 'onBlur'],
- },
- // chip_number: {
- // label: 'Chip Number',
- // required: false,
- // requiredLabel: '',
- // validation: zodToAntdRules(registerformSchema.shape.chip_number),
- // message: 'Chip Number is optional',
- // trigger: ['onChange', 'onBlur'],
- // },
- // variety: {
- // label: 'Variety',
- // required: false,
- // requiredLabel: '',
- // validation: zodToAntdRules(registerformSchema.shape.variety),
- // message: 'Variety is optional',
- // trigger: ['onChange', 'onBlur'],
- // },
- // patient_type: {
- // label: 'Patient Type',
- // required: true,
- // requiredLabel: '',
- // validation: zodToAntdRules(registerformSchema.shape.patient_type),
- // message: 'Patient Type is optional',
- // trigger: ['onChange', 'onBlur'],
- // },
- ref_physician: {
- label: 'Referring Physician',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.ref_physician),
- message: 'Referring Physician is optional',
- trigger: ['onChange', 'onBlur'],
- },
- operator_id: {
- label: 'Operator ID',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.operator_id),
- message: 'Operator ID is optional',
- trigger: ['onChange', 'onBlur'],
- },
- weight: {
- label: 'Weight',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.weight),
- message: 'Weight is optional',
- trigger: ['onChange', 'onBlur'],
- },
- thickness: {
- label: 'Thickness',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.thickness),
- message: 'Thickness is optional',
- trigger: ['onChange', 'onBlur'],
- },
- length: {
- label: 'Length',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.length),
- message: 'Length is optional',
- trigger: ['onChange', 'onBlur'],
- },
- comment: {
- label: 'Comment',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.comment),
- message: 'Comment is optional',
- trigger: ['onChange', 'onBlur'],
- },
- //动物专用字段
- owner_name: {
- label: 'Owner Name',
- required: true,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.owner_name),
- message: 'Owner Name is required',
- trigger: ['onChange', 'onBlur'],
- },
- sex_neutered: {
- label: 'neutered',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.sex_neutered),
- message: 'neutered is optional',
- trigger: ['onChange', 'onBlur'],
- },
- chip_number: {
- label: 'Chip Number',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.chip_number),
- message: 'Chip Number is optional',
- trigger: ['onChange', 'onBlur'],
- },
- variety: {
- label: 'Variety',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.variety),
- message: 'Variety is optional',
- trigger: ['onChange', 'onBlur'],
- },
- is_anaesthesia: {
- label: 'Anaesthesia',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.is_anaesthesia),
- message: 'Anaesthesia is optional',
- trigger: ['onChange', 'onBlur'],
- },
- is_sedation: {
- label: 'Sedation',
- required: false,
- requiredLabel: '',
- validation: zodToAntdRules(registerformSchema.shape.is_sedation),
- message: 'Sedation is optional',
- trigger: ['onChange', 'onBlur'],
- },
- } satisfies Record<
- keyof Omit<RegisterInfo, IgnoredKeys>,
- {
- label: string;
- required: boolean;
- requiredLabel: string;
- validation: Rule[];
- message: string;
- trigger: ('onChange' | 'onBlur' | 'onSubmit')[];
- }
- >;
- export default registerformSchema;
- type AntdRule = Rule & {};
- export function zodToAntdRules(field: ZodTypeAny): AntdRule[] {
- const rules: AntdRule[] = [];
- // 解开 effects,比如 .refine() 或 .transform()
- while (field instanceof ZodEffects) {
- field = field._def.schema;
- }
- if (field instanceof ZodString) {
- for (const check of field._def.checks) {
- switch (check.kind) {
- case 'min':
- if (check.value === 1) {
- rules.push({ required: true, message: check.message || '必填项' });
- } else {
- rules.push({ min: check.value, message: check.message ?? '' });
- }
- break;
- case 'max':
- rules.push({ max: check.value, message: check.message ?? '' });
- break;
- case 'email':
- rules.push({ type: 'email', message: check.message ?? '' });
- break;
- case 'regex':
- rules.push({ pattern: check.regex, message: check.message ?? '' });
- break;
- case 'length':
- rules.push({ len: check.value, message: check.message ?? '' });
- break;
- }
- }
- }
- if (field instanceof ZodNumber) {
- for (const check of field._def.checks) {
- switch (check.kind) {
- case 'min':
- rules.push({ min: check.value, message: check.message ?? '' });
- break;
- case 'max':
- rules.push({ max: check.value, message: check.message ?? '' });
- break;
- case 'int':
- rules.push({
- type: 'integer',
- message: check.message || '必须为整数',
- });
- break;
- }
- }
- }
- if (field instanceof ZodBoolean) {
- rules.push({ type: 'boolean', message: '必须为布尔值' });
- }
- return rules;
- }
|