feat: Radio改造

This commit is contained in:
kailong321200875 2023-05-23 15:36:33 +08:00
parent 64d436bf84
commit 83513d519d
10 changed files with 274 additions and 161 deletions

View File

@ -36,7 +36,7 @@
"dayjs": "^1.11.7",
"echarts": "^5.4.2",
"echarts-wordcloud": "^2.1.0",
"element-plus": "2.3.5",
"element-plus": "^2.3.5",
"intro.js": "^7.0.1",
"lodash-es": "^4.17.21",
"mitt": "^3.0.0",

View File

@ -21,7 +21,16 @@ import { set } from 'lodash-es'
import { FormProps } from './types'
import { Icon } from '@/components/Icon'
import { FormSchema, FormSetPropsType } from '@/types/form'
import { ComponentNameEnum, SelectComponentProps, SelectOption } from '@/types/components.d'
import {
ComponentNameEnum,
SelectComponentProps,
SelectOption,
RadioComponentProps
} from '@/types/components.d'
const { renderSelectOptions } = useRenderSelect()
const { renderRadioOptions } = useRenderRadio()
const { renderCheckboxOptions } = useRenderCheckbox()
const { getPrefixCls } = useDesign()
@ -181,7 +190,7 @@ export default defineComponent({
// selectoptions
if (item.component === ComponentNameEnum.SELECT) {
slotsMap.default = !componentSlots.default
? () => renderOptions(item)
? () => renderSelectOptions(item)
: () => {
return componentSlots.default(
unref((item?.componentProps as SelectComponentProps)?.options)
@ -231,15 +240,42 @@ export default defineComponent({
<ElFormItem {...(item.formItemProps || {})} prop={item.field} label={item.label || ''}>
{{
default: () => {
if (slots[item.field]) {
return getSlot(slots, item.field, formModel.value)
} else {
const Com = componentMap[item.component as string] as ReturnType<
typeof defineComponent
>
const { autoSetPlaceholder } = unref(getProps)
return slots[item.field] ? (
getSlot(slots, item.field, formModel.value)
) : (
//
const specialComponents = [ComponentNameEnum.RADIO]
if (specialComponents.findIndex((v) => v === item.component) !== -1) {
switch (item.component) {
case ComponentNameEnum.RADIO:
const componentProps = item.componentProps as RadioComponentProps
const valueAlias = componentProps?.props?.value || 'value'
const labelAlias = componentProps?.props?.label || 'label'
const disabledAlias = componentProps?.props?.disabled || 'disabled'
return componentProps?.options?.map((v) => {
return (
<Com
vModel={formModel.value[item.field]}
{...setComponentProps(item)}
label={v[valueAlias]}
disabled={v[disabledAlias]}
>
{v[labelAlias]}
</Com>
)
})
}
}
return (
<Com
vModel={formModel.value[item.field]}
{...(autoSetPlaceholder && setTextPlaceholder(item))}
@ -250,29 +286,27 @@ export default defineComponent({
</Com>
)
}
}
}}
</ElFormItem>
)
}
// options
const renderOptions = (item: FormSchema) => {
switch (item.component) {
case ComponentNameEnum.SELECT:
const { renderSelectOptions } = useRenderSelect()
return renderSelectOptions(item)
case 'Radio':
case 'RadioButton':
const { renderRadioOptions } = useRenderRadio()
return renderRadioOptions(item)
case 'Checkbox':
case 'CheckboxButton':
const { renderCheckboxOptions } = useRenderCheckbox()
return renderCheckboxOptions(item)
default:
break
}
}
// const renderOptions = (item: FormSchema) => {
// switch (item.component) {
// case ComponentNameEnum.SELECT:
// return renderSelectOptions(item)
// case ComponentNameEnum.RADIO:
// case 'RadioButton':
// return renderRadioOptions(item)
// case 'Checkbox':
// case 'CheckboxButton':
// return renderCheckboxOptions(item)
// default:
// break
// }
// }
// Form
const getFormBindValue = () => {

View File

@ -16,14 +16,16 @@ import {
ElTimeSelect,
ElTransfer,
ElAutocomplete,
ElDivider
ElDivider,
ElRadio
} from 'element-plus'
import { InputPassword } from '@/components/InputPassword'
import { Editor } from '@/components/Editor'
import { ComponentName } from '@/types/components'
const componentMap: Recordable<Component, ComponentName> = {
Radio: ElRadioGroup,
Radio: ElRadio,
// RadioGroup: ElRadioGroup,
Checkbox: ElCheckboxGroup,
CheckboxButton: ElCheckboxGroup,
Input: ElInput,

View File

@ -1,9 +1,13 @@
import { FormSchema } from '@/types/form'
import { ElRadio, ElRadioButton } from 'element-plus'
import { defineComponent } from 'vue'
import { ComponentNameEnum } from '@/types/components.d'
export const useRenderRadio = () => {
const renderRadioOptions = (item: FormSchema) => {
const renderRadioOptions = (
item: FormSchema,
type?: ComponentNameEnum.RADIO | ComponentNameEnum.RADIO_BUTTON = ComponentNameEnum.RADIO
) => {
// 如果有别名,就取别名
const labelAlias = item?.componentProps?.optionsAlias?.labelField
const valueAlias = item?.componentProps?.optionsAlias?.valueField

View File

@ -8,8 +8,8 @@ export const useRenderSelect = () => {
const componentsProps = item.componentProps as SelectComponentProps
const optionGroupDefaultSlot = componentsProps.slots?.optionGroupDefault
// 如果有别名,就取别名
const labelAlias = componentsProps?.labelAlias
const keyAlias = componentsProps?.keyAlias
const labelAlias = componentsProps?.props?.label
const keyAlias = componentsProps?.props?.key
return componentsProps?.options?.map((option) => {
if (option?.options?.length) {
return optionGroupDefaultSlot ? (
@ -34,9 +34,9 @@ export const useRenderSelect = () => {
const renderSelectOptionItem = (item: FormSchema, option: SelectOption) => {
// 如果有别名,就取别名
const componentsProps = item.componentProps as SelectComponentProps
const labelAlias = componentsProps?.labelAlias
const valueAlias = componentsProps?.valueAlias
const keyAlias = componentsProps?.keyAlias
const labelAlias = componentsProps?.props?.label
const valueAlias = componentsProps?.props?.value
const keyAlias = componentsProps?.props?.key
const optionDefaultSlot = componentsProps.slots?.optionDefault
return (

View File

@ -5,7 +5,7 @@ import { PlaceholderMoel } from './types'
import { FormSchema } from '@/types/form.d'
import { ColProps, ComponentNameEnum } from '@/types/components.d'
import { isFunction } from '@/utils/is'
import { firstUpperCase } from '@/utils'
import { firstUpperCase, humpToDash } from '@/utils'
const { t } = useI18n()
@ -123,11 +123,11 @@ export const setItemComponentSlots = (slotsProps: Recordable = {}): Recordable =
for (const key in slotsProps) {
if (slotsProps[key]) {
if (isFunction(slotsProps[key])) {
slotObj[key] = (...args: any[]) => {
slotObj[humpToDash(key)] = (...args: any[]) => {
return slotsProps[key]?.(...args)
}
} else {
slotObj[key] = () => {
slotObj[humpToDash(key)] = () => {
return slotsProps[key]
}
}

View File

@ -1,4 +1,4 @@
import { CSSProperties } from 'vue'
import { CSSProperties, VNodeProps, VNode } from 'vue'
import {
InputProps,
AutocompleteProps,
@ -148,7 +148,7 @@ export interface InputNumberComponentProps {
style?: CSSProperties
}
interface SelectOption {
export interface SelectOption {
label?: string
disabled?: boolean
value?: any
@ -208,19 +208,14 @@ export interface SelectComponentProps {
| 'right-end'
maxCollapseTags?: number
/**
* label别
*
*/
labelAlias?: string
/**
* value别名
*/
valueAlias?: string
/**
* key别名
*/
keyAlias?: string
props?: {
key?: string
value?: string
label?: string
children?: string
}
on?: {
change?: (value: string | number | boolean | Object) => void
visibleChange?: (visible: boolean) => void
@ -390,14 +385,17 @@ export interface ColorPickerComponentProps {
export interface TransferComponentProps {
value?: any[]
data?: Array<{ key; label; disabled }>
data?: any[]
filterable?: boolean
filterPlaceholder?: string
filterMethod?: (query: string, item: any) => boolean
targetOrder?: string
titles?: string[]
buttonTexts?: string[]
renderContent?: (h: any, option: any) => JSX.Element
renderContent?: (
h: (type: string, props: VNodeProps | null, children?: string) => VNode,
option: any
) => JSX.Element
format?: {
noChecked?: string
hasChecked?: string
@ -411,7 +409,11 @@ export interface TransferComponentProps {
rightDefaultChecked?: any[]
validateEvent?: boolean
on?: {
change?: (value: any[]) => void
change?: (
value: number | string,
direction: 'left' | 'right',
movedKeys: string[] | number[]
) => void
leftCheckChange?: (value: any[]) => void
rightCheckChange?: (value: any[]) => void
}
@ -423,6 +425,36 @@ export interface TransferComponentProps {
style?: CSSProperties
}
export interface RadioOption {
label?: string
value?: string | number | boolean
disabled?: boolean
[key: string]: any
}
export interface RadioComponentProps {
value?: string | number | boolean
label?: string | number | boolean
disabled?: boolean
border?: boolean
size?: ElementPlusSize
options?: RadioOption[]
/**
*
*/
props: {
label?: string
value?: string
disabled?: string
}
name?: string
on?: {
change?: (value: string | number | boolean) => void
}
slots?: {
default?: (...args: any[]) => JSX.Element | null
}
}
export interface ColProps {
span?: number
xs?: number

26
src/types/form.d.ts vendored
View File

@ -12,7 +12,8 @@ import {
SwitchComponentProps,
RateComponentProps,
ColorPickerComponentProps,
TransferComponentProps
TransferComponentProps,
RadioComponentProps
} from '@/types/components'
import { FormValueType, FormValueType } from '@/types/form'
import type { AxiosPromise } from 'axios'
@ -36,26 +37,28 @@ export type FormItemProps = {
}
// 定义联合类型和条件类型
type ComponentPropsForComponent<T extends ComponentName> = T extends 'input'
type ComponentPropsForComponent<T extends ComponentName> = T extends 'Input'
? InputComponentProps
: T extends 'autocomplete'
: T extends 'Autocomplete'
? AutocompleteComponentProps
: T extends 'inputNumber'
: T extends 'InputNumber'
? InputNumberComponentProps
: T extends 'select'
: T extends 'Select'
? SelectComponentProps
: T extends 'selectV2'
: T extends 'SelectV2'
? SelectV2ComponentProps
: T extends 'cascader'
: T extends 'Cascader'
? CascaderComponentProps
: T extends 'switch'
: T extends 'Switch'
? SwitchComponentProps
: T extends 'rate'
: T extends 'Rate'
? RateComponentProps
: T extends 'colorPicker'
: T extends 'ColorPicker'
? ColorPickerComponentProps
: T extends 'transfer'
: T extends 'Transfer'
? TransferComponentProps
: T extends 'Radio'
? RadioComponentProps
: any
export interface FormSchema {
@ -93,6 +96,7 @@ export interface FormSchema {
| RateComponentProps
| ColorPickerComponentProps
| TransferComponentProps
| RadioComponentProps
/**
* formItem组件属性element-plus文档

View File

@ -36,6 +36,13 @@ export const underlineToHump = (str: string): string => {
})
}
/**
*
*/
export const humpToDash = (str: string): string => {
return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}
export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
dom.style.setProperty(prop, val)
}

View File

@ -8,7 +8,7 @@ import { useAppStore } from '@/store/modules/app'
import { FormSchema } from '@/types/form'
import { ComponentOptions, SelectOption, SelectComponentProps } from '@/types/components'
import { useForm } from '@/hooks/web/useForm'
import { ElOption, ElOptionGroup } from 'element-plus'
import { ElOption, ElOptionGroup, ElButton } from 'element-plus'
const appStore = useAppStore()
@ -840,91 +840,116 @@ const schema = reactive<FormSchema[]>([
field: 'field34',
label: t('formDemo.transfer'),
component: 'Divider'
},
{
field: 'field35',
label: t('formDemo.default'),
component: 'Transfer',
componentProps: {
props: {
key: 'value',
label: 'desc'
},
data: generateData()
},
value: [],
colProps: {
span: 24
}
// {
// field: 'field35',
// label: t('formDemo.default'),
// component: 'Transfer',
// componentProps: {
// props: {
// key: 'value',
// label: 'desc',
// disabled: 'disabled'
// },
// data: generateData()
// },
// value: [],
// colProps: {
// span: 24
// }
// },
// {
// field: 'field36',
// label: t('formDemo.slot'),
// component: 'Transfer',
// componentProps: {
// props: {
// key: 'value',
// label: 'desc',
// disabled: 'disabled'
// },
// leftDefaultChecked: [2, 3],
// rightDefaultChecked: [1],
// data: generateData(),
// slots: {
// default: true
// }
// },
// value: [1],
// colProps: {
// span: 24
// }
// },
// {
// field: 'field37',
// label: `${t('formDemo.render')}`,
// component: 'Transfer',
// componentProps: {
// props: {
// key: 'value',
// label: 'desc',
// disabled: 'disabled'
// },
// leftDefaultChecked: [2, 3],
// rightDefaultChecked: [1],
// data: generateData(),
// renderContent: (h: Fn, option: Recordable) => {
// return h('span', null, `${option.value} - ${option.desc}`)
// }
// },
// value: [1],
// colProps: {
// span: 24
// }
// },
// {
// field: 'field38',
// label: t('formDemo.radio'),
// component: 'Divider'
// },
// {
// field: 'field39',
// label: t('formDemo.default'),
// component: 'Radio',
// componentProps: {
// options: [
// {
},
{
field: 'field36',
label: t('formDemo.slot'),
component: 'Transfer',
componentProps: {
props: {
key: 'value',
label: 'desc'
},
filterable: true,
leftDefaultChecked: [2, 3],
rightDefaultChecked: [1],
titles: ['Source', 'Target'],
buttonTexts: ['To Left', 'To Right'],
format: {
noChecked: '${total}',
hasChecked: '${checked}/${total}'
},
data: generateData(),
slots: {
default: ({ option }) => {
return (
<span>
{option.value} - {option.desc}
</span>
)
},
leftFooter: () => {
return (
<ElButton class="transfer-footer" size="small">
Operation
</ElButton>
)
},
rightFooter: () => {
return (
<ElButton class="transfer-footer" size="small">
Operation
</ElButton>
)
}
}
},
value: [1],
colProps: {
span: 24
}
},
{
field: 'field37',
label: `${t('formDemo.render')}`,
component: 'Transfer',
componentProps: {
props: {
key: 'value',
label: 'desc',
disabled: 'disabled'
},
leftDefaultChecked: [2, 3],
rightDefaultChecked: [1],
data: generateData(),
renderContent: (h, option) => {
return h('span', null, `${option.value} - ${option.desc}`)
}
},
value: [1],
colProps: {
span: 24
}
},
{
field: 'field38',
label: t('formDemo.radio'),
component: 'Divider'
},
{
field: 'field39',
label: t('formDemo.default'),
component: 'Radio',
componentProps: {
options: [
{
// disabled: true,
// label: 'option-1',
// value: '1'
// },
// {
// label: 'option-2',
// value: '2'
// }
// ]
// }
// },
label: 'option-1',
value: '1'
},
{
label: 'option-2',
value: '2'
}
]
}
}
// {
// field: 'field40',
// label: t('formDemo.button'),
@ -1360,4 +1385,9 @@ const changeToggle = () => {
transform: translateX(-50%);
}
}
.transfer-footer {
margin-left: 15px;
padding: 6px 5px;
}
</style>