Skip to content

Commit

Permalink
feat: SelectV2改造完成
Browse files Browse the repository at this point in the history
  • Loading branch information
kailong321200875 committed May 11, 2023
1 parent cdc7c76 commit 4d04734
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 75 deletions.
11 changes: 9 additions & 2 deletions src/components/Form/src/Form.vue
Expand Up @@ -21,7 +21,7 @@ import { set } from 'lodash-es'
import { FormProps } from './types'
import { Icon } from '@/components/Icon'
import { FormSchema, FormSetPropsType } from '@/types/form'
import { ComponentNameEnum, SelectComponentProps } from '@/types/components.d'
import { ComponentNameEnum, SelectComponentProps, SelectOption } from '@/types/components.d'
const { getPrefixCls } = useDesign()
Expand Down Expand Up @@ -188,6 +188,13 @@ export default defineComponent({
)
}
}
// 虚拟列表
if (item.component === ComponentNameEnum.SELECT_V2 && componentSlots.default) {
slotsMap.default = ({ item }: any) => {
return componentSlots.default(item)
}
}
// if (
// item?.component !== 'SelectV2' &&
// item?.component !== 'Cascader' &&
Expand Down Expand Up @@ -252,7 +259,7 @@ export default defineComponent({
const renderOptions = (item: FormSchema) => {
switch (item.component) {
case ComponentNameEnum.SELECT:
const { renderSelectOptions } = useRenderSelect(slots)
const { renderSelectOptions } = useRenderSelect()
return renderSelectOptions(item)
case 'Radio':
case 'RadioButton':
Expand Down
17 changes: 8 additions & 9 deletions src/components/Form/src/components/useRenderSelect.tsx
@@ -1,22 +1,21 @@
import { ElOption, ElOptionGroup } from 'element-plus'
import { getSlot } from '@/utils/tsxHelper'
import { Slots } from 'vue'
import { FormSchema } from '@/types/form'
import { SelectComponentProps, SelectOption } from '@/types/components'

export const useRenderSelect = (slots: Slots) => {
export const useRenderSelect = () => {
// 渲染 select options
const renderSelectOptions = (item: FormSchema) => {
const componentsProps = item.componentProps as SelectComponentProps
const optionGroupDefaultSlot = componentsProps.slots?.optionGroupDefault
// 如果有别名,就取别名
const labelAlias = componentsProps?.labelAlias
const keyAlias = componentsProps?.keyAlias
return componentsProps?.options?.map((option) => {
if (option?.options?.length) {
return optionGroupDefaultSlot ? (
optionGroupDefaultSlot(option)
) : (
<ElOptionGroup label={option[labelAlias || 'label']}>
<ElOptionGroup label={option[labelAlias || 'label']} key={option[keyAlias || 'key']}>
{{
default: () =>
option?.options?.map((v) => {
Expand All @@ -37,15 +36,15 @@ export const useRenderSelect = (slots: Slots) => {
const componentsProps = item.componentProps as SelectComponentProps
const labelAlias = componentsProps?.labelAlias
const valueAlias = componentsProps?.valueAlias
const keyAlias = componentsProps?.keyAlias
const optionDefaultSlot = componentsProps.slots?.optionDefault

const { label, value, ...other } = option

return (
<ElOption
{...other}
label={labelAlias ? option[labelAlias] : label}
value={valueAlias ? option[valueAlias] : value}
{...option}
key={option[keyAlias || 'key']}
label={option[labelAlias || 'label']}
value={option[valueAlias || 'value']}
>
{{
default: () => (optionDefaultSlot ? optionDefaultSlot(option) : undefined)
Expand Down
48 changes: 38 additions & 10 deletions src/components/Form/src/helper.ts
Expand Up @@ -2,9 +2,10 @@ import { useI18n } from '@/hooks/web/useI18n'
import { unref, type Slots } from 'vue'
import { getSlot } from '@/utils/tsxHelper'
import { PlaceholderMoel } from './types'
import { FormSchema } from '@/types/form'
import { ColProps } from '@/types/components'
import { FormSchema } from '@/types/form.d'
import { ColProps, ComponentNameEnum } from '@/types/components.d'
import { isFunction } from '@/utils/is'
import { firstUpperCase } from '@/utils'

const { t } = useI18n()

Expand All @@ -15,14 +16,25 @@ const { t } = useI18n()
* @description 用于自动设置placeholder
*/
export const setTextPlaceholder = (schema: FormSchema): PlaceholderMoel => {
const textMap = ['Input', 'Autocomplete', 'InputNumber', 'InputPassword']
const selectMap = ['Select', 'TimePicker', 'DatePicker', 'TimeSelect', 'TimeSelect']
if (textMap.includes(schema?.component as string)) {
const textMap = [
ComponentNameEnum.INPUT,
ComponentNameEnum.AUTOCOMPLETE,
ComponentNameEnum.INPUT_NUMBER,
ComponentNameEnum.INPUT_PASSWORD
]
const selectMap = [
ComponentNameEnum.SELECT,
ComponentNameEnum.TIME_PICKER,
ComponentNameEnum.DATE_PICKER,
ComponentNameEnum.TIME_SELECT,
ComponentNameEnum.SELECT_V2
]
if (textMap.includes(schema?.component as ComponentNameEnum)) {
return {
placeholder: t('common.inputText')
}
}
if (selectMap.includes(schema?.component as string)) {
if (selectMap.includes(schema?.component as ComponentNameEnum)) {
// 一些范围选择器
const twoTextMap = ['datetimerange', 'daterange', 'monthrange', 'datetimerange', 'daterange']
if (
Expand Down Expand Up @@ -74,14 +86,30 @@ export const setGridProp = (col: ColProps = {}): ColProps => {
*/
export const setComponentProps = (item: FormSchema): Recordable => {
// const notNeedClearable = ['ColorPicker']
// 拆分事件并组合
const onEvents = item?.componentProps?.on || {}
const newOnEvents: Recordable = {}

for (const key in onEvents) {
if (onEvents[key]) {
newOnEvents[`on${firstUpperCase(key)}`] = (...args: any[]) => {
onEvents[key](...args)
}
}
}

const componentProps: Recordable = {
clearable: true,
...item.componentProps
...item.componentProps,
...newOnEvents
}
// 需要删除额外的属性
if (componentProps.slots) {
delete componentProps.slots
}
if (componentProps.on) {
delete componentProps.on
}
return componentProps
}

Expand All @@ -95,8 +123,8 @@ export const setItemComponentSlots = (formModel: any, slotsProps: Recordable = {
for (const key in slotsProps) {
if (slotsProps[key]) {
if (isFunction(slotsProps[key])) {
slotObj[key] = () => {
return slotsProps[key]?.(formModel)
slotObj[key] = (...args: any[]) => {
return slotsProps[key]?.(formModel, ...args)
}
} else {
slotObj[key] = () => {
Expand Down Expand Up @@ -124,7 +152,7 @@ export const initModel = (schema: FormSchema[], formModel: Recordable) => {
} else if (v.component && v.component !== 'Divider') {
const hasField = Reflect.has(model, v.field)
// 如果先前已经有值存在,则不进行重新赋值,而是采用现有的值
model[v.field] = hasField ? model[v.field] : v.value !== void 0 ? v.value : ''
model[v.field] = hasField ? model[v.field] : v.value !== void 0 ? v.value : undefined
}
})
return model
Expand Down
50 changes: 48 additions & 2 deletions src/types/components.d.ts
Expand Up @@ -105,7 +105,7 @@ export interface AutocompleteComponentProps {
change?: (value: string | number) => void
}
slots?: {
default?: JSX.Element | null | ((formData: any) => JSX.Element | null)
default?: JSX.Element | null | ((formData: any, ...args: any[]) => JSX.Element | null)
prefix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
suffix?: JSX.Element | null | ((formData: any) => JSX.Element | null)
prepend?: JSX.Element | null | ((formData: any) => JSX.Element | null)
Expand Down Expand Up @@ -150,7 +150,7 @@ interface SelectOption {
}

export interface SelectComponentProps {
value?: Array | string | number | boolean | Object
value?: string | number | boolean | Object
multiple?: boolean
disabled?: boolean
valueKey?: string
Expand Down Expand Up @@ -230,6 +230,52 @@ export interface SelectComponentProps {
}
options?: SelectOption[]
style?: CSSProperties
style?: CSSProperties
}

export interface SelectV2ComponentProps {
value?: string | number | boolean | Object
multiple?: boolean
disabled?: boolean
valueKey?: string
size?: InputNumberProps['size']
clearable?: boolean
clearIcon?: string | JSX.Element | ((formData: any) => string | JSX.Element)
collapseTags?: boolean
multipleLimit?: number
name?: string
effect?: string
autocomplete?: string
placeholder?: string
filterable?: boolean
allowCreate?: boolean
reserveKeyword?: boolean
noDataText?: string
popperClass?: string
teleported?: boolean
persistent?: boolean
popperOptions?: any
automaticDropdown?: boolean
height?: number
scrollbarAlwaysOn?: boolean
remote?: boolean
remoteMethod?: (query: string) => void
validateEvent?: boolean
placement?: AutocompleteProps['placement']
collapseTagsTooltip?: boolean
on?: {
change?: (value: string | number | boolean | Object) => void
visibleChange?: (visible: boolean) => void
removeTag?: (tag: any) => void
clear?: () => void
blur?: (event: FocusEvent) => void
focus?: (event: FocusEvent) => void
}
options?: SelectOption[]
slots?: {
default?: (option: SelectOption) => JSX.Element | null
}
style?: CSSProperties
}

export interface ColProps {
Expand Down
4 changes: 3 additions & 1 deletion src/types/form.d.ts
Expand Up @@ -6,7 +6,8 @@ import {
InputComponentProps,
AutocompleteComponentProps,
InputNumberComponentProps,
SelectComponentProps
SelectComponentProps,
SelectV2ComponentProps
} from '@/types/components'
import { FormValueType, FormValueType } from '@/types/form'
import type { AxiosPromise } from 'axios'
Expand Down Expand Up @@ -58,6 +59,7 @@ export interface FormSchema {
| AutocompleteComponentProps
| InputNumberComponentProps
| SelectComponentProps
| SelectV2ComponentProps

/**
* formItem组件属性,具体可以查看element-plus文档
Expand Down
7 changes: 7 additions & 0 deletions src/utils/index.ts
Expand Up @@ -108,3 +108,10 @@ export function toAnyString() {
})
return str
}

/**
* 首字母大写
*/
export function firstUpperCase(str: string) {
return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase())
}

0 comments on commit 4d04734

Please sign in to comment.