diff --git a/packages/core/src/App.ts b/packages/core/src/App.ts
index 51f39840..3d45d818 100644
--- a/packages/core/src/App.ts
+++ b/packages/core/src/App.ts
@@ -18,7 +18,7 @@
import { EventEmitter } from 'events';
-import { has, isEmpty } from 'lodash-es';
+import { has, isArray, isEmpty } from 'lodash-es';
import { createDataSourceManager, DataSource, DataSourceManager, ObservedDataClass } from '@tmagic/data-source';
import {
@@ -228,10 +228,20 @@ class App extends EventEmitter implements AppCore {
for (const [, value] of this.page.nodes) {
value.events?.forEach((event, index) => {
- const eventName = `${event.name}_${value.data.id}`;
- const eventHandler = (fromCpt: Node, ...args: any[]) => {
+ let eventName = `${event.name}_${value.data.id}`;
+ let eventHandler = (fromCpt: Node, ...args: any[]) => {
this.eventHandler(index, fromCpt, args);
};
+
+ // 页面片容器可以配置页面片内组件的事件,形式为“${nodeId}.${eventName}”
+ const eventNames = event.name.split('.');
+ if (eventNames.length > 1) {
+ eventName = `${eventNames[1]}_${eventNames[0]}`;
+ eventHandler = (fromCpt: Node, ...args: any[]) => {
+ this.eventHandler(index, value, args);
+ };
+ }
+
this.eventList.set(eventHandler, eventName);
this.on(eventName, eventHandler);
});
@@ -269,7 +279,12 @@ class App extends EventEmitter implements AppCore {
public async compActionHandler(eventConfig: CompItemConfig, fromCpt: Node | DataSource, args: any[]) {
if (!this.page) throw new Error('当前没有页面');
- const { method: methodName, to } = eventConfig;
+ let { method: methodName, to } = eventConfig;
+
+ if (isArray(methodName)) {
+ [to, methodName] = methodName;
+ }
+
const toNode = this.page.getNode(to);
if (!toNode) throw `ID为${to}的组件不存在`;
diff --git a/packages/editor/src/fields/EventSelect.vue b/packages/editor/src/fields/EventSelect.vue
index 891dea55..863fe0f3 100644
--- a/packages/editor/src/fields/EventSelect.vue
+++ b/packages/editor/src/fields/EventSelect.vue
@@ -26,14 +26,14 @@
@change="onChangeHandler"
>
-
+ >
{
- const fieldType = props.config.src === 'component' ? 'select' : 'cascader';
- const defaultEventNameConfig = {
+ const defaultEventNameConfig: ChildConfig = {
name: 'name',
text: '事件',
- type: fieldType,
+ type: (mForm, { formValue }: any) => {
+ if (
+ props.config.src !== 'component' ||
+ (formValue.type === 'page-fragment-container' && formValue.pageFragmentId)
+ ) {
+ return 'cascader';
+ }
+ return 'select';
+ },
labelWidth: '40px',
- checkStrictly: true,
+ checkStrictly: () => props.config.src !== 'component',
valueSeparator: '.',
options: (mForm: FormState, { formValue }: any) => {
let events: EventOption[] | CascaderOption[] = [];
@@ -95,11 +102,39 @@ const eventNameConfig = computed(() => {
if (props.config.src === 'component') {
events = eventsService.getEvent(formValue.type);
+
+ if (formValue.type === 'page-fragment-container' && formValue.pageFragmentId) {
+ const pageFragment = editorService?.get('root')?.items?.find((page) => page.id === formValue.pageFragmentId);
+ if (pageFragment) {
+ events = [
+ {
+ label: pageFragment.name || '迭代器容器',
+ value: pageFragment.id,
+ children: events,
+ },
+ ];
+ pageFragment.items.forEach((node) => {
+ traverseNode(node, (node) => {
+ const nodeEvents = (node.type && eventsService.getEvent(node.type)) || [];
+
+ events.push({
+ label: `${node.name}_${node.id}`,
+ value: `${node.id}`,
+ children: nodeEvents,
+ });
+ });
+ });
+
+ return events;
+ }
+ }
+
return events.map((option) => ({
text: option.label,
value: option.value,
}));
}
+
if (props.config.src === 'datasource') {
// 从数据源类型中获取到相关事件
events = dataSourceService.getFormEvent(formValue.type);
@@ -163,24 +198,63 @@ 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 = '';
+ return v;
+ },
};
return { ...defaultTargetCompConfig, ...props.config.targetCompConfig };
});
// 联动组件动作配置
const compActionConfig = computed(() => {
- const defaultCompActionConfig = {
+ const defaultCompActionConfig: ChildConfig = {
name: 'method',
text: '动作',
- type: 'select',
- display: (mForm: FormState, { model }: { model: Record }) => model.actionType === ActionType.COMP,
+ type: (mForm, { model }: any) => {
+ const to = editorService?.getNodeById(model.to);
+
+ if (to && to.type === 'page-fragment-container' && to.pageFragmentId) {
+ return 'cascader';
+ }
+
+ return 'select';
+ },
+ checkStrictly: () => props.config.src !== 'component',
+ display: (mForm, { model }: any) => model.actionType === ActionType.COMP,
options: (mForm: FormState, { model }: any) => {
const node = editorService?.getNodeById(model.to);
if (!node?.type) return [];
- return eventsService?.getMethod(node.type).map((option: any) => ({
- text: option.label,
- value: option.value,
+ let methods: EventOption[] | CascaderOption[] = [];
+
+ methods = eventsService?.getMethod(node.type) || [];
+
+ if (node.type === 'page-fragment-container' && node.pageFragmentId) {
+ const pageFragment = editorService?.get('root')?.items?.find((page) => page.id === node.pageFragmentId);
+ if (pageFragment) {
+ methods = [];
+ pageFragment.items.forEach((node: MComponent | MContainer) => {
+ traverseNode(node, (node) => {
+ const nodeMethods = (node.type && eventsService?.getMethod(node.type)) || [];
+
+ if (nodeMethods.length) {
+ methods.push({
+ label: `${node.name}_${node.id}`,
+ value: `${node.id}`,
+ children: nodeMethods,
+ });
+ }
+ });
+ });
+
+ return methods;
+ }
+ }
+
+ return methods.map((method) => ({
+ text: method.label,
+ value: method.value,
}));
},
};
diff --git a/packages/form/src/containers/Container.vue b/packages/form/src/containers/Container.vue
index 949b6463..fcd0fe89 100644
--- a/packages/form/src/containers/Container.vue
+++ b/packages/form/src/containers/Container.vue
@@ -220,13 +220,13 @@