Commit 5832ee6697e23afefc25ba2aa4df9476b5034bf4

Authored by vben
1 parent 6676c950

feat(form): support function type of form item

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