import { ref, watch, unref, type Ref } from 'vue' import type { ProFormSchema, ProFormProps, FormActionType } from '../types' export interface UseFormProps extends ProFormProps { schemas?: ProFormSchema[] } /** 支持 ref/computed 的 props(参考 Vben Admin:参数 props 内的值可以是 computed 或者 ref 类型) */ export type UseFormPropsReactive = UseFormProps | Ref export interface UseFormReturn { /** 用于 @register,接收表单实例的 formAction */ register: (formAction: FormActionType) => void formAction: { value: FormActionType | null } getFieldsValue: () => Record setFieldsValue: (values: Record) => Promise resetFields: () => Promise validate: (nameList?: string[]) => Promise | { errors: Record }> validateFields: (nameList?: string[]) => Promise submit: () => Promise scrollToField: (name: string, options?: import('../types').ScrollToFieldOptions) => Promise clearValidate: (name?: string | string[]) => void updateSchema: (data: Partial | Partial[]) => Promise appendSchemaByField: (schema: ProFormSchema, prefixField?: string, first?: boolean) => Promise removeSchemaByField: (field: string | string[]) => Promise setProps: (props: Partial) => Promise getComponentInstance: FormActionType['getComponentInstance'] getFieldOptions: FormActionType['getFieldOptions'] isFieldLoading: FormActionType['isFieldLoading'] } export function useForm(props?: UseFormPropsReactive): [UseFormReturn['register'], Omit] { const formAction = ref(null) const formPropsRef = ref(props ? unref(props as Ref) : undefined) const getFormProps = () => (props ? unref(props as Ref) : undefined) as UseFormProps | undefined const register = (action: FormActionType) => { formAction.value = action const formProps = getFormProps() if (formProps && Object.keys(formProps).length > 0) { action.setProps(formProps) } } if (props) { watch( () => getFormProps(), (formProps) => { formPropsRef.value = formProps if (formProps && formAction.value) { formAction.value.setProps(formProps) } }, { deep: true } ) } const getFieldsValue = () => formAction.value?.getFieldsValue() ?? {} const setFieldsValue = async (values: Record) => { await formAction.value?.setFieldsValue(values) } const resetFields = async () => { await formAction.value?.resetFields() } const validate = (nameList?: string[]) => formAction.value?.validate(nameList) ?? Promise.resolve({} as Record) const validateFields = (nameList?: string[]) => formAction.value?.validateFields(nameList) ?? Promise.resolve() const submit = () => formAction.value?.submit() ?? Promise.resolve() const scrollToField = (name: string, options?: import('../types').ScrollToFieldOptions) => formAction.value?.scrollToField(name, options) ?? Promise.resolve() const clearValidate = (name?: string | string[]) => { formAction.value?.clearValidate(name) } const updateSchema = (data: Partial | Partial[]) => formAction.value?.updateSchema(data) ?? Promise.resolve() const appendSchemaByField = (schema: ProFormSchema, prefixField?: string, first?: boolean) => formAction.value?.appendSchemaByField(schema, prefixField, first) ?? Promise.resolve() const removeSchemaByField = (field: string | string[]) => formAction.value?.removeSchemaByField(field) ?? Promise.resolve() const setProps = async (formProps: Partial) => { formPropsRef.value = { ...formPropsRef.value, ...formProps } await formAction.value?.setProps(formProps) } const getComponentInstance: FormActionType['getComponentInstance'] = (field) => formAction.value?.getComponentInstance(field) ?? null function getFieldOptions(field: string): Array<{ label: string; value: unknown }> function getFieldOptions(field: string, raw: false): Array<{ label: string; value: unknown }> function getFieldOptions(field: string, raw: true): unknown[] function getFieldOptions(field: string, raw = false): Array<{ label: string; value: unknown }> | unknown[] { if (!formAction.value) return [] if (raw) return formAction.value.getFieldOptions(field, true) return formAction.value.getFieldOptions(field) } const isFieldLoading: FormActionType['isFieldLoading'] = (field) => formAction.value?.isFieldLoading(field) ?? false const result: UseFormReturn = { register, formAction, getFieldsValue, setFieldsValue, resetFields, validate, validateFields, submit, scrollToField, clearValidate, updateSchema, appendSchemaByField, removeSchemaByField, setProps, getComponentInstance, getFieldOptions, isFieldLoading, } return [register, result] }