wip: Form改造中

This commit is contained in:
kailong321200875 2023-05-10 10:14:11 +08:00
parent 46ac7f88c9
commit 998d9f3eeb
8 changed files with 184 additions and 123 deletions

View File

@ -21,7 +21,7 @@ import { set } from 'lodash-es'
import { FormProps } from './types' import { FormProps } from './types'
import { Icon } from '@/components/Icon' import { Icon } from '@/components/Icon'
import { FormSchema, FormSetPropsType } from '@/types/form' import { FormSchema, FormSetPropsType } from '@/types/form'
import { ComponentNameEnum } from '@/types/components.d' import { ComponentNameEnum, SelectComponentProps } from '@/types/components.d'
const { getPrefixCls } = useDesign() const { getPrefixCls } = useDesign()
@ -182,9 +182,10 @@ export default defineComponent({
if (item.component === ComponentNameEnum.SELECT) { if (item.component === ComponentNameEnum.SELECT) {
slotsMap.default = !componentSlots.default slotsMap.default = !componentSlots.default
? () => renderOptions(item) ? () => renderOptions(item)
: (option: any) => { : () => {
console.log(option) return componentSlots.default(
return componentSlots.default(option) unref((item?.componentProps as SelectComponentProps)?.options)
)
} }
} }
// if ( // if (

View File

@ -8,16 +8,20 @@ export const useRenderSelect = (slots: Slots) => {
// 渲染 select options // 渲染 select options
const renderSelectOptions = (item: FormSchema) => { const renderSelectOptions = (item: FormSchema) => {
const componentsProps = item.componentProps as SelectComponentProps const componentsProps = item.componentProps as SelectComponentProps
const optionGroupDefaultSlot = componentsProps.slots?.optionGroupDefault
// 如果有别名,就取别名 // 如果有别名,就取别名
const labelAlias = componentsProps?.labelAlias const labelAlias = componentsProps?.labelAlias
return componentsProps?.options?.map((option) => { return componentsProps?.options?.map((option) => {
if (option?.options?.length) { if (option?.options?.length) {
return ( return optionGroupDefaultSlot ? (
optionGroupDefaultSlot(option)
) : (
<ElOptionGroup label={option[labelAlias || 'label']}> <ElOptionGroup label={option[labelAlias || 'label']}>
{() => { {{
return option?.options?.map((v) => { default: () =>
return renderSelectOptionItem(item, v) option?.options?.map((v) => {
}) return renderSelectOptionItem(item, v)
})
}} }}
</ElOptionGroup> </ElOptionGroup>
) )
@ -33,6 +37,7 @@ export const useRenderSelect = (slots: Slots) => {
const componentsProps = item.componentProps as SelectComponentProps const componentsProps = item.componentProps as SelectComponentProps
const labelAlias = componentsProps?.labelAlias const labelAlias = componentsProps?.labelAlias
const valueAlias = componentsProps?.valueAlias const valueAlias = componentsProps?.valueAlias
const optionDefaultSlot = componentsProps.slots?.optionDefault
const { label, value, ...other } = option const { label, value, ...other } = option
@ -43,11 +48,7 @@ export const useRenderSelect = (slots: Slots) => {
value={valueAlias ? option[valueAlias] : value} value={valueAlias ? option[valueAlias] : value}
> >
{{ {{
default: () => default: () => (optionDefaultSlot ? optionDefaultSlot(option) : undefined)
// option 插槽名规则,{field}-option
componentsProps?.optionsSlot
? getSlot(slots, `${item.field}-option`, { item: option })
: undefined
}} }}
</ElOption> </ElOption>
) )

View File

@ -95,8 +95,8 @@ export const setItemComponentSlots = (formModel: any, slotsProps: Recordable = {
for (const key in slotsProps) { for (const key in slotsProps) {
if (slotsProps[key]) { if (slotsProps[key]) {
if (isFunction(slotsProps[key])) { if (isFunction(slotsProps[key])) {
slotObj[key] = (item: any) => { slotObj[key] = () => {
return slotsProps[key]?.(unref(item?.item) || undefined, formModel) return slotsProps[key]?.(formModel)
} }
} else { } else {
slotObj[key] = () => { slotObj[key] = () => {

View File

@ -202,7 +202,7 @@ const clear = () => {
<template> <template>
<div <div
:class="prefixCls" :class="prefixCls"
class="fixed top-[45%] right-0 w-40px h-40px text-center leading-40px bg-[var(--el-color-primary)] cursor-pointer" class="fixed top-[45%] right-0 w-40px h-40px flex items-center justify-center bg-[var(--el-color-primary)] cursor-pointer"
@click="drawer = true" @click="drawer = true"
> >
<Icon icon="ant-design:setting-outlined" color="#fff" /> <Icon icon="ant-design:setting-outlined" color="#fff" />

View File

@ -221,6 +221,7 @@ export default {
position: 'Position', position: 'Position',
autocomplete: 'Autocomplete', autocomplete: 'Autocomplete',
select: 'Select', select: 'Select',
optionSlot: 'Option Slot',
selectGroup: 'Select Group', selectGroup: 'Select Group',
selectV2: 'SelectV2', selectV2: 'SelectV2',
cascader: 'Cascader', cascader: 'Cascader',

View File

@ -221,6 +221,7 @@ export default {
position: '位置', position: '位置',
autocomplete: '自动补全', autocomplete: '自动补全',
select: '选择器', select: '选择器',
optionSlot: '选项插槽',
selectGroup: '选项分组', selectGroup: '选项分组',
selectV2: '虚拟列表选择器', selectV2: '虚拟列表选择器',
cascader: '级联选择器', cascader: '级联选择器',

View File

@ -47,8 +47,8 @@ export interface InputComponentProps {
showPassword?: boolean showPassword?: boolean
disabled?: boolean disabled?: boolean
size?: InputProps['size'] size?: InputProps['size']
prefixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element) prefixIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
suffixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element) suffixIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
type?: InputProps['type'] type?: InputProps['type']
rows?: number rows?: number
autosize?: boolean | { Pows?: numer; maxRows?: number } autosize?: boolean | { Pows?: numer; maxRows?: number }
@ -73,10 +73,10 @@ export interface InputComponentProps {
input?: (value: string | number) => void input?: (value: string | number) => void
} }
slots?: { slots?: {
prefix?: JSX.Element | ((item: any, data: any) => JSX.Element) prefix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
suffix?: JSX.Element | ((item: any, data: any) => JSX.Element) suffix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
prepend?: JSX.Element | ((item: any, data: any) => JSX.Element) prepend?: JSX.Element | null | ((formData: any) => JSX.Element | null)
append?: JSX.Element | ((item: any, data: any) => JSX.Element) append?: JSX.Element | null | ((formData: any) => JSX.Element | null)
} }
style?: CSSProperties style?: CSSProperties
} }
@ -105,11 +105,11 @@ export interface AutocompleteComponentProps {
change?: (value: string | number) => void change?: (value: string | number) => void
} }
slots?: { slots?: {
default?: JSX.Element | ((item: any, data: any) => JSX.Element) default?: JSX.Element | null | ((formData: any) => JSX.Element | null)
prefix?: JSX.Element | ((item: any, data: any) => JSX.Element) prefix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
suffix?: JSX.Element | ((item: any, data: any) => JSX.Element) suffix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
prepend?: JSX.Element | ((item: any, data: any) => JSX.Element) prepend?: JSX.Element | null | ((formData: any) => JSX.Element | null)
append?: JSX.Element | ((item: any, data: any) => JSX.Element) append?: JSX.Element | null | ((formData: any) => JSX.Element | null)
} }
style?: CSSProperties style?: CSSProperties
} }
@ -180,9 +180,9 @@ export interface SelectComponentProps {
teleported?: boolean teleported?: boolean
persistent?: boolean persistent?: boolean
automaticDropdown?: boolean automaticDropdown?: boolean
clearIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element) clearIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
fitInputWidth?: boolean fitInputWidth?: boolean
suffixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element) suffixIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
tagType?: 'success' | 'info' | 'warning' | 'danger' tagType?: 'success' | 'info' | 'warning' | 'danger'
validateEvent?: boolean validateEvent?: boolean
placement?: placement?:
@ -213,11 +213,6 @@ export interface SelectComponentProps {
* key别名 * key别名
*/ */
keyAlias?: string keyAlias?: string
/**
* option是否禁用的统一拦截
*/
optionDisabled?: (optin: any, data: any) => boolean
on?: { on?: {
change?: (value: string | number | boolean | Object) => void change?: (value: string | number | boolean | Object) => void
visibleChange?: (visible: boolean) => void visibleChange?: (visible: boolean) => void
@ -227,9 +222,11 @@ export interface SelectComponentProps {
focus?: (event: FocusEvent) => void focus?: (event: FocusEvent) => void
} }
slots?: { slots?: {
default?: (item: any) => JSX.Element default?: (options: SelectOption[]) => JSX.Element[] | null
prefix?: JSX.Element | ((item: any, data: any) => JSX.Element) optionGroupDefault?: (item: SelectOption) => JSX.Element
empty?: JSX.Element | ((item: any, data: any) => JSX.Element) optionDefault?: (option: SelectOption) => JSX.Element | null
prefix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
empty?: JSX.Element | null | ((formData: any) => JSX.Element | null)
} }
options?: SelectOption[] options?: SelectOption[]
style?: CSSProperties style?: CSSProperties

View File

@ -6,8 +6,9 @@ import { useIcon } from '@/hooks/web/useIcon'
import { ContentWrap } from '@/components/ContentWrap' import { ContentWrap } from '@/components/ContentWrap'
import { useAppStore } from '@/store/modules/app' import { useAppStore } from '@/store/modules/app'
import { FormSchema } from '@/types/form' import { FormSchema } from '@/types/form'
import { ComponentOptions } from '@/types/components' import { ComponentOptions, SelectOption, SelectComponentProps } from '@/types/components'
import { useForm } from '@/hooks/web/useForm' import { useForm } from '@/hooks/web/useForm'
import { ElOption, ElOptionGroup } from 'element-plus'
const appStore = useAppStore() const appStore = useAppStore()
@ -393,7 +394,7 @@ const schema = reactive<FormSchema[]>([
component: 'Input', component: 'Input',
componentProps: { componentProps: {
slots: { slots: {
suffix: (_, data: any) => { suffix: (data: any) => {
return unref(toggle) && data.field4 return unref(toggle) && data.field4
? useIcon({ icon: 'ep:calendar' }) ? useIcon({ icon: 'ep:calendar' })
: useIcon({ icon: 'ep:share' }) : useIcon({ icon: 'ep:share' })
@ -409,7 +410,7 @@ const schema = reactive<FormSchema[]>([
componentProps: { componentProps: {
slots: { slots: {
prepend: useIcon({ icon: 'ep:calendar' }), prepend: useIcon({ icon: 'ep:calendar' }),
append: (_, data: any) => { append: (data: any) => {
return data.field5 ? useIcon({ icon: 'ep:calendar' }) : useIcon({ icon: 'ep:share' }) return data.field5 ? useIcon({ icon: 'ep:calendar' }) : useIcon({ icon: 'ep:share' })
} }
} }
@ -510,10 +511,6 @@ const schema = reactive<FormSchema[]>([
label: t('formDemo.default'), label: t('formDemo.default'),
component: 'Select', component: 'Select',
componentProps: { componentProps: {
optionDisabled: (item: any, data: any) => {
console.log(item, data)
return false
},
options: [ options: [
{ {
disabled: true, disabled: true,
@ -543,94 +540,157 @@ const schema = reactive<FormSchema[]>([
} }
], ],
slots: { slots: {
default: (item) => { default: (options: SelectOption[]) => {
console.log(item) if (options.length) {
return options?.map((v) => {
return <ElOption key={v.value} label={v.label} value={v.value} />
})
} else {
return null
}
},
prefix: useIcon({ icon: 'ep:calendar' }),
empty: (data: any) => {
return data.field5 ? useIcon({ icon: 'ep:calendar' }) : useIcon({ icon: 'ep:share' })
}
}
}
},
{
field: 'select-field18',
label: t('formDemo.optionSlot'),
component: 'Select',
componentProps: {
options: [
{
value: 'Beijing',
label: 'Beijing'
},
{
value: 'Shanghai',
label: 'Shanghai'
},
{
value: 'Nanjing',
label: 'Nanjing'
},
{
value: 'Chengdu',
label: 'Chengdu'
},
{
value: 'Shenzhen',
label: 'Shenzhen'
},
{
value: 'Guangzhou',
label: 'Guangzhou'
}
],
slots: {
optionDefault: (option: SelectOption) => {
return ( return (
<> <>
<span style="float: left">{item.label}</span> <span style="float: left">{option.label}</span>
<span style=" float: right; color: var(--el-text-color-secondary); font-size: 13px;"> <span style="float: right; color: var(--el-text-color-secondary); font-size: 13px;">
{item.value} {option.value}
</span> </span>
</> </>
) )
} }
} }
} }
},
{
field: 'field16',
label: t('formDemo.selectGroup'),
component: 'Select',
componentProps: {
options: [
{
label: 'option1',
options: [
{
disabled: true,
label: 'option1-1',
value: '1-1'
},
{
label: 'option1-2',
value: '1-2'
}
]
},
{
label: 'option2',
options: [
{
label: 'option2-1',
value: '2-1'
},
{
label: 'option2-2',
value: '2-2'
}
]
}
]
}
},
{
field: 'field17',
label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
component: 'Select',
componentProps: {
options: [
{
label: 'option1',
options: [
{
label: 'option1-1',
value: '1-1'
},
{
label: 'option1-2',
value: '1-2'
}
]
},
{
label: 'option2',
options: [
{
label: 'option2-1',
value: '2-1'
},
{
label: 'option2-2',
value: '2-2'
}
]
}
],
slots: {
optionGroupDefault: (option: SelectOption) => {
return (
<ElOptionGroup key={option.label} label={`${option.label} ${option.label}`}>
{option?.options?.map((v) => {
return (
<ElOption
key={v.value}
disabled={unref(toggle)}
label={v.label}
value={v.value}
/>
)
})}
</ElOptionGroup>
)
}
}
}
} }
// { // {
// field: 'field16',
// label: t('formDemo.selectGroup'),
// component: 'Select',
// componentProps: {
// options: [
// {
// label: 'option1',
// options: [
// {
// disabled: true,
// label: 'option1-1',
// value: '1-1'
// },
// {
// label: 'option1-2',
// value: '1-2'
// }
// ]
// },
// {
// label: 'option2',
// options: [
// {
// label: 'option2-1',
// value: '2-1'
// },
// {
// label: 'option2-2',
// value: '2-2'
// }
// ]
// }
// ]
// }
// },
// {
// field: 'field17',
// label: `${t('formDemo.selectGroup')}${t('formDemo.slot')}`,
// component: 'Select',
// componentProps: {
// options: [
// {
// label: 'option1',
// options: [
// {
// label: 'option1-1',
// value: '1-1',
// disabled: true
// },
// {
// label: 'option1-2',
// value: '1-2'
// }
// ]
// },
// {
// label: 'option2',
// options: [
// {
// label: 'option2-1',
// value: '2-1'
// },
// {
// label: 'option2-2',
// value: '2-2'
// }
// ]
// }
// ],
// optionsSlot: true
// }
// },
// {
// field: 'field18', // field: 'field18',
// label: `${t('formDemo.selectV2')}`, // label: `${t('formDemo.selectV2')}`,
// component: 'Divider' // component: 'Divider'