Commit 47a448b8aea572e54dac97dc4f9fb6c1c005685a

Authored by 无木
1 parent 5138e447

feat(form): add `Divider` for schema component type

新增Divider用于较长表单的区域分割
CHANGELOG.zh_CN.md
  1 +### ✨ Features
  2 +
  3 +- **BasicForm** 表单组件新增`Divider`,用于较长表单的区域分割
  4 +
  5 +### 🐛 Bug Fixes
  6 +
  7 +- **其它** 修复部分封装组件在使用插槽时报错的问题
  8 +
1 ## 2.7.1(2021-08-16) 9 ## 2.7.1(2021-08-16)
2 10
3 - 升级 vue 3.2,如果运行失败,删除 node_modules 后重装即可 11 - 升级 vue 3.2,如果运行失败,删除 node_modules 后重装即可
src/components/Form/src/BasicForm.vue
@@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
29 #[item]="data" 29 #[item]="data"
30 v-for="item in ['resetBefore', 'submitBefore', 'advanceBefore', 'advanceAfter']" 30 v-for="item in ['resetBefore', 'submitBefore', 'advanceBefore', 'advanceAfter']"
31 > 31 >
32 - <slot :name="item" v-bind="data"></slot> 32 + <slot :name="item" v-bind="data || {}"></slot>
33 </template> 33 </template>
34 </FormAction> 34 </FormAction>
35 <slot name="formFooter"></slot> 35 <slot name="formFooter"></slot>
@@ -132,7 +132,11 @@ @@ -132,7 +132,11 @@
132 } 132 }
133 } 133 }
134 } 134 }
135 - return schemas as FormSchema[]; 135 + if (unref(getProps).showAdvancedButton) {
  136 + return schemas.filter((schema) => schema.component !== 'Divider') as FormSchema[];
  137 + } else {
  138 + return schemas as FormSchema[];
  139 + }
