wip: Form改造中
This commit is contained in:
parent
1d0f4b4c39
commit
2261f49976
|
@ -0,0 +1,302 @@
|
||||||
|
<script lang="tsx">
|
||||||
|
import { PropType, defineComponent, ref, computed, unref, watch, onMounted } from 'vue'
|
||||||
|
import { ElForm, ElFormItem, ElRow, ElCol, ElTooltip } from 'element-plus'
|
||||||
|
import { componentMap } from './componentMap'
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
import { getSlot } from '@/utils/tsxHelper'
|
||||||
|
import {
|
||||||
|
setTextPlaceholder,
|
||||||
|
setGridProp,
|
||||||
|
setComponentProps,
|
||||||
|
setItemComponentSlots,
|
||||||
|
initModel,
|
||||||
|
setFormItemSlots
|
||||||
|
} from './helper'
|
||||||
|
import { useRenderSelect } from './components/useRenderSelect'
|
||||||
|
import { useRenderRadio } from './components/useRenderRadio'
|
||||||
|
import { useRenderCheckbox } from './components/useRenderCheckbox'
|
||||||
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { findIndex } from '@/utils'
|
||||||
|
import { set } from 'lodash-es'
|
||||||
|
import { FormProps } from './types'
|
||||||
|
import { Icon } from '@/components/Icon'
|
||||||
|
import { FormSchema, FormSetPropsType } from '@/types/form'
|
||||||
|
|
||||||
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
|
const prefixCls = getPrefixCls('form')
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Form',
|
||||||
|
props: {
|
||||||
|
// 生成Form的布局结构数组
|
||||||
|
schema: {
|
||||||
|
type: Array as PropType<FormSchema[]>,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
// 是否需要栅格布局
|
||||||
|
isCol: propTypes.bool.def(true),
|
||||||
|
// 表单数据对象
|
||||||
|
model: {
|
||||||
|
type: Object as PropType<Recordable>,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
// 是否自动设置placeholder
|
||||||
|
autoSetPlaceholder: propTypes.bool.def(true),
|
||||||
|
// 是否自定义内容
|
||||||
|
isCustom: propTypes.bool.def(false),
|
||||||
|
// 表单label宽度
|
||||||
|
labelWidth: propTypes.oneOfType([String, Number]).def('auto')
|
||||||
|
},
|
||||||
|
emits: ['register'],
|
||||||
|
setup(props, { slots, expose, emit }) {
|
||||||
|
// element form 实例
|
||||||
|
const elFormRef = ref<ComponentRef<typeof ElForm>>()
|
||||||
|
|
||||||
|
// useForm传入的props
|
||||||
|
const outsideProps = ref<FormProps>({})
|
||||||
|
|
||||||
|
const mergeProps = ref<FormProps>({})
|
||||||
|
|
||||||
|
const getProps = computed(() => {
|
||||||
|
const propsObj = { ...props }
|
||||||
|
Object.assign(propsObj, unref(mergeProps))
|
||||||
|
return propsObj
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const formModel = ref<Recordable>({})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
emit('register', unref(elFormRef)?.$parent, unref(elFormRef))
|
||||||
|
})
|
||||||
|
|
||||||
|
// 对表单赋值
|
||||||
|
const setValues = (data: Recordable = {}) => {
|
||||||
|
formModel.value = Object.assign(unref(formModel), data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const setProps = (props: FormProps = {}) => {
|
||||||
|
mergeProps.value = Object.assign(unref(mergeProps), props)
|
||||||
|
outsideProps.value = props
|
||||||
|
}
|
||||||
|
|
||||||
|
const delSchema = (field: string) => {
|
||||||
|
const { schema } = unref(getProps)
|
||||||
|
|
||||||
|
const index = findIndex(schema, (v: FormSchema) => v.field === field)
|
||||||
|
if (index > -1) {
|
||||||
|
schema.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const addSchema = (formSchema: FormSchema, index?: number) => {
|
||||||
|
const { schema } = unref(getProps)
|
||||||
|
if (index !== void 0) {
|
||||||
|
schema.splice(index, 0, formSchema)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
schema.push(formSchema)
|
||||||
|
}
|
||||||
|
|
||||||
|
const setSchema = (schemaProps: FormSetPropsType[]) => {
|
||||||
|
const { schema } = unref(getProps)
|
||||||
|
for (const v of schema) {
|
||||||
|
for (const item of schemaProps) {
|
||||||
|
if (v.field === item.field) {
|
||||||
|
set(v, item.path, item.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getElFormRef = (): ComponentRef<typeof ElForm> => {
|
||||||
|
return unref(elFormRef) as ComponentRef<typeof ElForm>
|
||||||
|
}
|
||||||
|
|
||||||
|
expose({
|
||||||
|
setValues,
|
||||||
|
formModel,
|
||||||
|
setProps,
|
||||||
|
delSchema,
|
||||||
|
addSchema,
|
||||||
|
setSchema,
|
||||||
|
getElFormRef
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听表单结构化数组,重新生成formModel
|
||||||
|
watch(
|
||||||
|
() => unref(getProps).schema,
|
||||||
|
(schema = []) => {
|
||||||
|
formModel.value = initModel(schema, unref(formModel))
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 渲染包裹标签,是否使用栅格布局
|
||||||
|
const renderWrap = () => {
|
||||||
|
const { isCol } = unref(getProps)
|
||||||
|
const content = isCol ? (
|
||||||
|
<ElRow gutter={20}>{renderFormItemWrap()}</ElRow>
|
||||||
|
) : (
|
||||||
|
renderFormItemWrap()
|
||||||
|
)
|
||||||
|
return content
|
||||||
|
}
|
||||||
|
|
||||||
|
// 是否要渲染el-col
|
||||||
|
const renderFormItemWrap = () => {
|
||||||
|
// hidden属性表示隐藏,不做渲染
|
||||||
|
const { schema = [], isCol } = unref(getProps)
|
||||||
|
|
||||||
|
return schema
|
||||||
|
.filter((v) => !v.hidden)
|
||||||
|
.map((item) => {
|
||||||
|
// 如果是 Divider 组件,需要自己占用一行
|
||||||
|
const isDivider = item.component === 'Divider'
|
||||||
|
const Com = componentMap['Divider'] as ReturnType<typeof defineComponent>
|
||||||
|
return isDivider ? (
|
||||||
|
<Com {...{ contentPosition: 'left', ...item.componentProps }}>{item?.label}</Com>
|
||||||
|
) : isCol ? (
|
||||||
|
// 如果需要栅格,需要包裹 ElCol
|
||||||
|
<ElCol {...setGridProp(item.colProps)}>{renderFormItem(item)}</ElCol>
|
||||||
|
) : (
|
||||||
|
renderFormItem(item)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渲染formItem
|
||||||
|
const renderFormItem = (item: FormSchema) => {
|
||||||
|
// 单独给只有options属性的组件做判断
|
||||||
|
const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer']
|
||||||
|
const componentSlots = (item?.componentProps as any)?.slots || {}
|
||||||
|
const slotsMap: Recordable = {
|
||||||
|
...setItemComponentSlots(unref(formModel), componentSlots)
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
item?.component !== 'SelectV2' &&
|
||||||
|
item?.component !== 'Cascader' &&
|
||||||
|
item?.componentProps?.options
|
||||||
|
) {
|
||||||
|
slotsMap.default = () => renderOptions(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
const formItemSlots: Recordable = setFormItemSlots(slots, item.field)
|
||||||
|
// 如果有 labelMessage,自动使用插槽渲染
|
||||||
|
if (item?.labelMessage) {
|
||||||
|
formItemSlots.label = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span>{item.label}</span>
|
||||||
|
<ElTooltip placement="right" raw-content>
|
||||||
|
{{
|
||||||
|
content: () => <span v-html={item.labelMessage}></span>,
|
||||||
|
default: () => (
|
||||||
|
<Icon
|
||||||
|
icon="ep:warning"
|
||||||
|
size={16}
|
||||||
|
color="var(--el-color-primary)"
|
||||||
|
class="ml-2px relative top-1px"
|
||||||
|
></Icon>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</ElTooltip>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<ElFormItem {...(item.formItemProps || {})} prop={item.field} label={item.label || ''}>
|
||||||
|
{{
|
||||||
|
...formItemSlots,
|
||||||
|
default: () => {
|
||||||
|
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)
|
||||||
|
) : (
|
||||||
|
<Com
|
||||||
|
vModel={formModel.value[item.field]}
|
||||||
|
{...(autoSetPlaceholder && setTextPlaceholder(item))}
|
||||||
|
{...setComponentProps(item)}
|
||||||
|
style={item.componentProps?.style}
|
||||||
|
{...(notRenderOptions.includes(item?.component as string) &&
|
||||||
|
item?.componentProps?.options
|
||||||
|
? { options: item?.componentProps?.options || [] }
|
||||||
|
: {})}
|
||||||
|
>
|
||||||
|
{{ ...slotsMap }}
|
||||||
|
</Com>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
</ElFormItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 渲染options
|
||||||
|
const renderOptions = (item: FormSchema) => {
|
||||||
|
switch (item.component) {
|
||||||
|
case 'Select':
|
||||||
|
const { renderSelectOptions } = useRenderSelect(slots)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤传入Form组件的属性
|
||||||
|
const getFormBindValue = () => {
|
||||||
|
// 避免在标签上出现多余的属性
|
||||||
|
const delKeys = ['schema', 'isCol', 'autoSetPlaceholder', 'isCustom', 'model']
|
||||||
|
const props = { ...unref(getProps) }
|
||||||
|
for (const key in props) {
|
||||||
|
if (delKeys.indexOf(key) !== -1) {
|
||||||
|
delete props[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return props
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<ElForm
|
||||||
|
ref={elFormRef}
|
||||||
|
{...getFormBindValue()}
|
||||||
|
model={props.isCustom ? props.model : formModel}
|
||||||
|
class={prefixCls}
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
// 如果需要自定义,就什么都不渲染,而是提供默认插槽
|
||||||
|
default: () => {
|
||||||
|
const { isCustom } = unref(getProps)
|
||||||
|
return isCustom ? getSlot(slots, 'default') : renderWrap()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
</ElForm>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.@{elNamespace}-form.@{namespace}-form .@{elNamespace}-row {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -21,6 +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'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
|
@ -172,46 +173,55 @@ export default defineComponent({
|
||||||
// 渲染formItem
|
// 渲染formItem
|
||||||
const renderFormItem = (item: FormSchema) => {
|
const renderFormItem = (item: FormSchema) => {
|
||||||
// 单独给只有options属性的组件做判断
|
// 单独给只有options属性的组件做判断
|
||||||
const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer']
|
// const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer']
|
||||||
|
const componentSlots = (item?.componentProps as any)?.slots || {}
|
||||||
const slotsMap: Recordable = {
|
const slotsMap: Recordable = {
|
||||||
...setItemComponentSlots(unref(formModel), item?.componentProps?.slots)
|
...setItemComponentSlots(unref(formModel), componentSlots)
|
||||||
}
|
}
|
||||||
if (
|
// 如果是select组件,并且没有自定义模板,自动渲染options
|
||||||
item?.component !== 'SelectV2' &&
|
if (item.component === ComponentNameEnum.SELECT) {
|
||||||
item?.component !== 'Cascader' &&
|
slotsMap.default = !componentSlots.default
|
||||||
item?.componentProps?.options
|
? () => renderOptions(item)
|
||||||
) {
|
: (option: any) => {
|
||||||
slotsMap.default = () => renderOptions(item)
|
console.log(option)
|
||||||
|
return componentSlots.default(option)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// if (
|
||||||
|
// item?.component !== 'SelectV2' &&
|
||||||
|
// item?.component !== 'Cascader' &&
|
||||||
|
// item?.componentProps?.options
|
||||||
|
// ) {
|
||||||
|
// slotsMap.default = () => renderOptions(item)
|
||||||
|
// }
|
||||||
|
|
||||||
const formItemSlots: Recordable = setFormItemSlots(slots, item.field)
|
// const formItemSlots: Recordable = setFormItemSlots(slots, item.field)
|
||||||
// 如果有 labelMessage,自动使用插槽渲染
|
// 如果有 labelMessage,自动使用插槽渲染
|
||||||
if (item?.labelMessage) {
|
// if (item?.labelMessage) {
|
||||||
formItemSlots.label = () => {
|
// formItemSlots.label = () => {
|
||||||
return (
|
// return (
|
||||||
<>
|
// <>
|
||||||
<span>{item.label}</span>
|
// <span>{item.label}</span>
|
||||||
<ElTooltip placement="right" raw-content>
|
// <ElTooltip placement="right" raw-content>
|
||||||
{{
|
// {{
|
||||||
content: () => <span v-html={item.labelMessage}></span>,
|
// content: () => <span v-html={item.labelMessage}></span>,
|
||||||
default: () => (
|
// default: () => (
|
||||||
<Icon
|
// <Icon
|
||||||
icon="ep:warning"
|
// icon="ep:warning"
|
||||||
size={16}
|
// size={16}
|
||||||
color="var(--el-color-primary)"
|
// color="var(--el-color-primary)"
|
||||||
class="ml-2px relative top-1px"
|
// class="ml-2px relative top-1px"
|
||||||
></Icon>
|
// ></Icon>
|
||||||
)
|
// )
|
||||||
}}
|
// }}
|
||||||
</ElTooltip>
|
// </ElTooltip>
|
||||||
</>
|
// </>
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return (
|
return (
|
||||||
<ElFormItem {...(item.formItemProps || {})} prop={item.field} label={item.label || ''}>
|
<ElFormItem {...(item.formItemProps || {})} prop={item.field} label={item.label || ''}>
|
||||||
{{
|
{{
|
||||||
...formItemSlots,
|
|
||||||
default: () => {
|
default: () => {
|
||||||
const Com = componentMap[item.component as string] as ReturnType<
|
const Com = componentMap[item.component as string] as ReturnType<
|
||||||
typeof defineComponent
|
typeof defineComponent
|
||||||
|
@ -227,10 +237,6 @@ export default defineComponent({
|
||||||
{...(autoSetPlaceholder && setTextPlaceholder(item))}
|
{...(autoSetPlaceholder && setTextPlaceholder(item))}
|
||||||
{...setComponentProps(item)}
|
{...setComponentProps(item)}
|
||||||
style={item.componentProps?.style}
|
style={item.componentProps?.style}
|
||||||
{...(notRenderOptions.includes(item?.component as string) &&
|
|
||||||
item?.componentProps?.options
|
|
||||||
? { options: item?.componentProps?.options || [] }
|
|
||||||
: {})}
|
|
||||||
>
|
>
|
||||||
{{ ...slotsMap }}
|
{{ ...slotsMap }}
|
||||||
</Com>
|
</Com>
|
||||||
|
@ -244,7 +250,7 @@ export default defineComponent({
|
||||||
// 渲染options
|
// 渲染options
|
||||||
const renderOptions = (item: FormSchema) => {
|
const renderOptions = (item: FormSchema) => {
|
||||||
switch (item.component) {
|
switch (item.component) {
|
||||||
case 'Select':
|
case ComponentNameEnum.SELECT:
|
||||||
const { renderSelectOptions } = useRenderSelect(slots)
|
const { renderSelectOptions } = useRenderSelect(slots)
|
||||||
return renderSelectOptions(item)
|
return renderSelectOptions(item)
|
||||||
case 'Radio':
|
case 'Radio':
|
||||||
|
|
|
@ -2,14 +2,15 @@ import { ElOption, ElOptionGroup } from 'element-plus'
|
||||||
import { getSlot } from '@/utils/tsxHelper'
|
import { getSlot } from '@/utils/tsxHelper'
|
||||||
import { Slots } from 'vue'
|
import { Slots } from 'vue'
|
||||||
import { FormSchema } from '@/types/form'
|
import { FormSchema } from '@/types/form'
|
||||||
import { ComponentOptions } from '@/types/components'
|
import { SelectComponentProps, SelectOption } from '@/types/components'
|
||||||
|
|
||||||
export const useRenderSelect = (slots: Slots) => {
|
export const useRenderSelect = (slots: Slots) => {
|
||||||
// 渲染 select options
|
// 渲染 select options
|
||||||
const renderSelectOptions = (item: FormSchema) => {
|
const renderSelectOptions = (item: FormSchema) => {
|
||||||
|
const componentsProps = item.componentProps as SelectComponentProps
|
||||||
// 如果有别名,就取别名
|
// 如果有别名,就取别名
|
||||||
const labelAlias = item?.componentProps?.optionsAlias?.labelField
|
const labelAlias = componentsProps?.labelAlias
|
||||||
return item?.componentProps?.options?.map((option) => {
|
return componentsProps?.options?.map((option) => {
|
||||||
if (option?.options?.length) {
|
if (option?.options?.length) {
|
||||||
return (
|
return (
|
||||||
<ElOptionGroup label={option[labelAlias || 'label']}>
|
<ElOptionGroup label={option[labelAlias || 'label']}>
|
||||||
|
@ -27,10 +28,11 @@ export const useRenderSelect = (slots: Slots) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 渲染 select option item
|
// 渲染 select option item
|
||||||
const renderSelectOptionItem = (item: FormSchema, option: ComponentOptions) => {
|
const renderSelectOptionItem = (item: FormSchema, option: SelectOption) => {
|
||||||
// 如果有别名,就取别名
|
// 如果有别名,就取别名
|
||||||
const labelAlias = item?.componentProps?.optionsAlias?.labelField
|
const componentsProps = item.componentProps as SelectComponentProps
|
||||||
const valueAlias = item?.componentProps?.optionsAlias?.valueField
|
const labelAlias = componentsProps?.labelAlias
|
||||||
|
const valueAlias = componentsProps?.valueAlias
|
||||||
|
|
||||||
const { label, value, ...other } = option
|
const { label, value, ...other } = option
|
||||||
|
|
||||||
|
@ -43,7 +45,7 @@ export const useRenderSelect = (slots: Slots) => {
|
||||||
{{
|
{{
|
||||||
default: () =>
|
default: () =>
|
||||||
// option 插槽名规则,{field}-option
|
// option 插槽名规则,{field}-option
|
||||||
item?.componentProps?.optionsSlot
|
componentsProps?.optionsSlot
|
||||||
? getSlot(slots, `${item.field}-option`, { item: option })
|
? getSlot(slots, `${item.field}-option`, { item: option })
|
||||||
: undefined
|
: undefined
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -78,6 +78,7 @@ export interface InputComponentProps {
|
||||||
prepend?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
prepend?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
||||||
append?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
append?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
||||||
}
|
}
|
||||||
|
style?: CSSProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutocompleteComponentProps {
|
export interface AutocompleteComponentProps {
|
||||||
|
@ -110,6 +111,7 @@ export interface AutocompleteComponentProps {
|
||||||
prepend?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
prepend?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
||||||
append?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
append?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
||||||
}
|
}
|
||||||
|
style?: CSSProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InputNumberComponentProps {
|
export interface InputNumberComponentProps {
|
||||||
|
@ -135,6 +137,102 @@ export interface InputNumberComponentProps {
|
||||||
blur?: (event: FocusEvent) => void
|
blur?: (event: FocusEvent) => void
|
||||||
focus?: (event: FocusEvent) => void
|
focus?: (event: FocusEvent) => void
|
||||||
}
|
}
|
||||||
|
style?: CSSProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SelectOption {
|
||||||
|
label?: string
|
||||||
|
disabled?: boolean
|
||||||
|
value?: any
|
||||||
|
key?: string | number
|
||||||
|
options?: SelectOption[]
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SelectComponentProps {
|
||||||
|
value?: Array | string | number | boolean | Object
|
||||||
|
multiple?: boolean
|
||||||
|
disabled?: boolean
|
||||||
|
valueKey?: string
|
||||||
|
size?: InputNumberProps['size']
|
||||||
|
clearable?: boolean
|
||||||
|
collapseTags?: boolean
|
||||||
|
collapseTagsTooltip?: number
|
||||||
|
multipleLimit?: number
|
||||||
|
name?: string
|
||||||
|
effect?: string
|
||||||
|
autocomplete?: string
|
||||||
|
placeholder?: string
|
||||||
|
filterable?: boolean
|
||||||
|
allowCreate?: boolean
|
||||||
|
filterMethod?: (query: string, item: any) => boolean
|
||||||
|
remote?: boolean
|
||||||
|
remoteMethod?: (query: string) => void
|
||||||
|
remoteShowSuffix?: boolean
|
||||||
|
loading?: boolean
|
||||||
|
loadingText?: string
|
||||||
|
noMatchText?: string
|
||||||
|
noDataText?: string
|
||||||
|
popperClass?: string
|
||||||
|
reserveKeyword?: boolean
|
||||||
|
defaultFirstOption?: boolean
|
||||||
|
popperAppendToBody?: boolean
|
||||||
|
teleported?: boolean
|
||||||
|
persistent?: boolean
|
||||||
|
automaticDropdown?: boolean
|
||||||
|
clearIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element)
|
||||||
|
fitInputWidth?: boolean
|
||||||
|
suffixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element)
|
||||||
|
tagType?: 'success' | 'info' | 'warning' | 'danger'
|
||||||
|
validateEvent?: boolean
|
||||||
|
placement?:
|
||||||
|
| 'top'
|
||||||
|
| 'top-start'
|
||||||
|
| 'top-end'
|
||||||
|
| 'bottom'
|
||||||
|
| 'bottom-start'
|
||||||
|
| 'bottom-end'
|
||||||
|
| 'left'
|
||||||
|
| 'left-start'
|
||||||
|
| 'left-end'
|
||||||
|
| 'right'
|
||||||
|
| 'right-start'
|
||||||
|
| 'right-end'
|
||||||
|
maxCollapseTags?: number
|
||||||
|
/**
|
||||||
|
* label别名
|
||||||
|
*/
|
||||||
|
labelAlias?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* value别名
|
||||||
|
*/
|
||||||
|
valueAlias?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* key别名
|
||||||
|
*/
|
||||||
|
keyAlias?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* option是否禁用的统一拦截
|
||||||
|
*/
|
||||||
|
optionDisabled?: (optin: any, data: any) => 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
|
||||||
|
}
|
||||||
|
slots?: {
|
||||||
|
default?: (item: any) => JSX.Element
|
||||||
|
prefix?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
||||||
|
empty?: JSX.Element | ((item: any, data: any) => JSX.Element)
|
||||||
|
}
|
||||||
|
options?: SelectOption[]
|
||||||
|
style?: CSSProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ColProps {
|
export interface ColProps {
|
||||||
|
@ -149,7 +247,7 @@ export interface ColProps {
|
||||||
|
|
||||||
export interface ComponentOptions extends Recordable {
|
export interface ComponentOptions extends Recordable {
|
||||||
label?: string
|
label?: string
|
||||||
value?: FormValueType
|
value?: any
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
key?: string | number
|
key?: string | number
|
||||||
children?: ComponentOptions[]
|
children?: ComponentOptions[]
|
||||||
|
|
|
@ -5,7 +5,8 @@ import {
|
||||||
ComponentName,
|
ComponentName,
|
||||||
InputComponentProps,
|
InputComponentProps,
|
||||||
AutocompleteComponentProps,
|
AutocompleteComponentProps,
|
||||||
InputNumberComponentProps
|
InputNumberComponentProps,
|
||||||
|
SelectComponentProps
|
||||||
} from '@/types/components'
|
} from '@/types/components'
|
||||||
import { FormValueType, FormValueType } from '@/types/form'
|
import { FormValueType, FormValueType } from '@/types/form'
|
||||||
import type { AxiosPromise } from 'axios'
|
import type { AxiosPromise } from 'axios'
|
||||||
|
@ -52,7 +53,11 @@ export interface FormSchema {
|
||||||
/**
|
/**
|
||||||
* 表单组件属性,具体可以查看element-plus文档
|
* 表单组件属性,具体可以查看element-plus文档
|
||||||
*/
|
*/
|
||||||
componentProps?: InputComponentProps | AutocompleteComponentProps | InputNumberComponentProps
|
componentProps?:
|
||||||
|
| InputComponentProps
|
||||||
|
| AutocompleteComponentProps
|
||||||
|
| InputNumberComponentProps
|
||||||
|
| SelectComponentProps
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* formItem组件属性,具体可以查看element-plus文档
|
* formItem组件属性,具体可以查看element-plus文档
|
||||||
|
|
|
@ -499,49 +499,65 @@ const schema = reactive<FormSchema[]>([
|
||||||
controlsPosition: 'right'
|
controlsPosition: 'right'
|
||||||
},
|
},
|
||||||
value: 10
|
value: 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field13',
|
||||||
|
label: t('formDemo.select'),
|
||||||
|
component: 'Divider'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field14',
|
||||||
|
label: t('formDemo.default'),
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
optionDisabled: (item: any, data: any) => {
|
||||||
|
console.log(item, data)
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
disabled: true,
|
||||||
|
label: 'option1',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option2',
|
||||||
|
value: '2'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'field15',
|
||||||
|
label: t('formDemo.slot'),
|
||||||
|
component: 'Select',
|
||||||
|
componentProps: {
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: 'option1',
|
||||||
|
value: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'option2',
|
||||||
|
value: '2'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
slots: {
|
||||||
|
default: (item) => {
|
||||||
|
console.log(item)
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<span style="float: left">{item.label}</span>
|
||||||
|
<span style=" float: right; color: var(--el-text-color-secondary); font-size: 13px;">
|
||||||
|
{item.value}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
// field: 'field13',
|
|
||||||
// label: t('formDemo.select'),
|
|
||||||
// component: 'Divider'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// field: 'field14',
|
|
||||||
// label: t('formDemo.default'),
|
|
||||||
// component: 'Select',
|
|
||||||
// componentProps: {
|
|
||||||
// options: [
|
|
||||||
// {
|
|
||||||
// disabled: true,
|
|
||||||
// label: 'option1',
|
|
||||||
// value: '1'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: 'option2',
|
|
||||||
// value: '2'
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// field: 'field15',
|
|
||||||
// label: t('formDemo.slot'),
|
|
||||||
// component: 'Select',
|
|
||||||
// componentProps: {
|
|
||||||
// options: [
|
|
||||||
// {
|
|
||||||
// label: 'option1',
|
|
||||||
// value: '1'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: 'option2',
|
|
||||||
// value: '2'
|
|
||||||
// }
|
|
||||||
// ],
|
|
||||||
// optionsSlot: true
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// field: 'field16',
|
// field: 'field16',
|
||||||
// label: t('formDemo.selectGroup'),
|
// label: t('formDemo.selectGroup'),
|
||||||
// component: 'Select',
|
// component: 'Select',
|
||||||
|
|
Loading…
Reference in New Issue