Browse Source

fix(form-ui): normalize zod formats before default extraction

pull/8372/head
kilisamemarisaaa 4 weeks ago
parent
commit
4c3621157d
  1. 31
      packages/@core/ui-kit/form-ui/__tests__/form-integration.test.ts
  2. 41
      packages/@core/ui-kit/form-ui/src/use-form-context.ts

31
packages/@core/ui-kit/form-ui/__tests__/form-integration.test.ts

@ -104,6 +104,37 @@ describe('useVbenForm integration', () => {
});
});
it('filters native zod formats from nested default extraction', async () => {
const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
const [Form, formApi] = useVbenForm({
schema: [
{
component: TestInput,
fieldName: 'profile',
rules: z.object({
email: z.email(),
address: z.object({
ip: z.ipv4(),
backup: z.email().default('backup@example.com'),
}),
}),
},
],
showDefaultActions: false,
});
const wrapper = mount(Form);
wrappers.push(wrapper);
await flushPromises();
expect(warn).not.toHaveBeenCalled();
expect(await formApi.getValues()).toEqual({
profile: {
address: { backup: 'backup@example.com', ip: '' },
email: '',
},
});
});
it('uses model updates as the primary channel and preserves empty strings', async () => {
const validateValue = vi.fn();
const [Form, formApi] = useVbenForm({

41
packages/@core/ui-kit/form-ui/src/use-form-context.ts

@ -15,6 +15,7 @@ import {
ZodNumber,
ZodObject,
ZodString,
string as zodString,
ZodStringFormat,
} from 'zod';
import { getDefaultsForSchema } from 'zod-defaults';
@ -33,6 +34,42 @@ export const [injectFormProps, provideFormProps] =
export const [injectComponentRefMap, provideComponentRefMap] =
createContext<Map<string, unknown>>('ComponentRefMap');
function normalizeSchemaForDefaults(rule: ZodType): ZodType {
const rawRule = toRaw(rule) as any;
if (rawRule instanceof ZodStringFormat) {
return zodString();
}
if (rawRule instanceof ZodObject) {
const shape = Object.fromEntries(
Object.entries(rawRule.shape).map(([key, value]) => [
key,
normalizeSchemaForDefaults(value as ZodType),
]),
);
return object(shape);
}
if (rawRule instanceof ZodIntersection) {
const { left, right } = (rawRule as any).def;
return normalizeSchemaForDefaults(left as ZodType).and(
normalizeSchemaForDefaults(right as ZodType),
);
}
if (rawRule.constructor.name === 'ZodDefault') {
const inner = normalizeSchemaForDefaults(rawRule.unwrap());
return inner.default(rawRule.def.defaultValue);
}
if (rawRule.constructor.name === 'ZodPipe') {
return normalizeSchemaForDefaults(rawRule.in).pipe(rawRule.out);
}
return rawRule;
}
export function useFormInitial(
props: ComputedRef<VbenFormProps> | VbenFormProps,
) {
@ -63,7 +100,7 @@ export function useFormInitial(
// 检查规则是否适合提取默认值
const rawRules = toRaw(item.rules);
const customDefaultValue = getCustomDefaultValue(rawRules);
zodObject[item.fieldName] = rawRules;
zodObject[item.fieldName] = normalizeSchemaForDefaults(rawRules);
if (customDefaultValue !== undefined) {
initialValues[item.fieldName] = customDefaultValue;
}
@ -93,7 +130,7 @@ export function useFormInitial(
}
return defaultValues;
} else if (rule instanceof ZodIntersection) {
return getDefaultsForSchema(rule);
return getDefaultsForSchema(normalizeSchemaForDefaults(rule) as any);
} else {
return undefined; // 其他类型不提供默认值
}

Loading…
Cancel
Save