Commit 5832ee6697e23afefc25ba2aa4df9476b5034bf4

Authored by vben
1 parent 6676c950

feat(form): support function type of form item

CHANGELOG.zh_CN.md
1 1 ## Wip
2 2  
  3 +### ✨ Features
  4 +
  5 +- 表单项的`componentsProps`支持函数类型
  6 +
3 7 ### 🐛 Bug Fixes
4 8  
5 9 - 修复多个富文本编辑器只显示一个
... ...
src/components/Drawer/src/useDrawer.ts
... ... @@ -6,7 +6,16 @@ import type {
6 6 UseDrawerInnerReturnType,
7 7 } from './types';
8 8  
9   -import { ref, getCurrentInstance, onUnmounted, unref, reactive, computed, watchEffect } from 'vue';
  9 +import {
  10 + ref,
  11 + getCurrentInstance,
  12 + onUnmounted,
  13 + unref,
  14 + reactive,
  15 + computed,
  16 + watchEffect,
  17 + nextTick,
  18 +} from 'vue';
10 19  
11 20 import { isProdMode } from '/@/utils/env';
12 21 import { isFunction } from '/@/utils/is';
... ... @@ -94,7 +103,9 @@ export const useDrawerInner = (callbackFn?: Fn): UseDrawerInnerReturnType => {
94 103 const data = dataTransferRef[unref(uidRef)];
95 104 if (!data) return;
96 105 if (!callbackFn || !isFunction(callbackFn)) return;
97   - callbackFn(data);
  106 + nextTick(() => {
  107 + callbackFn(data);
  108 + });
98 109 });
99 110  
100 111 return [
... ...
src/components/Form/src/BasicForm.vue
... ... @@ -4,6 +4,7 @@
4 4 <slot name="formHeader" />
5 5 <template v-for="schema in getSchema" :key="schema.field">
6 6 <FormItem
  7 + :tableAction="tableAction"
7 8 :schema="schema"
8 9 :formProps="getProps"
9 10 :allDefaultValues="defaultValueRef"
... ...
src/components/Form/src/FormItem.tsx
... ... @@ -2,6 +2,7 @@ import type { PropType } from &#39;vue&#39;;
2 2 import type { 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 +import type { TableActionType } from '../../Table/src/types/table';
5 6  
6 7 import { defineComponent, computed, unref, toRef } from 'vue';
7 8 import { Form, Col } from 'ant-design-vue';
... ... @@ -37,6 +38,9 @@ export default defineComponent({
37 38 type: Object as PropType<any>,
38 39 default: {},
39 40 },
  41 + tableAction: {
  42 + type: Object as PropType<TableActionType>,
  43 + },
40 44 },
41 45 setup(props, { slots }) {
42 46 const itemLabelWidthRef = useItemLabelWidth(toRef(props, 'schema'), toRef(props, 'formProps'));
... ... @@ -56,10 +60,19 @@ export default defineComponent({
56 60 };
57 61 });
58 62  
  63 + const getComponentsPropsRef = computed(() => {
  64 + const { schema, tableAction, formModel } = props;
  65 + const { componentProps = {} } = schema;
  66 + if (!isFunction(componentProps)) {
  67 + return componentProps;
  68 + }
  69 + return componentProps({ schema, tableAction, formModel }) || {};
  70 + });
  71 +
59 72 const getDisableRef = computed(() => {
60 73 const { disabled: globDisabled } = props.formProps;
61   - const { dynamicDisabled, componentProps = {} } = props.schema;
62   - const { disabled: itemDisabled = false } = componentProps;
  74 + const { dynamicDisabled } = props.schema;
  75 + const { disabled: itemDisabled = false } = unref(getComponentsPropsRef);
63 76 let disabled = !!globDisabled || itemDisabled;
64 77 if (isBoolean(dynamicDisabled)) {
65 78 disabled = dynamicDisabled;
... ... @@ -166,13 +179,7 @@ export default defineComponent({
166 179 }
167 180  
168 181 function renderComponent() {
169   - const {
170   - componentProps,
171   - renderComponentContent,
172   - component,
173   - field,
174   - changeEvent = 'change',
175   - } = props.schema;
  182 + const { renderComponentContent, component, field, changeEvent = 'change' } = props.schema;
176 183  
177 184 const isCheck = component && ['Switch'].includes(component);
178 185  
... ... @@ -192,7 +199,7 @@ export default defineComponent({
192 199 allowClear: true,
193 200 getPopupContainer: (trigger: Element) => trigger.parentNode,
194 201 size,
195   - ...componentProps,
  202 + ...unref(getComponentsPropsRef),
196 203 disabled: unref(getDisableRef),
197 204 };
198 205  
... ... @@ -201,7 +208,8 @@ export default defineComponent({
201 208 // RangePicker place为数组
202 209 if (isCreatePlaceholder && component !== 'RangePicker' && component) {
203 210 placeholder =
204   - (componentProps && componentProps.placeholder) || createPlaceholderMessage(component);
  211 + (unref(getComponentsPropsRef) && unref(getComponentsPropsRef).placeholder) ||
  212 + createPlaceholderMessage(component);
205 213 }
206 214 propsData.placeholder = placeholder;
207 215 propsData.codeField = field;
... ...
src/components/Form/src/props.ts
1 1 import type { FieldMapToTime, FormSchema } from './types/form';
2 2 import type { PropType } from 'vue';
3 3 import type { ColEx } from './types';
  4 +import { TableActionType } from '../../Table/src/types/table';
4 5  
5 6 export const basicProps = {
6 7 model: {
... ... @@ -103,6 +104,9 @@ export const basicProps = {
103 104 type: String as PropType<'horizontal' | 'vertical' | 'inline'>,
104 105 default: 'horizontal',
105 106 },
  107 + tableAction: {
  108 + type: Object as PropType<TableActionType>,
  109 + },
106 110  
107 111 wrapperCol: Object as PropType<any>,
108 112  
... ...
src/components/Form/src/types/form.ts
... ... @@ -3,6 +3,7 @@ import type { VNode } from &#39;vue&#39;;
3 3 import type { BasicButtonProps } from '/@/components/Button/types';
4 4 import type { FormItem } from './formItem';
5 5 import type { ColEx, ComponentType } from './index';
  6 +import { TableActionType } from '../../../Table/src/types/table';
6 7  
7 8 export type FieldMapToTime = [string, [string, string], string?][];
8 9  
... ... @@ -111,7 +112,9 @@ export interface FormSchema {
111 112 // 组件
112 113 component: ComponentType;
113 114 // 组件参数
114   - componentProps?: any;
  115 + componentProps?:
  116 + | ((opt: { schema: FormSchema; tableAction: TableActionType; formModel: any }) => any)
  117 + | object;
115 118 // 必填
116 119 required?: boolean;
117 120  
... ...
src/components/Modal/src/useModal.ts
... ... @@ -5,7 +5,16 @@ import type {
5 5 ReturnMethods,
6 6 UseModalInnerReturnType,
7 7 } from './types';
8   -import { ref, onUnmounted, unref, getCurrentInstance, reactive, computed, watchEffect } from 'vue';
  8 +import {
  9 + ref,
  10 + onUnmounted,
  11 + unref,
  12 + getCurrentInstance,
  13 + reactive,
  14 + computed,
  15 + watchEffect,
  16 + nextTick,
  17 +} from 'vue';
9 18 import { isProdMode } from '/@/utils/env';
10 19 import { isFunction } from '/@/utils/is';
11 20 const dataTransferRef = reactive<any>({});
... ... @@ -89,7 +98,9 @@ export const useModalInner = (callbackFn?: Fn): UseModalInnerReturnType =&gt; {
89 98 const data = dataTransferRef[unref(uidRef)];
90 99 if (!data) return;
91 100 if (!callbackFn || !isFunction(callbackFn)) return;
92   - callbackFn(data);
  101 + nextTick(() => {
  102 + callbackFn(data);
  103 + });
93 104 });
94 105  
95 106 return [
... ...
src/components/Table/src/BasicTable.vue
... ... @@ -11,6 +11,7 @@
11 11 v-if="getBindValues.useSearchForm"
12 12 :submitOnReset="true"
13 13 :submitButtonOptions="{ loading }"
  14 + :tableAction="tableAction"
14 15 @register="registerForm"
15 16 @submit="handleSearchInfoChange"
16 17 @advanced-change="redoHeight"
... ... @@ -321,6 +322,7 @@
321 322 handleTableChange,
322 323 getRowClassName,
323 324 wrapRef,
  325 + tableAction,
324 326 ...tableAction,
325 327 };
326 328 },
... ...
src/components/Table/src/components/renderEditableCell.tsx
... ... @@ -38,7 +38,8 @@ const EditableCell = defineComponent({
38 38 default: 'Input',
39 39 },
40 40 },
41   - setup(props, { attrs }) {
  41 + emits: ['submit', 'cancel'],
  42 + setup(props, { attrs, emit }) {
42 43 const table = injectTable();
43 44 const elRef = ref<any>(null);
44 45  
... ... @@ -64,6 +65,7 @@ const EditableCell = defineComponent({
64 65  
65 66 function handleCancel() {
66 67 isEditRef.value = false;
  68 + emit('cancel');
67 69 }
68 70  
69 71 function handleSubmit() {
... ... @@ -78,6 +80,7 @@ const EditableCell = defineComponent({
78 80 const target = dataSource.find((item) => item.key === dataKey);
79 81 if (target) {
80 82 target[dataIndex] = unref(currentValueRef);
  83 + emit('submit', { dataKey, dataIndex, value: unref(currentValueRef) });
81 84 }
82 85 }
83 86  
... ...
src/views/demo/comp/drawer/Drawer4.vue
... ... @@ -7,7 +7,7 @@
7 7 </BasicDrawer>
8 8 </template>
9 9 <script lang="ts">
10   - import { defineComponent, nextTick } from 'vue';
  10 + import { defineComponent } from 'vue';
11 11 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
12 12  
13 13 import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
... ... @@ -42,12 +42,10 @@
42 42 },
43 43 });
44 44 const [register, { receiveDrawerDataRef }] = useDrawerInner((data) => {
45   - nextTick(() => {
46   - // 方式1
47   - setFieldsValue({
48   - field2: data.data,
49   - field1: data.info,
50   - });
  45 + // 方式1
  46 + setFieldsValue({
  47 + field2: data.data,
  48 + field1: data.info,
51 49 });
52 50 });
53 51 return { register, receiveDrawerDataRef, schemas, registerForm };
... ...
src/views/demo/comp/modal/Modal4.vue
... ... @@ -5,7 +5,7 @@
5 5 </BasicModal>
6 6 </template>
7 7 <script lang="ts">
8   - import { defineComponent, nextTick, ref } from 'vue';
  8 + import { defineComponent, ref } from 'vue';
9 9 import { BasicModal, useModalInner } from '/@/components/Modal';
10 10 import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
11 11 const schemas: FormSchema[] = [
... ... @@ -47,20 +47,18 @@
47 47 });
48 48  
49 49 const [register, { receiveModalDataRef }] = useModalInner((data) => {
50   - nextTick(() => {
51   - // 方式1
52   - // setFieldsValue({
53   - // field2: data.data,
54   - // field1: data.info,
55   - // });
  50 + // 方式1
  51 + // setFieldsValue({
  52 + // field2: data.data,
  53 + // field1: data.info,
  54 + // });
56 55  
57   - // 方式2
58   - modelRef.value = { field2: data.data, field1: data.info };
  56 + // 方式2
  57 + modelRef.value = { field2: data.data, field1: data.info };
59 58  
60   - // setProps({
61   - // model:{ field2: data.data, field1: data.info }
62   - // })
63   - });
  59 + // setProps({
  60 + // model:{ field2: data.data, field1: data.info }
  61 + // })
64 62 });
65 63 return { register, receiveModalDataRef, schemas, registerForm, model: modelRef };
66 64 },
... ...
src/views/demo/form/index.vue
... ... @@ -24,11 +24,13 @@
24 24 span: 8,
25 25 },
26 26 defaultValue: '111',
27   - componentProps: {
28   - placeholder: '自定义placeholder',
29   - onChange: (e: any) => {
30   - console.log(e);
31   - },
  27 + componentProps: () => {
  28 + return {
  29 + placeholder: '自定义placeholder',
  30 + onChange: (e: any) => {
  31 + console.log(e);
  32 + },
  33 + };
32 34 },
33 35 },
34 36 {
... ...