Merge branch 'v2' of github.com:kailong321200875/vue-element-plus-admin into v2

This commit is contained in:
hongxinzz 2023-04-28 17:51:04 +08:00
commit c72ac07de9
9 changed files with 736 additions and 174 deletions

View File

@ -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>>()
// useFormprops
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>

View File

@ -21,6 +21,7 @@ import { set } from 'lodash-es'
import { FormProps } from './types'
import { Icon } from '@/components/Icon'
import { FormSchema, FormSetPropsType } from '@/types/form'
import { ComponentNameEnum } from '@/types/components.d'
const { getPrefixCls } = useDesign()
@ -172,46 +173,55 @@ export default defineComponent({
// formItem
const renderFormItem = (item: FormSchema) => {
// options
const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer']
// const notRenderOptions = ['SelectV2', 'Cascader', 'Transfer']
const componentSlots = (item?.componentProps as any)?.slots || {}
const slotsMap: Recordable = {
...setItemComponentSlots(unref(formModel), item?.componentProps?.slots)
...setItemComponentSlots(unref(formModel), componentSlots)
}
if (
item?.component !== 'SelectV2' &&
item?.component !== 'Cascader' &&
item?.componentProps?.options
) {
slotsMap.default = () => renderOptions(item)
// selectoptions
if (item.component === ComponentNameEnum.SELECT) {
slotsMap.default = !componentSlots.default
? () => renderOptions(item)
: (option: any) => {
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使
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>
</>
)
}
}
// 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
@ -227,10 +237,6 @@ export default defineComponent({
{...(autoSetPlaceholder && setTextPlaceholder(item))}
{...setComponentProps(item)}
style={item.componentProps?.style}
{...(notRenderOptions.includes(item?.component as string) &&
item?.componentProps?.options
? { options: item?.componentProps?.options || [] }
: {})}
>
{{ ...slotsMap }}
</Com>
@ -244,7 +250,7 @@ export default defineComponent({
// options
const renderOptions = (item: FormSchema) => {
switch (item.component) {
case 'Select':
case ComponentNameEnum.SELECT:
const { renderSelectOptions } = useRenderSelect(slots)
return renderSelectOptions(item)
case 'Radio':

View File

@ -2,14 +2,15 @@ import { ElOption, ElOptionGroup } from 'element-plus'
import { getSlot } from '@/utils/tsxHelper'
import { Slots } from 'vue'
import { FormSchema } from '@/types/form'
import { ComponentOptions } from '@/types/components'
import { SelectComponentProps, SelectOption } from '@/types/components'
export const useRenderSelect = (slots: Slots) => {
// 渲染 select options
const renderSelectOptions = (item: FormSchema) => {
const componentsProps = item.componentProps as SelectComponentProps
// 如果有别名,就取别名
const labelAlias = item?.componentProps?.optionsAlias?.labelField
return item?.componentProps?.options?.map((option) => {
const labelAlias = componentsProps?.labelAlias
return componentsProps?.options?.map((option) => {
if (option?.options?.length) {
return (
<ElOptionGroup label={option[labelAlias || 'label']}>
@ -27,10 +28,11 @@ export const useRenderSelect = (slots: Slots) => {
}
// 渲染 select option item
const renderSelectOptionItem = (item: FormSchema, option: ComponentOptions) => {
const renderSelectOptionItem = (item: FormSchema, option: SelectOption) => {
// 如果有别名,就取别名
const labelAlias = item?.componentProps?.optionsAlias?.labelField
const valueAlias = item?.componentProps?.optionsAlias?.valueField
const componentsProps = item.componentProps as SelectComponentProps
const labelAlias = componentsProps?.labelAlias
const valueAlias = componentsProps?.valueAlias
const { label, value, ...other } = option
@ -43,7 +45,7 @@ export const useRenderSelect = (slots: Slots) => {
{{
default: () =>
// option 插槽名规则,{field}-option
item?.componentProps?.optionsSlot
componentsProps?.optionsSlot
? getSlot(slots, `${item.field}-option`, { item: option })
: undefined
}}

View File

@ -1,5 +1,5 @@
import { useI18n } from '@/hooks/web/useI18n'
import type { Slots } from 'vue'
import { unref, type Slots } from 'vue'
import { getSlot } from '@/utils/tsxHelper'
import { PlaceholderMoel } from './types'
import { FormSchema } from '@/types/form'
@ -74,12 +74,14 @@ export const setGridProp = (col: ColProps = {}): ColProps => {
*/
export const setComponentProps = (item: FormSchema): Recordable => {
// const notNeedClearable = ['ColorPicker']
const componentProps = {
const componentProps: Recordable = {
clearable: true,
...item.componentProps
}
// 需要删除额外的属性
delete componentProps?.slots
if (componentProps.slots) {
delete componentProps.slots
}
return componentProps
}
@ -93,8 +95,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] = (item: any) => {
return slotsProps[key]?.(unref(item?.item) || undefined, formModel)
}
} else {
slotObj[key] = () => {

View File

@ -214,7 +214,9 @@ export default {
default: 'Default',
icon: 'Icon',
mixed: 'Mixed',
password: 'Password',
textarea: 'Textarea',
remoteSearch: 'Remote search',
slot: 'Slot',
position: 'Position',
autocomplete: 'Autocomplete',

View File

@ -214,7 +214,9 @@ export default {
default: '默认',
icon: '图标',
mixed: '复合型',
password: '密码框',
textarea: '多行文本',
remoteSearch: '远程搜索',
slot: '插槽',
position: '位置',
autocomplete: '自动补全',

View File

@ -1,5 +1,5 @@
import { CSSProperties } from 'vue'
import { InputProps } from 'element-plus'
import { InputProps, AutocompleteProps, InputNumberProps } from 'element-plus'
export enum ComponentNameEnum {
RADIO = 'Radio',
@ -25,6 +25,16 @@ export enum ComponentNameEnum {
EDITOR = 'Editor'
}
type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K
? K extends string
? K extends `${infer A}_${infer B}`
? `${Capitalize<Lowercase<A>>}${Capitalize<Lowercase<B>>}`
: Capitalize<Lowercase<K>>
: never
: never
export type ComponentName = CamelCaseComponentName
export interface InputComponentProps {
value?: string | number
maxlength?: number | string
@ -37,8 +47,8 @@ export interface InputComponentProps {
showPassword?: boolean
disabled?: boolean
size?: InputProps['size']
prefixIcon?: string | JSX.Element | (<T>(data: T | any) => string | JSX.Element)
suffixIcon?: string | JSX.Element | (<T>(data: T | any) => string | JSX.Element)
prefixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element)
suffixIcon?: string | JSX.Element | ((item: any, data: any) => string | JSX.Element)
type?: InputProps['type']
rows?: number
autosize?: boolean | { Pows?: numer; maxRows?: number }
@ -63,22 +73,167 @@ export interface InputComponentProps {
input?: (value: string | number) => void
}
slots?: {
prefix?: JSX.Element | (<T>(data: T | any) => JSX.Element)
suffix?: JSX.Element | (<T>(data: T | any) => JSX.Element)
prepend?: JSX.Element | (<T>(data: T | any) => JSX.Element)
append?: JSX.Element | (<T>(data: T | any) => JSX.Element)
prefix?: JSX.Element | ((item: any, data: any) => JSX.Element)
suffix?: 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)
}
style?: CSSProperties
}
type CamelCaseComponentName = keyof typeof ComponentNameEnum extends infer K
? K extends string
? K extends `${infer A}_${infer B}`
? `${Capitalize<Lowercase<A>>}${Capitalize<Lowercase<B>>}`
: Capitalize<Lowercase<K>>
: never
: never
export interface AutocompleteComponentProps {
value?: string
placeholder?: string
clearable?: boolean
disabled?: boolean
valueKey?: string
debounce?: number
placement?: AutocompleteProps['placement']
fetchSuggestions?: (queryString: string, callback: (data: string[]) => void) => void
triggerOnFocus?: boolean
selectWhenUnmatched?: boolean
name?: string
label?: string
hideLoading?: boolean
popperClass?: string
popperAppendToBody?: boolean
teleported?: boolean
highlightFirstItem?: boolean
fitInputWidth?: boolean
on?: {
select?: (item: any) => void
change?: (value: string | number) => void
}
slots?: {
default?: JSX.Element | ((item: any, data: any) => JSX.Element)
prefix?: JSX.Element | ((item: any, data: any) => JSX.Element)
suffix?: 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)
}
style?: CSSProperties
}
export type ComponentName = CamelCaseComponentName
export interface InputNumberComponentProps {
value?: number
min?: number
max?: number
step?: number
stepStrictly?: boolean
precision?: number
size?: InputNumberProps['size']
readonly?: boolean
disabled?: boolean
controls?: boolean
controlsPosition?: InputNumberProps['controlsPosition']
name?: string
label?: string
placeholder?: string
id?: string
valueOnClear?: number | null | 'min' | 'max'
validateEvent?: boolean
on?: {
change?: (currentValue: number | undefined, oldValue: number | undefined) => void
blur?: (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 {
span?: number
@ -92,7 +247,7 @@ export interface ColProps {
export interface ComponentOptions extends Recordable {
label?: string
value?: FormValueType
value?: any
disabled?: boolean
key?: string | number
children?: ComponentOptions[]

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

@ -3,8 +3,10 @@ import {
ColProps,
ComponentProps,
ComponentName,
ComponentNameEnum,
InputComponentProps
InputComponentProps,
AutocompleteComponentProps,
InputNumberComponentProps,
SelectComponentProps
} from '@/types/components'
import { FormValueType, FormValueType } from '@/types/form'
import type { AxiosPromise } from 'axios'
@ -28,29 +30,57 @@ export type FormItemProps = {
}
export interface FormSchema {
// 唯一值
/**
*
*/
field: string
// 标题
label?: string
// 提示
labelMessage?: string
// col组件属性
colProps?: ColProps
// 表单组件属性slots对应的是表单组件的插槽规则${field}-xxx具体可以查看element-plus文档
// componentProps?: { slots?: Recordable } & ComponentProps
/**
* slots对应的是表单组件的插槽${field}-xxxelement-plus文档
*
*/
label?: string
/**
*
*/
labelMessage?: string
/**
* col组件属性
*/
colProps?: ColProps
/**
* element-plus文档
*/
componentProps?:
| InputComponentProps
| AutocompleteComponentProps
| InputNumberComponentProps
| SelectComponentProps
/**
* formItem组件属性element-plus文档
*/
componentProps?: InputComponentProps
// formItem组件属性
formItemProps?: FormItemProps
// 渲染的组件
/**
*
*/
component?: ComponentName
// 初始值
/**
*
*/
value?: FormValueType
// 是否隐藏
/**
*
*/
hidden?: boolean
// 远程加载下拉项
/**
* @returns
*/
api?: <T = any>() => AxiosPromise<T>
}

View File

@ -1,4 +1,4 @@
<script setup lang="ts">
<script setup lang="tsx">
import { Form } from '@/components/Form'
import { reactive, ref, onMounted, computed, unref } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
@ -25,6 +25,17 @@ const querySearch = (queryString: string, cb: Fn) => {
// call callback function to return suggestions
cb(results)
}
let timeout: NodeJS.Timeout
const querySearchAsync = (queryString: string, cb: (arg: any) => void) => {
const results = queryString
? restaurants.value.filter(createFilter(queryString))
: restaurants.value
clearTimeout(timeout)
timeout = setTimeout(() => {
cb(results)
}, 3000 * Math.random())
}
const createFilter = (queryString: string) => {
return (restaurant: Recordable) => {
return restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
@ -359,7 +370,11 @@ const schema = reactive<FormSchema[]>([
{
field: 'field2',
label: t('formDemo.default'),
component: 'Input'
component: 'Input',
componentProps: {
formatter: (value) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ','),
parser: (value) => value.replace(/\$\s?|(,*)/g, '')
}
},
{
field: 'field3',
@ -378,7 +393,7 @@ const schema = reactive<FormSchema[]>([
component: 'Input',
componentProps: {
slots: {
suffix: (data: any) => {
suffix: (_, data: any) => {
return unref(toggle) && data.field4
? useIcon({ icon: 'ep:calendar' })
: useIcon({ icon: 'ep:share' })
@ -394,12 +409,20 @@ const schema = reactive<FormSchema[]>([
componentProps: {
slots: {
prepend: useIcon({ icon: 'ep:calendar' }),
append: (data: any) => {
append: (_, data: any) => {
return data.field5 ? useIcon({ icon: 'ep:calendar' }) : useIcon({ icon: 'ep:share' })
}
}
}
},
{
field: 'input-field7',
label: t('formDemo.password'),
component: 'Input',
componentProps: {
showPassword: true
}
},
{
field: 'field6',
label: t('formDemo.textarea'),
@ -408,94 +431,132 @@ const schema = reactive<FormSchema[]>([
type: 'textarea',
rows: 2
}
},
{
field: 'field7',
label: t('formDemo.autocomplete'),
component: 'Divider'
},
{
field: 'field8',
label: t('formDemo.default'),
component: 'Autocomplete',
componentProps: {
fetchSuggestions: querySearch,
on: {
select: handleSelect
}
}
},
{
field: 'field9',
label: t('formDemo.slot'),
component: 'Autocomplete',
componentProps: {
fetchSuggestions: querySearch,
on: {
select: handleSelect
},
slots: {
default: (item: any) => {
return (
<>
<div class="value">{item.value}</div>
<span class="link">{item.link}</span>
</>
)
}
}
}
},
{
field: 'autocomplete-field10',
label: t('formDemo.remoteSearch'),
component: 'Autocomplete',
componentProps: {
fetchSuggestions: querySearchAsync,
on: {
select: handleSelect
}
}
},
{
field: 'field10',
component: 'Divider',
label: t('formDemo.inputNumber')
},
{
field: 'field11',
label: t('formDemo.default'),
component: 'InputNumber',
value: 0
},
{
field: 'field12',
label: t('formDemo.position'),
component: 'InputNumber',
componentProps: {
controlsPosition: 'right'
},
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: 'field7',
// label: t('formDemo.autocomplete'),
// component: 'Divider'
// },
// {
// field: 'field8',
// label: t('formDemo.default'),
// component: 'Autocomplete',
// componentProps: {
// fetchSuggestions: querySearch,
// onSelect: handleSelect
// }
// },
// {
// field: 'field9',
// label: t('formDemo.slot'),
// component: 'Autocomplete',
// componentProps: {
// fetchSuggestions: querySearch,
// onSelect: handleSelect,
// slots: {
// default: true
// }
// }
// },
// {
// field: 'field10',
// component: 'Divider',
// label: t('formDemo.inputNumber')
// },
// {
// field: 'field11',
// label: t('formDemo.default'),
// component: 'InputNumber',
// value: 0
// },
// {
// field: 'field12',
// label: t('formDemo.position'),
// component: 'InputNumber',
// componentProps: {
// controlsPosition: 'right'
// },
// value: 0
// },
// {
// 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',
// label: t('formDemo.selectGroup'),