From 5e0e776d4004c9a4ad2ae53d7146353dc088a478 Mon Sep 17 00:00:00 2001 From: roymondchen Date: Mon, 21 Apr 2025 19:42:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(form):=20onChange=E6=B7=BB=E5=8A=A0setMode?= =?UTF-8?q?l=E5=8F=82=E6=95=B0=EF=BC=8C=E7=94=A8=E4=BA=8E=E4=BF=AE?= =?UTF-8?q?=E6=94=B9model=E5=B9=B6=E6=B7=BB=E5=8A=A0=E8=87=B3=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E8=AE=B0=E5=BD=95=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor/src/fields/CodeSelect.vue | 12 ++++------ packages/editor/src/fields/CodeSelectCol.vue | 14 +++++++---- .../editor/src/fields/DataSourceFields.vue | 6 +++-- .../src/fields/DataSourceMethodSelect.vue | 23 ++++++++++++++----- packages/editor/src/fields/EventSelect.vue | 5 ++-- packages/form/src/containers/Container.vue | 9 +++++++- react-components/container/src/formConfig.ts | 6 ++--- .../iterator-container/src/formConfig.ts | 6 ++--- .../page-fragment/src/formConfig.ts | 6 ++--- react-components/page/src/formConfig.ts | 6 ++--- vue-components/container/src/formConfig.ts | 6 ++--- .../iterator-container/src/formConfig.ts | 6 ++--- .../page-fragment/src/formConfig.ts | 6 ++--- vue-components/page/src/formConfig.ts | 6 ++--- 14 files changed, 70 insertions(+), 47 deletions(-) diff --git a/packages/editor/src/fields/CodeSelect.vue b/packages/editor/src/fields/CodeSelect.vue index 6065e63c..e8ce5fe5 100644 --- a/packages/editor/src/fields/CodeSelect.vue +++ b/packages/editor/src/fields/CodeSelect.vue @@ -80,13 +80,11 @@ const codeConfig = computed(() => ({ { value: HookCodeType.DATA_SOURCE_METHOD, text: '数据源方法' }, ], defaultValue: 'code', - onChange: (mForm, v: HookCodeType, { model, prop, changeRecords }) => { + onChange: (_mForm, v: HookCodeType, { setModel }) => { if (v === HookCodeType.DATA_SOURCE_METHOD) { - model.codeId = []; - changeRecords.push({ propPath: prop.replace('codeType', 'codeId'), value: [] }); + setModel('codeId', []); } else { - model.codeId = ''; - changeRecords.push({ propPath: prop.replace('codeType', 'codeId'), value: '' }); + setModel('codeId', ''); } return v; @@ -97,7 +95,7 @@ const codeConfig = computed(() => ({ name: 'codeId', span: 18, labelWidth: 0, - display: (mForm, { model }) => model.codeType !== HookCodeType.DATA_SOURCE_METHOD, + display: (_mForm, { model }) => model.codeType !== HookCodeType.DATA_SOURCE_METHOD, notEditable: () => !codeBlockService.getEditStatus(), }, { @@ -105,7 +103,7 @@ const codeConfig = computed(() => ({ name: 'codeId', span: 18, labelWidth: 0, - display: (mForm, { model }) => model.codeType === HookCodeType.DATA_SOURCE_METHOD, + display: (_mForm, { model }) => model.codeType === HookCodeType.DATA_SOURCE_METHOD, notEditable: () => !dataSourceService.get('editable'), }, ], diff --git a/packages/editor/src/fields/CodeSelectCol.vue b/packages/editor/src/fields/CodeSelectCol.vue index f03742f1..ade54975 100644 --- a/packages/editor/src/fields/CodeSelectCol.vue +++ b/packages/editor/src/fields/CodeSelectCol.vue @@ -121,24 +121,28 @@ const selectConfig = { } return []; }, - onChange: (formState: any, codeId: Id, { model }: any) => { + onChange: (formState: any, codeId: Id, { setModel, model }: any) => { // 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params paramsConfig.value = getParamItemsConfig(codeId); if (paramsConfig.value.length) { - model.params = createValues(formState, paramsConfig.value, {}, model.params); + setModel('params', createValues(formState, paramsConfig.value, {}, model.params)); } else { - model.params = {}; + setModel('params', {}); } return codeId; }, }; -const onCodeIdChangeHandler = (value: any) => { +const onCodeIdChangeHandler = (value: any, eventData: ContainerChangeEventData) => { props.model.params = value.params; + emit('change', props.model, { - changeRecords: [ + changeRecords: eventData.changeRecords?.map((item) => ({ + prop: `${props.prop.replace(props.name, '')}${item.propPath}`, + value: item.value, + })) || [ { propPath: props.prop, value: value[props.name], diff --git a/packages/editor/src/fields/DataSourceFields.vue b/packages/editor/src/fields/DataSourceFields.vue index fbe98d2f..b3acc7f3 100644 --- a/packages/editor/src/fields/DataSourceFields.vue +++ b/packages/editor/src/fields/DataSourceFields.vue @@ -65,6 +65,7 @@ import FloatingBox from '@editor/components/FloatingBox.vue'; import { useEditorContentHeight } from '@editor/hooks'; import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position'; import { useServices } from '@editor/hooks/use-services'; +import { error } from '@editor/utils/logger'; defineOptions({ name: 'MFieldsDataSourceFields', @@ -144,6 +145,7 @@ const fieldColumns: ColumnConfig[] = [ try { return JSON.stringify(row.defaultValue); } catch (e) { + error(e); return row.defaultValue; } }, @@ -193,9 +195,9 @@ const dataSourceFieldsConfig: FormConfig = [ { text: 'null', value: 'null' }, { text: 'any', value: 'any' }, ], - onChange: (formState, v: string, { model }) => { + onChange: (_formState, v: string, { setModel }) => { if (!['any', 'array', 'object'].includes(v)) { - model.fields = []; + setModel('fields', []); } return v; }, diff --git a/packages/editor/src/fields/DataSourceMethodSelect.vue b/packages/editor/src/fields/DataSourceMethodSelect.vue index af1e928c..a06eaba6 100644 --- a/packages/editor/src/fields/DataSourceMethodSelect.vue +++ b/packages/editor/src/fields/DataSourceMethodSelect.vue @@ -37,7 +37,14 @@ import { Edit, View } from '@element-plus/icons-vue'; import type { Id } from '@tmagic/core'; import { TMagicButton, TMagicTooltip } from '@tmagic/design'; -import { createValues, type FieldProps, filterFunction, type FormState, MContainer } from '@tmagic/form'; +import { + createValues, + type FieldProps, + filterFunction, + type FormState, + MContainer, + type OnChangeHandlerData, +} from '@tmagic/form'; import CodeParams from '@editor/components/CodeParams.vue'; import MIcon from '@editor/components/Icon.vue'; @@ -92,14 +99,18 @@ const getParamItemsConfig = ([dataSourceId, methodName]: [Id, string] = ['', ''] const paramsConfig = ref(getParamItemsConfig(props.model[props.name || 'dataSourceMethod'])); -const setParamsConfig = (dataSourceMethod: [Id, string], formState: any = {}) => { +const setParamsConfig = ( + dataSourceMethod: [Id, string], + formState: any = {}, + setModel: OnChangeHandlerData['setModel'], +) => { // 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params paramsConfig.value = dataSourceMethod ? getParamItemsConfig(dataSourceMethod) : []; if (paramsConfig.value.length) { - props.model.params = createValues(formState, paramsConfig.value, {}, props.model.params); + setModel('params', createValues(formState, paramsConfig.value, {}, props.model.params)); } else { - props.model.params = {}; + setModel('params', {}); } }; @@ -125,8 +136,8 @@ const cascaderConfig = computed(() => ({ name: props.name, options: methodsOptions.value, disable: props.disabled, - onChange: (formState: any, dataSourceMethod: [Id, string]) => { - setParamsConfig(dataSourceMethod, formState); + onChange: (formState: any, dataSourceMethod: [Id, string], { setModel }: OnChangeHandlerData) => { + setParamsConfig(dataSourceMethod, formState, setModel); return dataSourceMethod; }, diff --git a/packages/editor/src/fields/EventSelect.vue b/packages/editor/src/fields/EventSelect.vue index ce0c78af..7ede202b 100644 --- a/packages/editor/src/fields/EventSelect.vue +++ b/packages/editor/src/fields/EventSelect.vue @@ -63,6 +63,7 @@ import type { ContainerChangeEventData, FieldProps, FormState, + OnChangeHandlerData, PanelConfig, } from '@tmagic/form'; import { MContainer as MFormContainer, MPanel } from '@tmagic/form'; @@ -202,8 +203,8 @@ const targetCompConfig = computed(() => { text: '联动组件', type: 'ui-select', display: (mForm: FormState, { model }: { model: Record }) => model.actionType === ActionType.COMP, - onChange: (MForm: FormState, v: string, { model }: any) => { - model.method = ''; + onChange: (MForm: FormState, v: string, { setModel }: OnChangeHandlerData) => { + setModel('method', ''); return v; }, }; diff --git a/packages/form/src/containers/Container.vue b/packages/form/src/containers/Container.vue index 978b3eb2..e3d334db 100644 --- a/packages/form/src/containers/Container.vue +++ b/packages/form/src/containers/Container.vue @@ -228,6 +228,7 @@ import { WarningFilled } from '@element-plus/icons-vue'; import { isEqual } from 'lodash-es'; import { TMagicButton, TMagicFormItem, TMagicIcon, TMagicTooltip } from '@tmagic/design'; +import { setValueByKeyPath } from '@tmagic/utils'; import type { ChildConfig, ContainerChangeEventData, ContainerCommonConfig, FormState, FormValue } from '../schema'; import { display as displayFunction, filterFunction, getRules } from '../utils/form'; @@ -423,6 +424,12 @@ const onChangeHandler = async function (v: any, eventData: ContainerChangeEventD prop: itemProp.value, config: props.config, changeRecords: newChangeRecords, + setModel: (key: string, value: any) => { + setValueByKeyPath(key, value, props.model); + if (props.config.name) { + newChangeRecords.push({ propPath: itemProp.value.replace(`${props.config.name}`, key), value }); + } + }, })) ?? value; } value = trimHandler(trim, value) ?? value; @@ -442,10 +449,10 @@ const onChangeHandler = async function (v: any, eventData: ContainerChangeEventD valueProp = valueProp ? `${valueProp}.${eventData.modifyKey}` : eventData.modifyKey!; // 需要清除掉modifyKey,不然往上层抛出后还会被认为需要修改 + // eslint-disable-next-line no-param-reassign delete eventData.modifyKey; } else if (isValidName() && props.model !== value && (v !== value || props.model[name.value] !== value)) { // field内容下包含field-link时,model===value, 这里避免循环引用 - // eslint-disable-next-line vue/no-mutating-props props.model[name.value] = value; } diff --git a/react-components/container/src/formConfig.ts b/react-components/container/src/formConfig.ts index 15b707ac..7b134a61 100644 --- a/react-components/container/src/formConfig.ts +++ b/react-components/container/src/formConfig.ts @@ -28,14 +28,14 @@ export default [ { value: 'absolute', text: '绝对定位' }, { value: 'relative', text: '流式布局' }, ], - onChange: (formState: any, v: string, { model }: any) => { + onChange: (formState: any, v: string, { setModel, model }: any) => { if (!model.style) return v; if (v === 'relative') { - model.style.height = 'auto'; + setModel('style.height', 'auto'); } else { const el = getElById()(formState.stage?.renderer?.contentWindow.document, model.id); if (el) { - model.style.height = el.getBoundingClientRect().height; + setModel('style.height', el.getBoundingClientRect().height); } } }, diff --git a/react-components/iterator-container/src/formConfig.ts b/react-components/iterator-container/src/formConfig.ts index b3cfcbef..461ffcf0 100644 --- a/react-components/iterator-container/src/formConfig.ts +++ b/react-components/iterator-container/src/formConfig.ts @@ -25,12 +25,12 @@ export default [ dataSourceFieldType: ['array'], checkStrictly: true, type: 'data-source-field-select', - onChange: (_vm: any, v: string[] = [], { model }: any) => { + onChange: (_vm: any, v: string[] = [], { setModel }: any) => { if (Array.isArray(v) && v.length > 1) { const [dsId, ...keys] = v; - model.dsField = [dsId.replace(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, ''), ...keys]; + setModel('dsField', [dsId.replace(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, ''), ...keys]); } else { - model.dsField = []; + setModel('dsField', []); } }, }, diff --git a/react-components/page-fragment/src/formConfig.ts b/react-components/page-fragment/src/formConfig.ts index 8b0c6715..0bd318ad 100644 --- a/react-components/page-fragment/src/formConfig.ts +++ b/react-components/page-fragment/src/formConfig.ts @@ -37,14 +37,14 @@ export default [ { value: 'absolute', text: '绝对定位' }, { value: 'relative', text: '流式布局' }, ], - onChange: (formState: any, v: string, { model }: any) => { + onChange: (formState: any, v: string, { model, setModel }: any) => { if (!model.style) return v; if (v === 'relative') { - model.style.height = 'auto'; + setModel('style.height', 'auto'); } else { const el = getElById()(formState.stage?.renderer?.contentWindow.document, model.id); if (el) { - model.style.height = el.getBoundingClientRect().height; + setModel('style.height', el.getBoundingClientRect().height); } } }, diff --git a/react-components/page/src/formConfig.ts b/react-components/page/src/formConfig.ts index cdff7ddc..bc3a1d88 100644 --- a/react-components/page/src/formConfig.ts +++ b/react-components/page/src/formConfig.ts @@ -39,14 +39,14 @@ export default [ { value: 'absolute', text: '绝对定位' }, { value: 'relative', text: '流式布局' }, ], - onChange: (formState: any, v: string, { model }: any) => { + onChange: (formState: any, v: string, { model, setModel }: any) => { if (!model.style) return v; if (v === 'relative') { - model.style.height = 'auto'; + setModel('style.height', 'auto'); } else { const el = getElById()(formState.stage?.renderer?.contentWindow.document, model.id); if (el) { - model.style.height = el.getBoundingClientRect().height; + setModel('style.height', el.getBoundingClientRect().height); } } }, diff --git a/vue-components/container/src/formConfig.ts b/vue-components/container/src/formConfig.ts index 8afc103e..549f7dbb 100644 --- a/vue-components/container/src/formConfig.ts +++ b/vue-components/container/src/formConfig.ts @@ -33,14 +33,14 @@ export default [ { value: 'absolute', text: '绝对定位' }, { value: 'relative', text: '流式布局' }, ], - onChange: (formState: any, v: string, { model }: any) => { + onChange: (formState: any, v: string, { model, setModel }: any) => { if (!model.style) return v; if (v === 'relative') { - model.style.height = 'auto'; + setModel('style.height', 'auto'); } else { const el = getElById()(formState.stage?.renderer?.contentWindow.document, model.id); if (el) { - model.style.height = el.getBoundingClientRect().height; + setModel('style.height', el.getBoundingClientRect().height); } } }, diff --git a/vue-components/iterator-container/src/formConfig.ts b/vue-components/iterator-container/src/formConfig.ts index 5f0b34b2..bb8736ce 100644 --- a/vue-components/iterator-container/src/formConfig.ts +++ b/vue-components/iterator-container/src/formConfig.ts @@ -30,12 +30,12 @@ export default [ dataSourceFieldType: ['array'], checkStrictly: true, type: 'data-source-field-select', - onChange: (_vm: any, v: string[] = [], { model }: any) => { + onChange: (_vm: any, v: string[] = [], { setModel }: any) => { if (Array.isArray(v) && v.length > 1) { const [dsId, ...keys] = v; - model.dsField = [dsId.replace(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, ''), ...keys]; + setModel('dsField', [dsId.replace(DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, ''), ...keys]); } else { - model.dsField = []; + setModel('dsField', []); } }, }, diff --git a/vue-components/page-fragment/src/formConfig.ts b/vue-components/page-fragment/src/formConfig.ts index 8b0c6715..0bd318ad 100644 --- a/vue-components/page-fragment/src/formConfig.ts +++ b/vue-components/page-fragment/src/formConfig.ts @@ -37,14 +37,14 @@ export default [ { value: 'absolute', text: '绝对定位' }, { value: 'relative', text: '流式布局' }, ], - onChange: (formState: any, v: string, { model }: any) => { + onChange: (formState: any, v: string, { model, setModel }: any) => { if (!model.style) return v; if (v === 'relative') { - model.style.height = 'auto'; + setModel('style.height', 'auto'); } else { const el = getElById()(formState.stage?.renderer?.contentWindow.document, model.id); if (el) { - model.style.height = el.getBoundingClientRect().height; + setModel('style.height', el.getBoundingClientRect().height); } } }, diff --git a/vue-components/page/src/formConfig.ts b/vue-components/page/src/formConfig.ts index 234daa54..0d0e389f 100644 --- a/vue-components/page/src/formConfig.ts +++ b/vue-components/page/src/formConfig.ts @@ -38,14 +38,14 @@ export default [ { value: 'absolute', text: '绝对定位' }, { value: 'relative', text: '流式布局' }, ], - onChange: (formState: any, v: string, { model }: any) => { + onChange: (formState: any, v: string, { model, setModel }: any) => { if (!model.style) return v; if (v === 'relative') { - model.style.height = 'auto'; + setModel('style.height', 'auto'); } else { const el = getElById()(formState.stage?.renderer?.contentWindow.document, model.id); if (el) { - model.style.height = el.getBoundingClientRect().height; + setModel('style.height', el.getBoundingClientRect().height); } } },