fix(editor): 表单组件保持单向数据流

This commit is contained in:
roymondchen 2025-10-31 11:56:32 +08:00
parent 6f0498a9e7
commit 564a7f4271
6 changed files with 78 additions and 77 deletions

View File

@ -2,13 +2,15 @@
<div class="m-fields-code-select-col">
<div class="code-select-container">
<!-- 代码块下拉框 -->
<MContainer
<MSelect
class="select"
:config="selectConfig"
:name="name"
:model="model"
:size="size"
:prop="prop"
@change="onCodeIdChangeHandler"
></MContainer>
></MSelect>
<!-- 查看/编辑按钮 -->
<TMagicButton
@ -28,6 +30,7 @@
:key="model[name]"
:model="model"
:size="size"
:disabled="disabled"
:params-config="paramsConfig"
@change="onParamsChangeHandler"
></CodeParams>
@ -48,7 +51,8 @@ import {
type FieldProps,
filterFunction,
type FormState,
MContainer,
MSelect,
type SelectConfig,
} from '@tmagic/form';
import CodeParams from '@editor/components/CodeParams.vue';
@ -108,7 +112,7 @@ watch(
},
);
const selectConfig = {
const selectConfig: SelectConfig = {
type: 'select',
name: props.name,
disable: props.disabled,
@ -122,33 +126,26 @@ const selectConfig = {
}
return [];
},
onChange: (formState: any, codeId: Id, { setModel, model }: any) => {
// codeIdmodelcodeIdparams
paramsConfig.value = getParamItemsConfig(codeId);
if (paramsConfig.value.length) {
setModel('params', createValues(formState, paramsConfig.value, {}, model.params));
} else {
setModel('params', {});
}
return codeId;
},
};
const onCodeIdChangeHandler = (value: any, eventData: ContainerChangeEventData) => {
props.model.params = value.params;
const onCodeIdChangeHandler = (value: any) => {
// codeIdmodelcodeIdparams
paramsConfig.value = getParamItemsConfig(value);
emit('change', props.model, {
changeRecords: eventData.changeRecords?.map((item) => ({
prop: `${props.prop.replace(props.name, '')}${item.propPath}`,
value: item.value,
})) || [
{
propPath: props.prop,
value: value[props.name],
},
],
const changeRecords = [
{
propPath: props.prop,
value,
},
];
changeRecords.push({
propPath: props.prop.replace(`${props.name}`, 'params'),
value: paramsConfig.value.length ? createValues(mForm, paramsConfig.value, {}, props.model.params) : {},
});
emit('change', value, {
changeRecords,
});
};
@ -156,14 +153,10 @@ const onCodeIdChangeHandler = (value: any, eventData: ContainerChangeEventData)
* 参数值修改更新
*/
const onParamsChangeHandler = (value: any, eventData: ContainerChangeEventData) => {
props.model.params = value.params;
emit('change', props.model, {
...eventData,
changeRecords: (eventData.changeRecords || []).map((item) => ({
prop: `${props.prop.replace(props.name, '')}${item.propPath}`,
value: item.value,
})),
eventData.changeRecords?.forEach((record) => {
record.propPath = `${props.prop.replace(`${props.name}`, '')}${record.propPath}`;
});
emit('change', props.model[props.name], eventData);
};
const editCode = (id: string) => {

View File

@ -1,6 +1,6 @@
<template>
<TMagicSelect
v-model="model[name]"
:model-value="model[name]"
clearable
filterable
:size="size"

View File

@ -1,13 +1,16 @@
<template>
<div class="m-fields-data-source-method-select">
<div class="data-source-method-select-container">
<MContainer
<MCascader
class="select"
:config="cascaderConfig"
:model="model"
:name="name"
:size="size"
:disabled="disabled"
:prop="prop"
@change="onChangeHandler"
></MContainer>
></MCascader>
<TMagicTooltip
v-if="model[name] && isCustomMethod && hasDataSourceSidePanel"
@ -22,11 +25,12 @@
<CodeParams
v-if="paramsConfig.length"
name="params"
:key="model[name]"
:model="model"
:size="size"
:disabled="disabled"
:params-config="paramsConfig"
@change="onChangeHandler"
@change="onParamsChangeHandler"
></CodeParams>
</div>
</template>
@ -38,13 +42,14 @@ import { Edit, View } from '@element-plus/icons-vue';
import type { Id } from '@tmagic/core';
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
import {
type CascaderConfig,
type ContainerChangeEventData,
createValues,
type DataSourceMethodSelectConfig,
type FieldProps,
filterFunction,
type FormState,
MContainer,
type OnChangeHandlerData,
MCascader,
} from '@tmagic/form';
import CodeParams from '@editor/components/CodeParams.vue';
@ -100,21 +105,6 @@ const getParamItemsConfig = ([dataSourceId, methodName]: [Id, string] = ['', '']
const paramsConfig = ref<CodeParamStatement[]>(getParamItemsConfig(props.model[props.name || 'dataSourceMethod']));
const setParamsConfig = (
dataSourceMethod: [Id, string],
formState: any = {},
setModel: OnChangeHandlerData['setModel'],
) => {
// codeIdmodelcodeIdparams
paramsConfig.value = dataSourceMethod ? getParamItemsConfig(dataSourceMethod) : [];
if (paramsConfig.value.length) {
setModel('params', createValues(formState, paramsConfig.value, {}, props.model.params));
} else {
setModel('params', {});
}
};
const methodsOptions = computed(
() =>
dataSources.value
@ -132,24 +122,42 @@ const methodsOptions = computed(
})) || [],
);
const cascaderConfig = computed(() => ({
const cascaderConfig = computed<CascaderConfig>(() => ({
type: 'cascader',
name: props.name,
options: methodsOptions.value,
disable: props.disabled,
onChange: (formState: any, dataSourceMethod: [Id, string], { setModel }: OnChangeHandlerData) => {
setParamsConfig(dataSourceMethod, formState, setModel);
return dataSourceMethod;
},
}));
/**
* 参数值修改更新
*/
const onChangeHandler = (value: any) => {
props.model.params = value.params;
emit('change', props.model);
paramsConfig.value = getParamItemsConfig(value);
const changeRecords = [
{
propPath: props.prop,
value,
},
];
changeRecords.push({
propPath: props.prop.replace(`${props.name}`, 'params'),
value: paramsConfig.value.length ? createValues(mForm, paramsConfig.value, {}, props.model.params) : {},
});
emit('change', value, {
changeRecords,
});
};
/**
* 参数值修改更新
*/
const onParamsChangeHandler = (value: any, eventData: ContainerChangeEventData) => {
eventData.changeRecords?.forEach((record) => {
record.propPath = `${props.prop.replace(`${props.name}`, '')}${record.propPath}`;
});
emit('change', props.model[props.name], eventData);
};
const editCodeHandler = () => {

View File

@ -219,7 +219,6 @@ const targetCompConfig = computed(() => {
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
onChange: (MForm: FormState, v: string, { setModel }: OnChangeHandlerData) => {
setModel('method', '');
return v;
},
};
return { ...defaultTargetCompConfig, ...props.config.targetCompConfig };

View File

@ -2,13 +2,16 @@
<div class="m-fields-page-fragment-select">
<div class="page-fragment-select-container">
<!-- 页面片下拉框 -->
<m-form-container
<MSelect
class="select"
:config="selectConfig"
:model="model"
:name="name"
:size="size"
:prop="prop"
:disabled="disabled"
@change="changeHandler"
></m-form-container>
></MSelect>
<!-- 编辑按钮 -->
<Icon v-if="model[name]" class="icon" :icon="Edit" @click="editPageFragment(model[name])"></Icon>
</div>
@ -20,7 +23,7 @@ import { computed } from 'vue';
import { Edit } from '@element-plus/icons-vue';
import { Id, NodeType } from '@tmagic/core';
import { FieldProps, type PageFragmentSelectConfig } from '@tmagic/form';
import { FieldProps, MSelect, type PageFragmentSelectConfig, type SelectConfig } from '@tmagic/form';
import Icon from '@editor/components/Icon.vue';
import { useServices } from '@editor/hooks/use-services';
@ -32,16 +35,16 @@ defineOptions({
const { editorService } = useServices();
const emit = defineEmits(['change']);
const props = withDefaults(defineProps<FieldProps<PageFragmentSelectConfig>>(), {
withDefaults(defineProps<FieldProps<PageFragmentSelectConfig>>(), {
disabled: false,
});
const pageList = computed(() =>
editorService.get('root')?.items.filter((item) => item.type === NodeType.PAGE_FRAGMENT),
);
const selectConfig = {
const selectConfig: SelectConfig = {
type: 'select',
name: props.name,
options: () => {
if (pageList.value) {
return pageList.value.map((item) => ({
@ -53,8 +56,8 @@ const selectConfig = {
return [];
},
};
const changeHandler = async () => {
emit('change', props.model[props.name]);
const changeHandler = (v: Id) => {
emit('change', v);
};
const editPageFragment = (id: Id) => {

View File

@ -79,7 +79,6 @@ const clickHandler = ({ detail }: Event & { detail: HTMLElement | MNode }) => {
id = getIdFromEl()(detail as HTMLElement) || id;
}
if (id) {
props.model[props.name] = id;
emit('change', id);
mForm?.$emit('field-change', props.prop, id);
}
@ -102,7 +101,6 @@ const startSelect = () => {
const deleteHandler = () => {
if (props.model) {
props.model[props.name] = '';
emit('change', '');
mForm?.$emit('field-change', props.prop, '');
}