136 }); 140 });
137 141
138 const { handleToggleAdvanced } = useAdvanced({ 142 const { handleToggleAdvanced } = useAdvanced({
src/components/Form/src/componentMap.ts
@@ -18,6 +18,7 @@ import { @@ -18,6 +18,7 @@ import {
18 TreeSelect, 18 TreeSelect,
19 Slider, 19 Slider,
20 Rate, 20 Rate,
  21 + Divider,
21 } from 'ant-design-vue'; 22 } from 'ant-design-vue';
22 23
23 import RadioButtonGroup from './components/RadioButtonGroup.vue'; 24 import RadioButtonGroup from './components/RadioButtonGroup.vue';
@@ -61,6 +62,7 @@ componentMap.set(&#39;IconPicker&#39;, IconPicker); @@ -61,6 +62,7 @@ componentMap.set(&#39;IconPicker&#39;, IconPicker);
61 componentMap.set('InputCountDown', CountdownInput); 62 componentMap.set('InputCountDown', CountdownInput);
62 63
63 componentMap.set('Upload', BasicUpload); 64 componentMap.set('Upload', BasicUpload);
  65 +componentMap.set('Divider', Divider);
64 66
65 export function add(compName: ComponentType, component: Component) { 67 export function add(compName: ComponentType, component: Component) {
66 componentMap.set(compName, component); 68 componentMap.set(compName, component);
src/components/Form/src/components/FormItem.vue
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 import type { ValidationRule } from 'ant-design-vue/lib/form/Form'; 5 import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
6 import type { TableActionType } from '/@/components/Table'; 6 import type { TableActionType } from '/@/components/Table';
7 import { defineComponent, computed, unref, toRefs } from 'vue'; 7 import { defineComponent, computed, unref, toRefs } from 'vue';
8 - import { Form, Col } from 'ant-design-vue'; 8 + import { Form, Col, Divider } from 'ant-design-vue';
9 import { componentMap } from '../componentMap'; 9 import { componentMap } from '../componentMap';
10 import { BasicHelp } from '/@/components/Basic'; 10 import { BasicHelp } from '/@/components/Basic';
11 import { isBoolean, isFunction, isNull } from '/@/utils/is'; 11 import { isBoolean, isFunction, isNull } from '/@/utils/is';
@@ -73,11 +73,17 @@ @@ -73,11 +73,17 @@
73 73
74 const getComponentsProps = computed(() => { 74 const getComponentsProps = computed(() => {
75 const { schema, tableAction, formModel, formActionType } = props; 75 const { schema, tableAction, formModel, formActionType } = props;
76 - const { componentProps = {} } = schema;  
77 - if (!isFunction(componentProps)) {  
78 - return componentProps; 76 + let { componentProps = {} } = schema;
  77 + if (isFunction(componentProps)) {
  78 + componentProps = componentProps({ schema, tableAction, formModel, formActionType }) ?? {};
79 } 79 }
80 - return componentProps({ schema, tableAction, formModel, formActionType }) ?? {}; 80 + if (schema.component === 'Divider') {
  81 + componentProps = Object.assign({ type: 'horizontal' }, componentProps, {
  82 + orientation: 'left',
  83 + plain: true,
  84 + });
  85 + }
  86 + return componentProps;
81 }); 87 });
82 88
83 const getDisable = computed(() => { 89 const getDisable = computed(() => {
@@ -300,38 +306,46 @@ @@ -300,38 +306,46 @@
300 } 306 }
301 307
302 function renderItem() { 308 function renderItem() {
303 - const { itemProps, slot, render, field, suffix } = props.schema; 309 + const { itemProps, slot, render, field, suffix, component, label } = props.schema;
304 const { labelCol, wrapperCol } = unref(itemLabelWidthProp); 310 const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
305 const { colon } = props.formProps; 311 const { colon } = props.formProps;
306 312
307 - const getContent = () => {  
308 - return slot  
309 - ? getSlot(slots, slot, unref(getValues))  
310 - : render  
311 - ? render(unref(getValues))  
312 - : renderComponent();  
313 - };  
314 -  
315 - const showSuffix = !!suffix;  
316 - const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;  
317 -  
318 - return (  
319 - <Form.Item  
320 - name={field}  
321 - colon={colon}  
322 - class={{ 'suffix-item': showSuffix }}  
323 - {...(itemProps as Recordable)}  
324 - label={renderLabelHelpMessage()}  
325 - rules={handleRules()}  
326 - labelCol={labelCol}  
327 - wrapperCol={wrapperCol}  
328 - >  
329 - <div style="display:flex">  
330 - <div style="flex:1">{getContent()}</div>  
331 - {showSuffix && <span class="suffix">{getSuffix}</span>}  
332 - </div>  
333 - </Form.Item>  
334 - ); 313 + if (component === 'Divider') {
  314 + return (
  315 + <Col span={24}>
  316 + <Divider {...unref(getComponentsProps)}>{label}</Divider>
  317 + </Col>
  318 + );
  319 + } else {
  320 + const getContent = () => {
  321 + return slot
  322 + ? getSlot(slots, slot, unref(getValues))
  323 + : render
  324 + ? render(unref(getValues))
  325 + : renderComponent();
  326 + };
  327 +
  328 + const showSuffix = !!suffix;
  329 + const getSuffix = isFunction(suffix) ? suffix(unref(getValues)) : suffix;
  330 +
  331 + return (
  332 + <Form.Item
  333 + name={field}
  334 + colon={colon}
  335 + class={{ 'suffix-item': showSuffix }}
  336 + {...(itemProps as Recordable)}
  337 + label={renderLabelHelpMessage()}
  338 + rules={handleRules()}
  339 + labelCol={labelCol}
  340 + wrapperCol={wrapperCol}
  341 + >
  342 + <div style="display:flex">
  343 + <div style="flex:1">{getContent()}</div>
  344 + {showSuffix && <span class="suffix">{getSuffix}</span>}
  345 + </div>
  346 + </Form.Item>
  347 + );
  348 + }
335 } 349 }
336 350
337 return () => { 351 return () => {
src/components/Form/src/hooks/useFormEvents.ts
@@ -149,7 +149,9 @@ export function useFormEvents({ @@ -149,7 +149,9 @@ export function useFormEvents({
149 updateData = [...data]; 149 updateData = [...data];
150 } 150 }
151 151
152 - const hasField = updateData.every((item) => Reflect.has(item, 'field') && item.field); 152 + const hasField = updateData.every(
  153 + (item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field)
  154 + );
153 155
154 if (!hasField) { 156 if (!hasField) {
155 error( 157 error(
@@ -169,7 +171,9 @@ export function useFormEvents({ @@ -169,7 +171,9 @@ export function useFormEvents({
169 updateData = [...data]; 171 updateData = [...data];
170 } 172 }
171 173
172 - const hasField = updateData.every((item) => Reflect.has(item, 'field') && item.field); 174 + const hasField = updateData.every(
  175 + (item) => item.component === 'Divider' || (Reflect.has(item, 'field') && item.field)
  176 + );
173 177
174 if (!hasField) { 178 if (!hasField) {
175 error( 179 error(
src/components/Form/src/types/index.ts
@@ -109,4 +109,5 @@ export type ComponentType = @@ -109,4 +109,5 @@ export type ComponentType =
109 | 'IconPicker' 109 | 'IconPicker'
110 | 'Render' 110 | 'Render'
111 | 'Slider' 111 | 'Slider'
112 - | 'Rate'; 112 + | 'Rate'
  113 + | 'Divider';
src/views/demo/form/AdvancedForm.vue
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <script lang="ts"> 12 <script lang="ts">
13 import { defineComponent } from 'vue'; 13 import { defineComponent } from 'vue';
14 import { BasicForm, FormSchema, useForm } from '/@/components/Form/index'; 14 import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
15 - import { CollapseContainer } from '/@/components/Container/index'; 15 + import { CollapseContainer } from '/@/components/Container';
16 import { PageWrapper } from '/@/components/Page'; 16 import { PageWrapper } from '/@/components/Page';
17 17
18 const getSchamas = (): FormSchema[] => { 18 const getSchamas = (): FormSchema[] => {
@@ -173,7 +173,12 @@ @@ -173,7 +173,12 @@
173 } 173 }
174 const [register1] = useForm({ 174 const [register1] = useForm({
175 labelWidth: 120, 175 labelWidth: 120,
176 - schemas: [...getSchamas(), ...getAppendSchemas(), ...extraSchemas], 176 + schemas: [
  177 + ...getSchamas(),
  178 + ...getAppendSchemas(),
  179 + { field: '', component: 'Divider', label: '更多字段' },
  180 + ...extraSchemas,
  181 + ],
177 actionColOptions: { 182 actionColOptions: {
178 span: 24, 183 span: 24,
179 }, 184 },
src/views/demo/form/index.vue
@@ -101,6 +101,11 @@ @@ -101,6 +101,11 @@
101 101
102 const schemas: FormSchema[] = [ 102 const schemas: FormSchema[] = [
103 { 103 {
  104 + field: '',
  105 + component: 'Divider',
  106 + label: '基础字段',
  107 + },
  108 + {
104 field: 'field1', 109 field: 'field1',
105 component: 'Input', 110 component: 'Input',
106 label: '字段1', 111 label: '字段1',
@@ -294,6 +299,11 @@ @@ -294,6 +299,11 @@
294 }, 299 },
295 }, 300 },
296 { 301 {
  302 + field: '',
  303 + component: 'Divider',
  304 + label: '远程下拉演示',
  305 + },
  306 + {
297 field: 'field30', 307 field: 'field30',
298 component: 'ApiSelect', 308 component: 'ApiSelect',
299 label: '懒加载远程下拉', 309 label: '懒加载远程下拉',
@@ -363,6 +373,11 @@ @@ -363,6 +373,11 @@
363 }, 373 },
364 }, 374 },
365 { 375 {
  376 + field: '',
  377 + component: 'Divider',
  378 + label: '其它',
  379 + },
  380 + {
366 field: 'field20', 381 field: 'field20',
367 component: 'InputNumber', 382 component: 'InputNumber',
368 label: '字段20', 383 label: '字段20',