From 2261f49976a29b5de76dc1be6ded709d2ee28822 Mon Sep 17 00:00:00 2001
From: kailong321200875 <321200875@qq.com>
Date: Fri, 28 Apr 2023 14:02:27 +0800
Subject: [PATCH] =?UTF-8?q?wip:=20Form=E6=94=B9=E9=80=A0=E4=B8=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/Form/src/Form copy.vue | 302 ++++++++++++++++++
src/components/Form/src/Form.vue | 80 ++---
.../Form/src/components/useRenderSelect.tsx | 16 +-
src/types/components.d.ts | 100 +++++-
src/types/form.d.ts | 9 +-
src/views/Components/Form/DefaultForm.vue | 98 +++---
6 files changed, 517 insertions(+), 88 deletions(-)
create mode 100644 src/components/Form/src/Form copy.vue
diff --git a/src/components/Form/src/Form copy.vue b/src/components/Form/src/Form copy.vue
new file mode 100644
index 0000000..94fe848
--- /dev/null
+++ b/src/components/Form/src/Form copy.vue
@@ -0,0 +1,302 @@
+
+
+
diff --git a/src/components/Form/src/Form.vue b/src/components/Form/src/Form.vue
index 5686668..0ce1af2 100644
--- a/src/components/Form/src/Form.vue
+++ b/src/components/Form/src/Form.vue
@@ -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)
+ // 如果是select组件,并且没有自定义模板,自动渲染options
+ 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 (
- <>
- {item.label}
-
- {{
- content: () => ,
- default: () => (
-
- )
- }}
-
- >
- )
- }
- }
+ // if (item?.labelMessage) {
+ // formItemSlots.label = () => {
+ // return (
+ // <>
+ // {item.label}
+ //
+ // {{
+ // content: () => ,
+ // default: () => (
+ //
+ // )
+ // }}
+ //
+ // >
+ // )
+ // }
+ // }
return (
{{
- ...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 }}
@@ -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':
diff --git a/src/components/Form/src/components/useRenderSelect.tsx b/src/components/Form/src/components/useRenderSelect.tsx
index e4b5a26..9421c0e 100644
--- a/src/components/Form/src/components/useRenderSelect.tsx
+++ b/src/components/Form/src/components/useRenderSelect.tsx
@@ -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 (
@@ -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
}}
diff --git a/src/types/components.d.ts b/src/types/components.d.ts
index 05bb0bb..e132fad 100644
--- a/src/types/components.d.ts
+++ b/src/types/components.d.ts
@@ -78,6 +78,7 @@ export interface InputComponentProps {
prepend?: JSX.Element | ((item: any, data: any) => JSX.Element)
append?: JSX.Element | ((item: any, data: any) => JSX.Element)
}
+ style?: CSSProperties
}
export interface AutocompleteComponentProps {
@@ -110,6 +111,7 @@ export interface AutocompleteComponentProps {
prepend?: JSX.Element | ((item: any, data: any) => JSX.Element)
append?: JSX.Element | ((item: any, data: any) => JSX.Element)
}
+ style?: CSSProperties
}
export interface InputNumberComponentProps {
@@ -135,6 +137,102 @@ export interface InputNumberComponentProps {
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 {
@@ -149,7 +247,7 @@ export interface ColProps {
export interface ComponentOptions extends Recordable {
label?: string
- value?: FormValueType
+ value?: any
disabled?: boolean
key?: string | number
children?: ComponentOptions[]
diff --git a/src/types/form.d.ts b/src/types/form.d.ts
index 131a161..5530c99 100644
--- a/src/types/form.d.ts
+++ b/src/types/form.d.ts
@@ -5,7 +5,8 @@ import {
ComponentName,
InputComponentProps,
AutocompleteComponentProps,
- InputNumberComponentProps
+ InputNumberComponentProps,
+ SelectComponentProps
} from '@/types/components'
import { FormValueType, FormValueType } from '@/types/form'
import type { AxiosPromise } from 'axios'
@@ -52,7 +53,11 @@ export interface FormSchema {
/**
* 表单组件属性,具体可以查看element-plus文档
*/
- componentProps?: InputComponentProps | AutocompleteComponentProps | InputNumberComponentProps
+ componentProps?:
+ | InputComponentProps
+ | AutocompleteComponentProps
+ | InputNumberComponentProps
+ | SelectComponentProps
/**
* formItem组件属性,具体可以查看element-plus文档
diff --git a/src/views/Components/Form/DefaultForm.vue b/src/views/Components/Form/DefaultForm.vue
index 5670add..3902705 100644
--- a/src/views/Components/Form/DefaultForm.vue
+++ b/src/views/Components/Form/DefaultForm.vue
@@ -499,49 +499,65 @@ const schema = reactive([
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 (
+ <>
+ {item.label}
+
+ {item.value}
+
+ >
+ )
+ }
+ }
+ }
}
// {
- // 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'),
// component: 'Select',