Commit 1d45617e4a311e339eb008a629cd342cd673ecf1
1 parent
3f78b5aa
refactor(form): enhanced form customization and dynamic capabilities
Showing
14 changed files
with
364 additions
and
39 deletions
CHANGELOG.zh_CN.md
... | ... | @@ -4,6 +4,7 @@ |
4 | 4 | |
5 | 5 | - 重构 hook,引入 `@vueuse`,删除其中已有的`hook`,优化现有的 hook |
6 | 6 | - `useEvent` 更名->`useEventListener` |
7 | +- 表单`ComponentType`删除 `SelectOptGroup`,`SelectOption`,`Transfer`,`Radio`,四个类型。修改`RadioButtonGroup`组件 | |
7 | 8 | |
8 | 9 | ### ✨ Features |
9 | 10 | |
... | ... | @@ -12,10 +13,15 @@ |
12 | 13 | - 新增菜单及顶栏颜色选择配色 |
13 | 14 | - 增加示例结果页 |
14 | 15 | |
16 | +### ⚡ Wip | |
17 | + | |
18 | +- 上传组件(未完成,测试中...) | |
19 | + | |
15 | 20 | ### ⚡ Performance Improvements |
16 | 21 | |
17 | 22 | - 优化 settingDrawer 代码 |
18 | 23 | - 优化多标签页切换速度 |
24 | +- 增加表单自定义及动态能力 | |
19 | 25 | |
20 | 26 | ### 🐛 Bug Fixes |
21 | 27 | |
... | ... | @@ -23,6 +29,7 @@ |
23 | 29 | - 修复登录过期后重新登录未跳转原来页面的 |
24 | 30 | - 修复 window 系统动态引入错误 |
25 | 31 | - 修复页面类型错误 |
32 | +- 修复表单 switch 和 checkBox 单独使用报错 | |
26 | 33 | |
27 | 34 | ## 2.0.0-rc.9 (2020-11-9) |
28 | 35 | ... | ... |
src/components/Form/src/BasicForm.vue
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | <template v-for="schema in getSchema" :key="schema.field"> |
6 | 6 | <FormItem |
7 | 7 | :tableAction="tableAction" |
8 | + :formActionType="formActionType" | |
8 | 9 | :schema="schema" |
9 | 10 | :formProps="getProps" |
10 | 11 | :allDefaultValues="defaultValueRef" |
... | ... | @@ -164,7 +165,7 @@ |
164 | 165 | propsRef.value = mergeProps; |
165 | 166 | } |
166 | 167 | |
167 | - const methods: Partial<FormActionType> = { | |
168 | + const formActionType: Partial<FormActionType> = { | |
168 | 169 | getFieldsValue, |
169 | 170 | setFieldsValue, |
170 | 171 | resetFields, |
... | ... | @@ -179,7 +180,7 @@ |
179 | 180 | |
180 | 181 | onMounted(() => { |
181 | 182 | initDefault(); |
182 | - emit('register', methods); | |
183 | + emit('register', formActionType); | |
183 | 184 | }); |
184 | 185 | |
185 | 186 | return { |
... | ... | @@ -191,7 +192,8 @@ |
191 | 192 | getProps, |
192 | 193 | formElRef, |
193 | 194 | getSchema, |
194 | - ...methods, | |
195 | + formActionType, | |
196 | + ...formActionType, | |
195 | 197 | }; |
196 | 198 | }, |
197 | 199 | }); | ... | ... |
src/components/Form/src/FormItem.tsx
1 | 1 | import type { PropType } from 'vue'; |
2 | -import type { FormProps } from './types/form'; | |
2 | +import type { FormActionType, FormProps } from './types/form'; | |
3 | 3 | import type { FormSchema } from './types/form'; |
4 | 4 | import type { ValidationRule } from 'ant-design-vue/lib/form/Form'; |
5 | 5 | import type { TableActionType } from '/@/components/Table'; |
... | ... | @@ -41,6 +41,9 @@ export default defineComponent({ |
41 | 41 | tableAction: { |
42 | 42 | type: Object as PropType<TableActionType>, |
43 | 43 | }, |
44 | + formActionType: { | |
45 | + type: Object as PropType<FormActionType>, | |
46 | + }, | |
44 | 47 | }, |
45 | 48 | setup(props, { slots }) { |
46 | 49 | const itemLabelWidthRef = useItemLabelWidth(toRef(props, 'schema'), toRef(props, 'formProps')); |
... | ... | @@ -61,12 +64,12 @@ export default defineComponent({ |
61 | 64 | }); |
62 | 65 | |
63 | 66 | const getComponentsPropsRef = computed(() => { |
64 | - const { schema, tableAction, formModel } = props; | |
67 | + const { schema, tableAction, formModel, formActionType } = props; | |
65 | 68 | const { componentProps = {} } = schema; |
66 | 69 | if (!isFunction(componentProps)) { |
67 | 70 | return componentProps; |
68 | 71 | } |
69 | - return componentProps({ schema, tableAction, formModel }) || {}; | |
72 | + return componentProps({ schema, tableAction, formModel, formActionType }) || {}; | |
70 | 73 | }); |
71 | 74 | |
72 | 75 | const getDisableRef = computed(() => { |
... | ... | @@ -179,17 +182,27 @@ export default defineComponent({ |
179 | 182 | } |
180 | 183 | |
181 | 184 | function renderComponent() { |
182 | - const { renderComponentContent, component, field, changeEvent = 'change' } = props.schema; | |
185 | + const { | |
186 | + renderComponentContent, | |
187 | + component, | |
188 | + field, | |
189 | + changeEvent = 'change', | |
190 | + valueField, | |
191 | + } = props.schema; | |
183 | 192 | |
184 | - const isCheck = component && ['Switch'].includes(component); | |
193 | + const isCheck = component && ['Switch', 'Checkbox'].includes(component); | |
185 | 194 | |
186 | 195 | const eventKey = `on${upperFirst(changeEvent)}`; |
196 | + | |
187 | 197 | const on = { |
188 | 198 | [eventKey]: (e: any) => { |
189 | 199 | if (propsData[eventKey]) { |
190 | 200 | propsData[eventKey](e); |
191 | 201 | } |
192 | - (props.formModel as any)[field] = e && e.target ? e.target.value : e; | |
202 | + | |
203 | + const target = e ? e.target : null; | |
204 | + const value = target ? (isCheck ? target.checked : target.value) : e; | |
205 | + (props.formModel as any)[field] = value; | |
193 | 206 | }, |
194 | 207 | }; |
195 | 208 | const Comp = componentMap.get(component); |
... | ... | @@ -215,17 +228,20 @@ export default defineComponent({ |
215 | 228 | propsData.codeField = field; |
216 | 229 | propsData.formValues = unref(getValuesRef); |
217 | 230 | const bindValue = { |
218 | - [isCheck ? 'checked' : 'value']: handleValue(component, field), | |
231 | + [valueField || (isCheck ? 'checked' : 'value')]: handleValue(component, field), | |
219 | 232 | }; |
220 | 233 | if (!renderComponentContent) { |
221 | 234 | return <Comp {...propsData} {...on} {...bindValue} />; |
222 | 235 | } |
236 | + const compSlot = isFunction(renderComponentContent) | |
237 | + ? { ...renderComponentContent(unref(getValuesRef)) } | |
238 | + : { | |
239 | + default: () => renderComponentContent, | |
240 | + }; | |
223 | 241 | |
224 | 242 | return ( |
225 | 243 | <Comp {...propsData} {...on} {...bindValue}> |
226 | - {{ | |
227 | - ...renderComponentContent(unref(getValuesRef)), | |
228 | - }} | |
244 | + {compSlot} | |
229 | 245 | </Comp> |
230 | 246 | ); |
231 | 247 | } |
... | ... | @@ -249,7 +265,7 @@ export default defineComponent({ |
249 | 265 | const { colon } = props.formProps; |
250 | 266 | const getContent = () => { |
251 | 267 | return slot |
252 | - ? getSlot(slots, slot) | |
268 | + ? getSlot(slots, slot, unref(getValuesRef)) | |
253 | 269 | : render |
254 | 270 | ? render(unref(getValuesRef)) |
255 | 271 | : renderComponent(); |
... | ... | @@ -276,7 +292,7 @@ export default defineComponent({ |
276 | 292 | const { isIfShow, isShow } = getShow(); |
277 | 293 | const getContent = () => { |
278 | 294 | return colSlot |
279 | - ? getSlot(slots, colSlot) | |
295 | + ? getSlot(slots, colSlot, unref(getValuesRef)) | |
280 | 296 | : renderColContent |
281 | 297 | ? renderColContent(unref(getValuesRef)) |
282 | 298 | : renderItem(); | ... | ... |
src/components/Form/src/componentMap.ts
... | ... | @@ -14,8 +14,8 @@ import { |
14 | 14 | Switch, |
15 | 15 | TimePicker, |
16 | 16 | TreeSelect, |
17 | - Transfer, | |
18 | 17 | } from 'ant-design-vue'; |
18 | +import RadioButtonGroup from './components/RadioButtonGroup.vue'; | |
19 | 19 | |
20 | 20 | import { ComponentType } from './types/index'; |
21 | 21 | |
... | ... | @@ -30,13 +30,13 @@ componentMap.set('InputNumber', InputNumber); |
30 | 30 | componentMap.set('AutoComplete', AutoComplete); |
31 | 31 | |
32 | 32 | componentMap.set('Select', Select); |
33 | -componentMap.set('SelectOptGroup', Select.OptGroup); | |
34 | -componentMap.set('SelectOption', Select.Option); | |
33 | +// componentMap.set('SelectOptGroup', Select.OptGroup); | |
34 | +// componentMap.set('SelectOption', Select.Option); | |
35 | 35 | componentMap.set('TreeSelect', TreeSelect); |
36 | -componentMap.set('Transfer', Transfer); | |
37 | -componentMap.set('Radio', Radio); | |
36 | +// componentMap.set('Transfer', Transfer); | |
37 | +// componentMap.set('Radio', Radio); | |
38 | 38 | componentMap.set('Switch', Switch); |
39 | -componentMap.set('RadioButton', Radio.Button); | |
39 | +componentMap.set('RadioButtonGroup', RadioButtonGroup); | |
40 | 40 | componentMap.set('RadioGroup', Radio.Group); |
41 | 41 | componentMap.set('Checkbox', Checkbox); |
42 | 42 | componentMap.set('CheckboxGroup', Checkbox.Group); | ... | ... |
src/components/Form/src/components/RadioButtonGroup.vue
0 → 100644
1 | +<template> | |
2 | + <RadioGroup v-bind="$attrs" v-model:value="valueRef" button-style="solid"> | |
3 | + <template v-for="item in getOptions" :key="`${item.value}`"> | |
4 | + <RadioButton :value="item.value"> {{ item.label }} </RadioButton> | |
5 | + </template> | |
6 | + </RadioGroup> | |
7 | +</template> | |
8 | +<script lang="ts"> | |
9 | + import { defineComponent, ref, PropType, watch, unref, computed } from 'vue'; | |
10 | + import { Radio } from 'ant-design-vue'; | |
11 | + import {} from 'ant-design-vue/es/radio/Group'; | |
12 | + import { isString } from '/@/utils/is'; | |
13 | + | |
14 | + type OptionsItem = { label: string; value: string; disabled?: boolean }; | |
15 | + type RadioItem = string | OptionsItem; | |
16 | + export default defineComponent({ | |
17 | + name: 'RadioButtonGroup', | |
18 | + components: { | |
19 | + RadioGroup: Radio.Group, | |
20 | + RadioButton: Radio.Button, | |
21 | + }, | |
22 | + props: { | |
23 | + value: { | |
24 | + type: String as PropType<string>, | |
25 | + }, | |
26 | + options: { | |
27 | + type: Array as PropType<RadioItem[]>, | |
28 | + default: () => [], | |
29 | + }, | |
30 | + }, | |
31 | + setup(props, { emit }) { | |
32 | + const valueRef = ref(''); | |
33 | + | |
34 | + watch( | |
35 | + () => props.value, | |
36 | + (v = '') => { | |
37 | + valueRef.value = v; | |
38 | + }, | |
39 | + { immediate: true } | |
40 | + ); | |
41 | + | |
42 | + watch( | |
43 | + () => unref(valueRef), | |
44 | + () => { | |
45 | + emit('change', valueRef.value); | |
46 | + }, | |
47 | + { immediate: true } | |
48 | + ); | |
49 | + | |
50 | + const getOptions = computed((): OptionsItem[] => { | |
51 | + const { options } = props; | |
52 | + if (!options || options.length === 0) return []; | |
53 | + const isStringArr = options.some((item) => isString(item)); | |
54 | + if (!isStringArr) return options as OptionsItem[]; | |
55 | + return options.map((item) => ({ label: item, value: item })) as OptionsItem[]; | |
56 | + }); | |
57 | + | |
58 | + return { valueRef, getOptions }; | |
59 | + }, | |
60 | + }); | |
61 | +</script> | ... | ... |
src/components/Form/src/types/form.ts
... | ... | @@ -7,6 +7,10 @@ import { TableActionType } from '../../../Table/src/types/table'; |
7 | 7 | |
8 | 8 | export type FieldMapToTime = [string, [string, string], string?][]; |
9 | 9 | |
10 | +export type Rule = RuleObject & { | |
11 | + trigger?: 'blur' | 'change' | ['change', 'blur']; | |
12 | +}; | |
13 | + | |
10 | 14 | export interface RenderCallbackParams { |
11 | 15 | schema: FormSchema; |
12 | 16 | values: any; |
... | ... | @@ -98,7 +102,10 @@ export interface FormProps { |
98 | 102 | export interface FormSchema { |
99 | 103 | // 字段名 |
100 | 104 | field: string; |
105 | + // 内部值更改触发的事件名,默认 change | |
101 | 106 | changeEvent?: string; |
107 | + // v-model绑定的变量名 默认 value | |
108 | + valueField?: string; | |
102 | 109 | // 标签名 |
103 | 110 | label: string; |
104 | 111 | // 文本右侧帮助文本 |
... | ... | @@ -113,13 +120,18 @@ export interface FormSchema { |
113 | 120 | component: ComponentType; |
114 | 121 | // 组件参数 |
115 | 122 | componentProps?: |
116 | - | ((opt: { schema: FormSchema; tableAction: TableActionType; formModel: any }) => any) | |
123 | + | ((opt: { | |
124 | + schema: FormSchema; | |
125 | + tableAction: TableActionType; | |
126 | + formActionType: FormActionType; | |
127 | + formModel: any; | |
128 | + }) => any) | |
117 | 129 | | object; |
118 | 130 | // 必填 |
119 | 131 | required?: boolean; |
120 | 132 | |
121 | 133 | // 校验规则 |
122 | - rules?: RuleObject[]; | |
134 | + rules?: Rule[]; | |
123 | 135 | // 校验信息是否加入label |
124 | 136 | rulesMessageJoinLabel?: boolean; |
125 | 137 | |
... | ... | @@ -146,7 +158,11 @@ export interface FormSchema { |
146 | 158 | // 渲染 col内容,需要外层包裹 form-item |
147 | 159 | renderColContent?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string; |
148 | 160 | |
149 | - renderComponentContent?: (renderCallbackParams: RenderCallbackParams) => any; | |
161 | + renderComponentContent?: | |
162 | + | ((renderCallbackParams: RenderCallbackParams) => any) | |
163 | + | VNode | |
164 | + | VNode[] | |
165 | + | string; | |
150 | 166 | |
151 | 167 | // 自定义slot, 在 from-item内 |
152 | 168 | slot?: string; |
... | ... | @@ -156,7 +172,7 @@ export interface FormSchema { |
156 | 172 | |
157 | 173 | dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean); |
158 | 174 | |
159 | - dynamicRules?: (renderCallbackParams: RenderCallbackParams) => RuleObject[]; | |
175 | + dynamicRules?: (renderCallbackParams: RenderCallbackParams) => Rule[]; | |
160 | 176 | } |
161 | 177 | export interface HelpComponentProps { |
162 | 178 | maxWidth: string; | ... | ... |
src/components/Form/src/types/index.ts
src/components/Table/src/types/table.ts
... | ... | @@ -87,7 +87,7 @@ export interface GetColumnsParams { |
87 | 87 | export type SizeType = 'default' | 'middle' | 'small' | 'large'; |
88 | 88 | |
89 | 89 | export interface TableActionType { |
90 | - reload: (opt?: FetchParams) => Promise<void>; | |
90 | + // reload: (opt?: FetchParams) => Promise<void>; | |
91 | 91 | getSelectRows: () => any[]; |
92 | 92 | clearSelectedRowKeys: () => void; |
93 | 93 | getSelectRowKeys: () => string[]; | ... | ... |
src/router/menus/modules/demo/comp.ts
src/router/menus/modules/demo/form.ts
... | ... | @@ -4,10 +4,18 @@ const menu: MenuModule = { |
4 | 4 | menu: { |
5 | 5 | path: '/form', |
6 | 6 | name: 'Form', |
7 | + tag: { | |
8 | + type: 'warn', | |
9 | + dot: true, | |
10 | + }, | |
7 | 11 | children: [ |
8 | 12 | { |
9 | 13 | path: 'basic', |
10 | 14 | name: '基础表单', |
15 | + tag: { | |
16 | + type: 'warn', | |
17 | + content: 'updated', | |
18 | + }, | |
11 | 19 | }, |
12 | 20 | { |
13 | 21 | path: 'useForm', |
... | ... | @@ -24,14 +32,26 @@ const menu: MenuModule = { |
24 | 32 | { |
25 | 33 | path: 'ruleForm', |
26 | 34 | name: '表单校验', |
35 | + tag: { | |
36 | + type: 'warn', | |
37 | + content: 'updated', | |
38 | + }, | |
27 | 39 | }, |
28 | 40 | { |
29 | 41 | path: 'dynamicForm', |
30 | 42 | name: '动态表单', |
43 | + tag: { | |
44 | + type: 'warn', | |
45 | + content: 'updated', | |
46 | + }, | |
31 | 47 | }, |
32 | 48 | { |
33 | 49 | path: 'customerForm', |
34 | 50 | name: '自定义组件', |
51 | + tag: { | |
52 | + type: 'warn', | |
53 | + content: 'updated', | |
54 | + }, | |
35 | 55 | }, |
36 | 56 | ], |
37 | 57 | }, | ... | ... |
src/views/demo/form/CustomerForm.vue
1 | 1 | <template> |
2 | 2 | <div class="m-4"> |
3 | 3 | <CollapseContainer title="自定义表单"> |
4 | - <BasicForm @register="register" @submit="handleSubmit" /> | |
4 | + <BasicForm @register="register" @submit="handleSubmit"> | |
5 | + <template #f3="{ model, field }"> | |
6 | + <a-input v-model:value="model[field]" placeholder="自定义slot" /> | |
7 | + </template> | |
8 | + </BasicForm> | |
5 | 9 | </CollapseContainer> |
6 | 10 | </div> |
7 | 11 | </template> |
... | ... | @@ -15,7 +19,7 @@ |
15 | 19 | { |
16 | 20 | field: 'field1', |
17 | 21 | component: 'Input', |
18 | - label: '字段1', | |
22 | + label: 'render方式', | |
19 | 23 | colProps: { |
20 | 24 | span: 8, |
21 | 25 | }, |
... | ... | @@ -33,7 +37,7 @@ |
33 | 37 | { |
34 | 38 | field: 'field2', |
35 | 39 | component: 'Input', |
36 | - label: '字段2', | |
40 | + label: 'render组件slot', | |
37 | 41 | colProps: { |
38 | 42 | span: 8, |
39 | 43 | }, |
... | ... | @@ -44,6 +48,16 @@ |
44 | 48 | }; |
45 | 49 | }, |
46 | 50 | }, |
51 | + { | |
52 | + field: 'field3', | |
53 | + component: 'Input', | |
54 | + label: '自定义Slot', | |
55 | + slot: 'f3', | |
56 | + colProps: { | |
57 | + span: 8, | |
58 | + }, | |
59 | + rules: [{ required: true }], | |
60 | + }, | |
47 | 61 | ]; |
48 | 62 | export default defineComponent({ |
49 | 63 | components: { BasicForm, CollapseContainer }, | ... | ... |
src/views/demo/form/DynamicForm.vue
... | ... | @@ -9,6 +9,10 @@ |
9 | 9 | <CollapseContainer title="动态表单示例,动态根据表单内其他值改变"> |
10 | 10 | <BasicForm @register="register" /> |
11 | 11 | </CollapseContainer> |
12 | + | |
13 | + <CollapseContainer class="mt-5" title="componentProps动态改变"> | |
14 | + <BasicForm @register="register1" /> | |
15 | + </CollapseContainer> | |
12 | 16 | </div> |
13 | 17 | </template> |
14 | 18 | <script lang="ts"> |
... | ... | @@ -120,6 +124,58 @@ |
120 | 124 | }, |
121 | 125 | ]; |
122 | 126 | |
127 | + const schemas1: FormSchema[] = [ | |
128 | + { | |
129 | + field: 'f1', | |
130 | + component: 'Input', | |
131 | + label: 'F1', | |
132 | + colProps: { | |
133 | + span: 12, | |
134 | + }, | |
135 | + labelWidth: 200, | |
136 | + componentProps: ({ formModel }) => { | |
137 | + return { | |
138 | + placeholder: '同步f2的值为f1', | |
139 | + onChange: (e: ChangeEvent) => { | |
140 | + formModel.f2 = e.target.value; | |
141 | + }, | |
142 | + }; | |
143 | + }, | |
144 | + }, | |
145 | + { | |
146 | + field: 'f2', | |
147 | + component: 'Input', | |
148 | + label: 'F2', | |
149 | + colProps: { | |
150 | + span: 12, | |
151 | + }, | |
152 | + labelWidth: 200, | |
153 | + componentProps: { disabled: true }, | |
154 | + }, | |
155 | + { | |
156 | + field: 'f3', | |
157 | + component: 'Input', | |
158 | + label: 'F3', | |
159 | + colProps: { | |
160 | + span: 12, | |
161 | + }, | |
162 | + labelWidth: 200, | |
163 | + // @ts-ignore | |
164 | + componentProps: ({ formActionType, tableAction }) => { | |
165 | + return { | |
166 | + placeholder: '值改变时执行查询,查看控制台', | |
167 | + onChange: async () => { | |
168 | + const { validate } = formActionType; | |
169 | + // tableAction只适用于在表格内开启表单的例子 | |
170 | + // const { reload } = tableAction; | |
171 | + const res = await validate(); | |
172 | + console.log(res); | |
173 | + }, | |
174 | + }; | |
175 | + }, | |
176 | + }, | |
177 | + ]; | |
178 | + | |
123 | 179 | export default defineComponent({ |
124 | 180 | components: { BasicForm, CollapseContainer }, |
125 | 181 | setup() { |
... | ... | @@ -133,6 +189,13 @@ |
133 | 189 | span: 24, |
134 | 190 | }, |
135 | 191 | }); |
192 | + const [register1] = useForm({ | |
193 | + labelWidth: 120, | |
194 | + schemas: schemas1, | |
195 | + actionColOptions: { | |
196 | + span: 24, | |
197 | + }, | |
198 | + }); | |
136 | 199 | function changeLabel3() { |
137 | 200 | updateSchema({ |
138 | 201 | field: 'field3', |
... | ... | @@ -170,6 +233,7 @@ |
170 | 233 | } |
171 | 234 | return { |
172 | 235 | register, |
236 | + register1, | |
173 | 237 | schemas, |
174 | 238 | setProps, |
175 | 239 | changeLabel3, | ... | ... |
src/views/demo/form/RuleForm.vue
... | ... | @@ -65,7 +65,33 @@ |
65 | 65 | }, |
66 | 66 | ], |
67 | 67 | }, |
68 | - rules: [{ required: true, message: '请输入aa' }], | |
68 | + rules: [ | |
69 | + { | |
70 | + required: true, | |
71 | + message: '请输入aa', | |
72 | + }, | |
73 | + ], | |
74 | + }, | |
75 | + { | |
76 | + field: 'field44', | |
77 | + component: 'Input', | |
78 | + label: '自定义校验', | |
79 | + colProps: { | |
80 | + span: 8, | |
81 | + }, | |
82 | + rules: [ | |
83 | + { | |
84 | + required: true, | |
85 | + // @ts-ignore | |
86 | + validator: async (rule, value) => { | |
87 | + if (value === '1') { | |
88 | + return Promise.reject('值不能为1'); | |
89 | + } | |
90 | + return Promise.resolve(); | |
91 | + }, | |
92 | + trigger: 'blur', | |
93 | + }, | |
94 | + ], | |
69 | 95 | }, |
70 | 96 | { |
71 | 97 | field: 'field5', | ... | ... |
src/views/demo/form/index.vue
... | ... | @@ -11,10 +11,11 @@ |
11 | 11 | </div> |
12 | 12 | </template> |
13 | 13 | <script lang="ts"> |
14 | - import { defineComponent } from 'vue'; | |
14 | + import { defineComponent, ref } from 'vue'; | |
15 | 15 | import { BasicForm, FormSchema } from '/@/components/Form/index'; |
16 | 16 | import { CollapseContainer } from '/@/components/Container/index'; |
17 | 17 | import { useMessage } from '/@/hooks/web/useMessage'; |
18 | + | |
18 | 19 | const schemas: FormSchema[] = [ |
19 | 20 | { |
20 | 21 | field: 'field1', |
... | ... | @@ -23,8 +24,11 @@ |
23 | 24 | colProps: { |
24 | 25 | span: 8, |
25 | 26 | }, |
26 | - defaultValue: '111', | |
27 | - componentProps: () => { | |
27 | + // componentProps:{}, | |
28 | + // can func | |
29 | + componentProps: ({ schema, formModel }) => { | |
30 | + console.log('form:', schema); | |
31 | + console.log('formModel:', formModel); | |
28 | 32 | return { |
29 | 33 | placeholder: '自定义placeholder', |
30 | 34 | onChange: (e: any) => { |
... | ... | @@ -32,14 +36,26 @@ |
32 | 36 | }, |
33 | 37 | }; |
34 | 38 | }, |
39 | + renderComponentContent: () => { | |
40 | + return { | |
41 | + prefix: () => 'pSlot', | |
42 | + suffix: () => 'sSlot', | |
43 | + }; | |
44 | + }, | |
35 | 45 | }, |
36 | 46 | { |
37 | 47 | field: 'field2', |
38 | 48 | component: 'Input', |
39 | 49 | label: '字段2', |
50 | + defaultValue: '111', | |
40 | 51 | colProps: { |
41 | 52 | span: 8, |
42 | 53 | }, |
54 | + componentProps: { | |
55 | + onChange: (e: any) => { | |
56 | + console.log(e); | |
57 | + }, | |
58 | + }, | |
43 | 59 | }, |
44 | 60 | { |
45 | 61 | field: 'field3', |
... | ... | @@ -111,17 +127,100 @@ |
111 | 127 | ], |
112 | 128 | }, |
113 | 129 | }, |
130 | + { | |
131 | + field: 'field8', | |
132 | + component: 'Checkbox', | |
133 | + label: '字段8', | |
134 | + colProps: { | |
135 | + span: 8, | |
136 | + }, | |
137 | + renderComponentContent: 'Check', | |
138 | + }, | |
139 | + { | |
140 | + field: 'field9', | |
141 | + component: 'Switch', | |
142 | + label: '字段9', | |
143 | + colProps: { | |
144 | + span: 8, | |
145 | + }, | |
146 | + }, | |
147 | + { | |
148 | + field: 'field10', | |
149 | + component: 'RadioButtonGroup', | |
150 | + label: '字段10', | |
151 | + colProps: { | |
152 | + span: 8, | |
153 | + }, | |
154 | + componentProps: { | |
155 | + options: [ | |
156 | + { | |
157 | + label: '选项1', | |
158 | + value: '1', | |
159 | + }, | |
160 | + { | |
161 | + label: '选项2', | |
162 | + value: '2', | |
163 | + }, | |
164 | + ], | |
165 | + }, | |
166 | + }, | |
167 | + { | |
168 | + field: 'field11', | |
169 | + component: 'Cascader', | |
170 | + label: '字段11', | |
171 | + colProps: { | |
172 | + span: 8, | |
173 | + }, | |
174 | + componentProps: { | |
175 | + options: [ | |
176 | + { | |
177 | + value: 'zhejiang', | |
178 | + label: 'Zhejiang', | |
179 | + children: [ | |
180 | + { | |
181 | + value: 'hangzhou', | |
182 | + label: 'Hangzhou', | |
183 | + children: [ | |
184 | + { | |
185 | + value: 'xihu', | |
186 | + label: 'West Lake', | |
187 | + }, | |
188 | + ], | |
189 | + }, | |
190 | + ], | |
191 | + }, | |
192 | + { | |
193 | + value: 'jiangsu', | |
194 | + label: 'Jiangsu', | |
195 | + children: [ | |
196 | + { | |
197 | + value: 'nanjing', | |
198 | + label: 'Nanjing', | |
199 | + children: [ | |
200 | + { | |
201 | + value: 'zhonghuamen', | |
202 | + label: 'Zhong Hua Men', | |
203 | + }, | |
204 | + ], | |
205 | + }, | |
206 | + ], | |
207 | + }, | |
208 | + ], | |
209 | + }, | |
210 | + }, | |
114 | 211 | ]; |
115 | 212 | |
116 | 213 | export default defineComponent({ |
117 | 214 | components: { BasicForm, CollapseContainer }, |
118 | 215 | setup() { |
216 | + const check = ref(null); | |
119 | 217 | const { createMessage } = useMessage(); |
120 | 218 | return { |
121 | 219 | schemas, |
122 | 220 | handleSubmit: (values: any) => { |
123 | 221 | createMessage.success('click search,values:' + JSON.stringify(values)); |
124 | 222 | }, |
223 | + check, | |
125 | 224 | }; |
126 | 225 | }, |
127 | 226 | }); | ... | ... |