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 9 ## 2.7.1(2021-08-16)
2 10  
3 11 - 升级 vue 3.2,如果运行失败,删除 node_modules 后重装即可
... ...
src/components/Form/src/BasicForm.vue
... ... @@ -29,7 +29,7 @@
29 29 #[item]="data"
30 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 33 </template>
34 34 </FormAction>
35 35 <slot name="formFooter"></slot>
... ... @@ -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 142 const { handleToggleAdvanced } = useAdvanced({
... ...
src/components/Form/src/componentMap.ts
... ... @@ -18,6 +18,7 @@ import {
18 18 TreeSelect,
19 19 Slider,
20 20 Rate,
  21 + Divider,
21 22 } from 'ant-design-vue';
22 23  
23 24 import RadioButtonGroup from './components/RadioButtonGroup.vue';
... ... @@ -61,6 +62,7 @@ componentMap.set(&#39;IconPicker&#39;, IconPicker);
61 62 componentMap.set('InputCountDown', CountdownInput);
62 63  
63 64 componentMap.set('Upload', BasicUpload);
  65 +componentMap.set('Divider', Divider);
64 66  
65 67 export function add(compName: ComponentType, component: Component) {
66 68 componentMap.set(compName, component);
... ...
src/components/Form/src/components/FormItem.vue
... ... @@ -5,7 +5,7 @@
5 5 import type { ValidationRule } from 'ant-design-vue/lib/form/Form';
6 6 import type { TableActionType } from '/@/components/Table';
7 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 9 import { componentMap } from '../componentMap';
10 10 import { BasicHelp } from '/@/components/Basic';
11 11 import { isBoolean, isFunction, isNull } from '/@/utils/is';
... ... @@ -73,11 +73,17 @@
73 73  
74 74 const getComponentsProps = computed(() => {
75 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 89 const getDisable = computed(() => {
... ... @@ -300,38 +306,46 @@
300 306 }
301 307  
302 308 function renderItem() {
303   - const { itemProps, slot, render, field, suffix } = props.schema;
  309 + const { itemProps, slot, render, field, suffix, component, label } = props.schema;
304 310 const { labelCol, wrapperCol } = unref(itemLabelWidthProp);
305 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 351 return () => {
... ...
src/components/Form/src/hooks/useFormEvents.ts
... ... @@ -149,7 +149,9 @@ export function useFormEvents({
149 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 156 if (!hasField) {
155 157 error(
... ... @@ -169,7 +171,9 @@ export function useFormEvents({
169 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 178 if (!hasField) {
175 179 error(
... ...
src/components/Form/src/types/index.ts
... ... @@ -109,4 +109,5 @@ export type ComponentType =
109 109 | 'IconPicker'
110 110 | 'Render'
111 111 | 'Slider'
112   - | 'Rate';
  112 + | 'Rate'
  113 + | 'Divider';
... ...
src/views/demo/form/AdvancedForm.vue
... ... @@ -12,7 +12,7 @@
12 12 <script lang="ts">
13 13 import { defineComponent } from 'vue';
14 14 import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
15   - import { CollapseContainer } from '/@/components/Container/index';
  15 + import { CollapseContainer } from '/@/components/Container';
16 16 import { PageWrapper } from '/@/components/Page';
17 17  
18 18 const getSchamas = (): FormSchema[] => {
... ... @@ -173,7 +173,12 @@
173 173 }
174 174 const [register1] = useForm({
175 175 labelWidth: 120,
176   - schemas: [...getSchamas(), ...getAppendSchemas(), ...extraSchemas],
  176 + schemas: [
  177 + ...getSchamas(),
  178 + ...getAppendSchemas(),
  179 + { field: '', component: 'Divider', label: '更多字段' },
  180 + ...extraSchemas,
  181 + ],
177 182 actionColOptions: {
178 183 span: 24,
179 184 },
... ...
src/views/demo/form/index.vue
... ... @@ -101,6 +101,11 @@
101 101  
102 102 const schemas: FormSchema[] = [
103 103 {
  104 + field: '',
  105 + component: 'Divider',
  106 + label: '基础字段',
  107 + },
  108 + {
104 109 field: 'field1',
105 110 component: 'Input',
106 111 label: '字段1',
... ... @@ -294,6 +299,11 @@
294 299 },
295 300 },
296 301 {
  302 + field: '',
  303 + component: 'Divider',
  304 + label: '远程下拉演示',
  305 + },
  306 + {
297 307 field: 'field30',
298 308 component: 'ApiSelect',
299 309 label: '懒加载远程下拉',
... ... @@ -363,6 +373,11 @@
363 373 },
364 374 },
365 375 {
  376 + field: '',
  377 + component: 'Divider',
  378 + label: '其它',
  379 + },
  380 + {
366 381 field: 'field20',
367 382 component: 'InputNumber',
368 383 label: '字段20',
... ...