<template>
    <EleText v-if="item.type === 'label'" v-bind="item.props || {}">
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot :name="item.slots?.[name]" v-bind="slotProps || {}"></slot>
        </template>
        <template
            v-if="
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
        >
            <template v-if="item.label != null && item.label !== ''">
                {{ item.label }}
            </template>
            <ProFormContent
                v-if="item.children && item.children.length"
                :model="model"
                :rules="rules"
                :items="item.children"
                :grid="item.grid"
                :rowProps="item.rowProps"
                :formItems="formItems"
                :searchExpand="searchExpand"
                @updateItemValue="updateItemValue"
            >
                <template
                    v-for="name in Object.keys($slots)"
                    #[name]="slotProps"
                >
                    <slot :name="name" v-bind="slotProps || {}"></slot>
                </template>
            </ProFormContent>
        </template>
    </EleText>
    <ElDivider v-else-if="item.type === 'divider'" v-bind="item.props || {}">
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot :name="item.slots?.[name]" v-bind="slotProps || {}"></slot>
        </template>
        <template
            v-if="
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
        >
            <template v-if="item.label != null && item.label !== ''">
                {{ item.label }}
            </template>
            <ProFormContent
                v-if="item.children && item.children.length"
                :model="model"
                :rules="rules"
                :items="item.children"
                :grid="item.grid"
                :rowProps="item.rowProps"
                :formItems="formItems"
                :searchExpand="searchExpand"
                @updateItemValue="updateItemValue"
            >
                <template
                    v-for="name in Object.keys($slots)"
                    #[name]="slotProps"
                >
                    <slot :name="name" v-bind="slotProps || {}"></slot>
                </template>
            </ProFormContent>
        </template>
    </ElDivider>
    <ElButton
        v-else-if="item.type === 'button'"
        type="primary"
        v-bind="item.props || {}"
    >
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot :name="item.slots?.[name]" v-bind="slotProps || {}"></slot>
        </template>
        <template
            v-if="
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
        >
            <template v-if="item.label != null && item.label !== ''">
                {{ item.label }}
            </template>
            <ProFormContent
                v-if="item.children && item.children.length"
                :model="model"
                :rules="rules"
                :items="item.children"
                :grid="item.grid"
                :rowProps="item.rowProps"
                :formItems="formItems"
                :searchExpand="searchExpand"
                @updateItemValue="updateItemValue"
            >
                <template
                    v-for="name in Object.keys($slots)"
                    #[name]="slotProps"
                >
                    <slot :name="name" v-bind="slotProps || {}"></slot>
                </template>
            </ProFormContent>
        </template>
    </ElButton>
    <EleSteps
        v-else-if="item.type === 'steps'"
        :active="model[item.prop] ?? 0"
        v-bind="item.props || {}"
    >
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot :name="item.slots?.[name]" v-bind="slotProps || {}"></slot>
        </template>
    </EleSteps>
    <EleCard
        v-else-if="item.type === 'card'"
        :header="item.label"
        :bordered="true"
        v-bind="item.props || {}"
    >
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot
                :name="item.slots?.[name]"
                v-bind="slotProps || {}"
                :proForm="{
                    item: item,
                    model: model,
                    rules: rules,
                    formItems: formItems,
                    searchExpand: searchExpand,
                    updateItemValue: updateItemValue,
                    slots: $slots
                }"
            ></slot>
        </template>
        <ProFormContent
            v-if="
                item.children &&
                item.children.length &&
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
            :model="model"
            :rules="rules"
            :items="item.children"
            :grid="item.grid"
            :rowProps="item.rowProps"
            :formItems="formItems"
            :searchExpand="searchExpand"
            @updateItemValue="updateItemValue"
        >
            <template v-for="name in Object.keys($slots)" #[name]="slotProps">
                <slot :name="name" v-bind="slotProps || {}"></slot>
            </template>
        </ProFormContent>
    </EleCard>
    <EleTabs
        v-else-if="item.type === 'tabs'"
        type="border-card"
        :modelValue="
            model[item.prop] ??
            (item.children?.length ? item.children[0].prop : void 0)
        "
        v-bind="item.props || {}"
        :items="
            item.children
                ? item.children.map((c) => ({
                      name: c.prop,
                      label: c.label,
                      slot: 'itemContent',
                      meta: c
                  })) || []
                : []
        "
        @update:modelValue="updateValue"
    >
        <template #itemContent="{ item: tabItem }">
            <slot
                v-if="
                    tabItem.meta.slots &&
                    tabItem.meta.slots.default &&
                    $slots[tabItem.meta.slots.default]
                "
                :name="tabItem.meta.slots.default"
                :proForm="{
                    item: tabItem,
                    model: model,
                    rules: rules,
                    formItems: formItems,
                    searchExpand: searchExpand,
                    updateItemValue: updateItemValue,
                    slots: $slots
                }"
            ></slot>
            <ProFormContent
                v-else-if="
                    tabItem.meta.children && tabItem.meta.children.length
                "
                :model="model"
                :rules="rules"
                :items="tabItem.meta.children"
                :grid="tabItem.meta.grid"
                :rowProps="tabItem.meta.rowProps"
                :formItems="formItems"
                :searchExpand="searchExpand"
                @updateItemValue="updateItemValue"
            >
                <template
                    v-for="name in Object.keys($slots)"
                    #[name]="slotProps"
                >
                    <slot :name="name" v-bind="slotProps || {}"></slot>
                </template>
            </ProFormContent>
        </template>
    </EleTabs>
    <EleTable
        v-else-if="
            item.type === 'table' ||
            (item.type === 'div' &&
                item.props?.is &&
                ['ele-table', 'EleTable'].includes(item.props.is))
        "
        v-bind="item.props ? { ...item.props, is: void 0 } : {}"
    >
        <slot
            v-if="
                item.slots && item.slots.default && $slots[item.slots.default]
            "
            :name="item.slots?.default"
            :proForm="{
                item: item,
                model: model,
                rules: rules,
                formItems: formItems,
                searchExpand: searchExpand,
                updateItemValue: updateItemValue,
                slots: $slots
            }"
        ></slot>
        <ProFormContent
            v-else-if="item.children && item.children.length"
            :model="model"
            :rules="rules"
            :items="item.children"
            :grid="item.grid"
            :rowProps="item.rowProps"
            :formItems="formItems"
            :searchExpand="searchExpand"
            @updateItemValue="updateItemValue"
        >
            <template v-for="name in Object.keys($slots)" #[name]="slotProps">
                <slot :name="name" v-bind="slotProps || {}"></slot>
            </template>
        </ProFormContent>
    </EleTable>
    <ElCollapse
        v-else-if="item.type === 'collapse'"
        :modelValue="
            model[item.prop] ??
            (item.props?.accordion
                ? item.children?.length
                    ? (item.children[0].props?.name ?? item.children[0].prop)
                    : void 0
                : [])
        "
        v-bind="item.props || {}"
        @update:modelValue="updateValue"
    >
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot
                :name="item.slots?.[name]"
                v-bind="slotProps || {}"
                :proForm="{
                    item: item,
                    model: model,
                    rules: rules,
                    formItems: formItems,
                    searchExpand: searchExpand,
                    updateItemValue: updateItemValue,
                    slots: $slots
                }"
            ></slot>
        </template>
        <ProFormContent
            v-if="
                item.children &&
                item.children.length &&
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
            :model="model"
            :rules="rules"
            :items="item.children"
            :grid="item.grid"
            :rowProps="item.rowProps"
            :formItems="formItems"
            :searchExpand="searchExpand"
            @updateItemValue="updateItemValue"
        >
            <template v-for="name in Object.keys($slots)" #[name]="slotProps">
                <slot :name="name" v-bind="slotProps || {}"></slot>
            </template>
        </ProFormContent>
    </ElCollapse>
    <ElCollapseItem
        v-else-if="item.type === 'collapseItem'"
        :title="item.label"
        :name="item.prop"
        v-bind="item.props || {}"
    >
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot
                :name="item.slots?.[name]"
                v-bind="slotProps || {}"
                :proForm="{
                    item: item,
                    model: model,
                    rules: rules,
                    formItems: formItems,
                    searchExpand: searchExpand,
                    updateItemValue: updateItemValue,
                    slots: $slots
                }"
            ></slot>
        </template>
        <ProFormContent
            v-if="
                item.children &&
                item.children.length &&
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
            :model="model"
            :rules="rules"
            :items="item.children"
            :grid="item.grid"
            :rowProps="item.rowProps"
            :formItems="formItems"
            :searchExpand="searchExpand"
            @updateItemValue="updateItemValue"
        >
            <template v-for="name in Object.keys($slots)" #[name]="slotProps">
                <slot :name="name" v-bind="slotProps || {}"></slot>
            </template>
        </ProFormContent>
    </ElCollapseItem>
    <ElRow v-else-if="item.type === 'row'" v-bind="item.props || {}">
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot
                :name="item.slots?.[name]"
                v-bind="slotProps || {}"
                :proForm="{
                    item: item,
                    model: model,
                    rules: rules,
                    formItems: formItems,
                    searchExpand: searchExpand,
                    updateItemValue: updateItemValue,
                    slots: $slots
                }"
            ></slot>
        </template>
        <ProFormContent
            v-if="
                item.children &&
                item.children.length &&
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
            :model="model"
            :rules="rules"
            :items="item.children"
            :grid="item.grid"
            :rowProps="item.rowProps"
            :formItems="formItems"
            :searchExpand="searchExpand"
            @updateItemValue="updateItemValue"
        >
            <template v-for="name in Object.keys($slots)" #[name]="slotProps">
                <slot :name="name" v-bind="slotProps || {}"></slot>
            </template>
        </ProFormContent>
    </ElRow>
    <ElCol v-else-if="item.type === 'col'" v-bind="item.props || {}">
        <template
            v-for="name in Object.keys(item.slots || {}).filter(
                (k) => !!(item.slots && item.slots[k] && $slots[item.slots[k]])
            )"
            #[name]="slotProps"
        >
            <slot
                :name="item.slots?.[name]"
                v-bind="slotProps || {}"
                :proForm="{
                    item: item,
                    model: model,
                    rules: rules,
                    formItems: formItems,
                    searchExpand: searchExpand,
                    updateItemValue: updateItemValue,
                    slots: $slots
                }"
            ></slot>
        </template>
        <ProFormContent
            v-if="
                item.children &&
                item.children.length &&
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
            :model="model"
            :rules="rules"
            :items="item.children"
            :grid="item.grid"
            :rowProps="item.rowProps"
            :formItems="formItems"
            :searchExpand="searchExpand"
            @updateItemValue="updateItemValue"
        >
            <template v-for="name in Object.keys($slots)" #[name]="slotProps">
                <slot :name="name" v-bind="slotProps || {}"></slot>
            </template>
        </ProFormContent>
    </ElCol>
    <component
        v-else-if="item.type === 'div'"
        v-bind="item.props ? { ...item.props, is: void 0 } : {}"
        :is="item.props?.is || 'div'"
    >
        <template
            v-if="
                !(
                    item.slots &&
                    item.slots.default &&
                    $slots[item.slots.default]
                )
            "
        >
            <template v-if="item.label != null && item.label !== ''">
                {{ item.label }}
            </template>
            <ProFormContent
                v-if="item.children && item.children.length"
                :model="model"
                :rules="rules"
                :items="item.children"
                :grid="item.grid"
                :rowProps="item.rowProps"
                :formItems="formItems"
                :searchExpand="searchExpand"
                @updateItemValue="updateItemValue"
            >
                <template
                    v-for="name in Object.keys($slots)"
                    #[name]="slotProps"
                >
                    <slot :name="name" v-bind="slotProps || {}"></slot>
                </template>
            </ProFormContent>
        </template>
        <slot
            v-else
            :name="item.slots?.default"
            :proForm="{
                item: item,
                model: model,
                rules: rules,
                formItems: formItems,
                searchExpand: searchExpand,
                updateItemValue: updateItemValue,
                slots: $slots
            }"
        ></slot>
    </component>
    <slot
        v-else-if="
            item.type &&
            !defaultTypes.includes(item.type) &&
            (item.itemType === 'view' || item.itemType === 'container')
        "
        :name="item.type"
        :item="item"
        :model="model"
        :updateValue="updateValue"
        :proForm="{
            item: item,
            model: model,
            rules: rules,
            formItems: formItems,
            searchExpand: searchExpand,
            updateItemValue: updateItemValue,
            slots: $slots
        }"
    ></slot>
    <ElFormItem
        v-else
        :label="item.label"
        v-bind="item.itemProps || {}"
        :prop="item.prop"
        :rules="itemRules"
    >
        <template
            v-for="name in Object.keys(item.itemSlots || {}).filter(
                (k) =>
                    !!(
                        item.itemSlots &&
                        item.itemSlots[k] &&
                        $slots[item.itemSlots[k]]
                    )
            )"
            #[name]="slotProps"
        >
            <slot
                :name="item.itemSlots?.[name]"
                v-bind="slotProps || {}"
            ></slot>
        </template>
        <ElInput
            v-if="item.type === 'input'"
            :clearable="true"
            :placeholder="'请输入' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElInput>
        <ElInput
            v-else-if="item.type === 'textarea'"
            :rows="4"
            :placeholder="'请输入' + item.label"
            v-bind="item.props || {}"
            type="textarea"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElInput>
        <ElSelect
            v-else-if="item.type === 'select'"
            class="ele-fluid"
            :clearable="true"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
            <ElOption
                v-for="opt in item.options || []"
                :key="opt.key ?? opt.value"
                :label="opt.label"
                :value="opt.value"
                :disabled="opt.disabled"
            />
        </ElSelect>
        <ElSelect
            v-else-if="item.type === 'multipleSelect'"
            class="ele-fluid"
            :clearable="true"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :multiple="true"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
            <ElOption
                v-for="opt in item.options || []"
                :key="opt.key ?? opt.value"
                :label="opt.label"
                :value="opt.value"
                :disabled="opt.disabled"
            />
        </ElSelect>
        <ElRadioGroup
            v-else-if="item.type === 'radio'"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <ElRadio
                v-for="opt in item.options || []"
                :key="opt.key ?? opt.value"
                :value="opt.value"
                :label="opt.label"
                :disabled="opt.disabled"
            />
        </ElRadioGroup>
        <ElRadioGroup
            v-else-if="item.type === 'radioButton'"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <ElRadioButton
                v-for="opt in item.options || []"
                :key="opt.key ?? opt.value"
                :value="opt.value"
                :label="opt.label"
                :disabled="opt.disabled"
            />
        </ElRadioGroup>
        <ElCheckboxGroup
            v-else-if="item.type === 'checkbox'"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <ElCheckbox
                v-for="opt in item.options || []"
                :key="opt.key ?? opt.value"
                :value="opt.value"
                :label="opt.label"
                :disabled="opt.disabled"
            />
        </ElCheckboxGroup>
        <ElCheckboxGroup
            v-else-if="item.type === 'checkboxButton'"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <ElCheckboxButton
                v-for="opt in item.options || []"
                :key="opt.key ?? opt.value"
                :value="opt.value"
                :label="opt.label"
                :disabled="opt.disabled"
            />
        </ElCheckboxGroup>
        <ElDatePicker
            v-else-if="item.type === 'date'"
            valueFormat="YYYY-MM-DD"
            class="ele-fluid"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElDatePicker>
        <ElDatePicker
            v-else-if="item.type === 'datetime'"
            valueFormat="YYYY-MM-DD HH:mm:ss"
            class="ele-fluid"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            type="datetime"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElDatePicker>
        <ElDatePicker
            v-else-if="item.type === 'daterange'"
            valueFormat="YYYY-MM-DD"
            rangeSeparator="-"
            startPlaceholder="开始日期"
            endPlaceholder="结束日期"
            :unlinkPanels="true"
            class="ele-fluid"
            type="daterange"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElDatePicker>
        <ElDatePicker
            v-else-if="item.type === 'datetimerange'"
            valueFormat="YYYY-MM-DD HH:mm:ss"
            rangeSeparator="-"
            startPlaceholder="开始时间"
            endPlaceholder="结束时间"
            :unlinkPanels="true"
            class="ele-fluid"
            v-bind="item.props || {}"
            type="datetimerange"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElDatePicker>
        <ElTimePicker
            v-else-if="item.type === 'time'"
            valueFormat="HH:mm:ss"
            class="ele-fluid"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElTimePicker>
        <ElTimePicker
            v-else-if="item.type === 'timerange'"
            valueFormat="HH:mm:ss"
            rangeSeparator="-"
            startPlaceholder="开始时间"
            end-placeholder="结束时间"
            class="ele-fluid"
            v-bind="item.props || {}"
            :isRange="true"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElTimePicker>
        <ElTimeSelect
            v-else-if="item.type === 'timeSelect'"
            class="ele-fluid"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        />
        <ElSwitch
            v-else-if="item.type === 'switch'"
            :active-value="1"
            :inactive-value="0"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElSwitch>
        <ElInputNumber
            v-else-if="item.type === 'inputNumber'"
            class="ele-fluid"
            controls-position="right"
            :placeholder="'请输入' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElInputNumber>
        <ElAutocomplete
            v-else-if="item.type === 'autocomplete'"
            class="ele-fluid"
            :fetchSuggestions="
                (_keyword, callback) => callback(item.options || [])
            "
            :placeholder="'请输入' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElAutocomplete>
        <ElCascader
            v-else-if="item.type === 'cascader'"
            class="ele-fluid"
            :clearable="true"
            :options="item.options || []"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElCascader>
        <ElRate
            v-else-if="item.type === 'rate'"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElRate>
        <ElSlider
            v-else-if="item.type === 'slider'"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElSlider>
        <ElSlider
            v-else-if="item.type === 'sliderRange'"
            v-bind="item.props || {}"
            :range="true"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElSlider>
        <ElTreeSelect
            v-else-if="item.type === 'treeSelect'"
            class="ele-fluid"
            :clearable="true"
            :data="item.options"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElTreeSelect>
        <ElTreeSelect
            v-else-if="item.type === 'treeMultipleSelect'"
            class="ele-fluid"
            :clearable="true"
            :data="item.options"
            :placeholder="'请选择' + item.label"
            :show-checkbox="true"
            v-bind="item.props || {}"
            :multiple="true"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ElTreeSelect>
        <EleTreeSelect
            v-else-if="item.type === 'virtualTreeSelect'"
            :clearable="true"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </EleTreeSelect>
        <EleTreeSelect
            v-else-if="item.type === 'virtualTreeMultipleSelect'"
            :clearable="true"
            :placeholder="'请选择' + item.label"
            :maxTagCount="1"
            v-bind="item.props || {}"
            :multiple="true"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </EleTreeSelect>
        <EleTableSelect
            v-else-if="item.type === 'tableSelect'"
            :clearable="true"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </EleTableSelect>
        <EleTableSelect
            v-else-if="item.type === 'tableMultipleSelect'"
            :clearable="true"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :multiple="true"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </EleTableSelect>
        <EleCheckCard
            v-else-if="item.type === 'checkCard'"
            :items="item.options"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </EleCheckCard>
        <EleCheckCard
            v-else-if="item.type === 'multipleCheckCard'"
            :items="item.options"
            v-bind="item.props || {}"
            :multiple="true"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </EleCheckCard>
        <EleEditTag
            v-else-if="item.type === 'editTag'"
            type="info"
            :style="{ marginTop: '4px' }"
            :itemStyle="{ margin: '0 4px 4px 0' }"
            :buttonStyle="{ marginBottom: '4px' }"
            :inputTagStyle="{ marginBottom: '4px' }"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </EleEditTag>
        <DictData
            v-else-if="item.type === 'dictRadio'"
            code=""
            v-bind="item.props || {}"
            type="radio"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </DictData>
        <DictData
            v-else-if="item.type === 'dictSelect'"
            code=""
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            type="select"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </DictData>
        <DictData
            v-else-if="item.type === 'dictCheckbox'"
            code=""
            v-bind="item.props || {}"
            type="checkbox"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </DictData>
        <DictData
            v-else-if="item.type === 'dictMultipleSelect'"
            code=""
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            type="multipleSelect"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </DictData>
        <ImageUpload
            v-else-if="item.type === 'imageUpload'"
            v-bind="item.props || {}"
            ref="imageUploadRef"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </ImageUpload>
        <FileUpload
            v-else-if="item.type === 'fileUpload'"
            v-bind="item.props || {}"
            ref="fileUploadRef"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </FileUpload>
        <RegionsSelect
            v-else-if="item.type === 'regions'"
            :placeholder="'请选择' + item.label"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </RegionsSelect>
        <TinymceEditor
            v-else-if="item.type === 'editor'"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        >
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </TinymceEditor>
        <EleText v-else-if="item.type === 'text'" v-bind="item.props || {}">
            <template
                v-if="
                    !(
                        item.slots &&
                        item.slots.default &&
                        $slots[item.slots.default]
                    )
                "
            >
                {{ model[item.prop] }}
            </template>
            <template
                v-for="name in Object.keys(item.slots || {}).filter(
                    (k) =>
                        !!(item.slots && item.slots[k] && $slots[item.slots[k]])
                )"
                #[name]="slotProps"
            >
                <slot
                    :name="item.slots?.[name]"
                    v-bind="slotProps || {}"
                ></slot>
            </template>
        </EleText>

        <InputNumberRange
            v-else-if="item.type === 'inputNumberRange'"
            class="ele-fluid"
            v-bind="item.props || {}"
            :modelValue="model[item.prop]"
            @update:modelValue="updateValue"
        />

        <slot
            v-else-if="item.type"
            :name="item.type"
            :item="item"
            :model="model"
            :updateValue="updateValue"
        ></slot>
    </ElFormItem>
