import type { FormKitFrameworkContext, FormKitTypeDefinition } from '@formkit/core'; import type { FormKitInputs } from '@formkit/inputs'; import { createSection, label, outer } from '@formkit/inputs'; import type { CascadeSelectEmitsOptions, CascadeSelectProps } from 'primevue/cascadeselect'; import PrimevueCascadeselect from 'primevue/cascadeselect'; import { defineComponent, markRaw, ref } from 'vue'; import { floatLabel } from '../sections/floatLabel'; import { messages } from '../sections/messages'; import { help } from '../sections/help'; // https://formkit.com/inputs/dropdown type PrimevueSelectListeners = { 'onUpdate:modelValue': CascadeSelectEmitsOptions['update:modelValue']; 'onBlur': CascadeSelectEmitsOptions['blur']; }; const SchemaComponent = defineComponent( (vueProps: { context: FormKitFrameworkContext }) => { const formkitContext = vueProps.context; const listeners: PrimevueSelectListeners = { 'onUpdate:modelValue': (value: unknown) => { formkitContext.node.input(value); }, 'onBlur': async (e) => { setTimeout( () => formkitContext.handlers.blur.call(undefined, e as never), 166, // 因为会触发两次。所以让blur事件延迟一点,可以考虑优化。(Cascadeselect好像没有这个问题) ); }, }; const p_options = ref(); const loading = ref(true); const loadOptions = async () => { try { let result; if (formkitContext.options instanceof Promise) { result = await formkitContext.options; } else { console.warn('未支持的 options 类型 :>> ', typeof formkitContext.options); } p_options.value = result; } catch (error) { console.error('Failed to load options:', error); p_options.value = []; } finally { loading.value = false; } }; loadOptions(); // 立即加载options return () => { return ( ); }; }, // https://cn.vuejs.org/api/general#definecomponent // 目前仍然需要手动声明运行时的 props // 在将来,我们计划提供一个 Babel 插件,自动推断并注入运行时 props (就像在单文件组件中的 defineProps 一样),以便省略运行时 props 的声明。 { props: ['context'], }, ); const input = createSection('input', () => ({ $cmp: markRaw(SchemaComponent) as never, bind: '$attrs', props: { context: '$node.context', }, })); export const PCascadeSelect: FormKitTypeDefinition = { type: 'input', schema: outer( floatLabel( input(), // label('$label'), ), help('$help'), messages(), ), props: ['options', 'optionLabel', 'optionValue'], schemaMemoKey: '72psvunq45', // Math.random().toString(36).substring(2, 15) }; type OptionsType = CascadeSelectProps['options']; declare module '@formkit/inputs' { // https://formkit.com/essentials/custom-inputs#typescript-support interface FormKitInputProps> { PCascadeSelect: { type: 'PCascadeSelect'; options: Promise; optionLabel: string; optionValue: string; }; } }