</template>

<script setup>
    import { computed, ref } from 'vue';
    import { ElCarousel, ElCarouselItem, ElIcon } from 'element-plus/es';
    import { EleAlert, EleAdminLayout } from 'ele-admin-plus/es';
    import TinymceEditor from '@/components/TinymceEditor/index.vue';
    import RegionsSelect from '@/components/RegionsSelect/index.vue';
    import ImageUpload from '@/components/ImageUpload/index.vue';
    import FileUpload from '@/components/FileUpload/index.vue';
    import InputNumberRange from '@/components/CommonPage/InputNumberRange.vue';
    import {
        defaultTypes,
        uploadTypes,
        getRuleTrigger,
        getRuleMessage
    } from '../util';
    import ProFormContent from './pro-form-content.vue';

    // 用于 div 的 is
    defineOptions({
        components: {
            ElCarousel,
            ElCarouselItem,
            ElIcon,
            EleAlert,
            EleAdminLayout
        }
    });

    const props = defineProps({
        /** 表单项配置 */
        item: {
            type: Object,
            required: true
        },
        /** 表单数据 */
        model: {
            type: Object,
            required: true
        },
        /** 验证规则 */
        rules: Object,
        /** 全部的表单项 */
        formItems: Array,
        /** 搜索表单展开状态 */
        searchExpand: Boolean
    });

    const emit = defineEmits(['updateItemValue']);

    /** 更新值 */
    const updateValue = (value) => {
        if (props.item.prop != null) {
            updateItemValue(props.item.prop, value);
        }
    };

    /** 更新表单项值 */
    const updateItemValue = (prop, value) => {
        emit('updateItemValue', prop, value);
    };

    /** 图片上传组件实例 */
    const imageUploadRef = ref(null);

    /** 文件上传组件实例 */
    const fileUploadRef = ref(null);

    /** 判断上传组件是否上传完毕 */
    const uploadIsDone = () => {
        if (props.item.type === 'imageUpload') {
            return imageUploadRef.value ? imageUploadRef.value.isDone() : true;
        }
        if (props.item.type === 'fileUpload') {
            return fileUploadRef.value ? fileUploadRef.value.isDone() : true;
        }
        return true;
    };

    /** 表单验证规则 */
    const itemRules = computed(() => {
        const itemProps = props.item.itemProps;
        const iRule = itemProps ? itemProps.rules : void 0;
        const iRules = iRule
            ? Array.isArray(iRule)
                ? iRule
                : [iRule]
            : void 0;
        const fRule = props.rules ? props.rules[props.item.prop] : void 0;
        const fRules = fRule
            ? Array.isArray(fRule)
                ? fRule
                : [fRule]
            : void 0;
        const rules = iRules || fRules || [];
        const trigger = getRuleTrigger(props.item.type);
        const message = getRuleMessage(props.item.type, props.item.label);
        if (props.item.required) {
            rules.unshift({ required: true, message, trigger });
        }
        if (props.item.type && uploadTypes.includes(props.item.type)) {
            const validator = (_rule, value, callback) => {
                if (value && !uploadIsDone()) {
                    return callback(
                        new Error(`${props.item.label ?? ''}还未上传完毕`)
                    );
                }
                callback();
            };
            rules.push({ trigger, validator });
        }
        return rules;
    });
</script>
