fix: add register logic

This commit is contained in:
Jian Lu 2025-02-05 15:06:29 +08:00
parent 70a1f6b05d
commit 2f7660837d
12 changed files with 138 additions and 248 deletions

View File

@ -11,7 +11,7 @@ import { useEvent } from '../../event-flow';
import { useCollection } from '../../data-source/collection/CollectionProvider';
export function useFormEvents({ form }) {
const { define, emit, removeDefinition } = useEvent();
const { define, emit } = useEvent();
const collection = useCollection();
const fields = collection?.fields || [];
const fieldsMap = fields.reduce((acc, field) => {
@ -107,12 +107,12 @@ export function useFormEvents({ form }) {
};
form.subscribe(({ type, payload, ...args }) => {
// console.log('type', type, payload, args);
// 表格重置后代表着添加成功
if (type === 'onFieldInputValueChange') {
emit({
name: inter.name,
eventName: 'valueChange',
event: {
definition: inter.name,
event: 'valueChange',
},
params: {
// fieldName: payload?.props?.name,
// fieldValue: payload?.inputValue,

View File

@ -55,10 +55,22 @@ export function useSubmitEvents() {
});
return {
emitBeforeSubmit: async (values: any) => {
await emit({ name: 'formSubmit', eventName: 'beforeSubmit', params: { values } });
await emit({
event: {
definition: 'formSubmit',
event: 'beforeSubmit',
},
params: { values },
});
},
emitAfterSubmit: async (values: any) => {
await emit({ name: 'formSubmit', eventName: 'afterSubmit', params: { values } });
await emit({
event: {
definition: 'formSubmit',
event: 'afterSubmit',
},
params: { values },
});
},
};
}

View File

@ -8,11 +8,13 @@
*/
import { Plugin } from '../application/Plugin';
import { EventSetting, PluginName } from './types';
import { EventActionSetting, EventSetting, PluginName } from './types';
import { EventSettingItem } from './EventSettingItem';
import { uniqBy } from 'lodash';
import { EventFlowProvider } from './EventFlowProvider';
import { EventDefinition } from './types';
import { ISchema } from '@formily/react';
import { getPageSchema } from './utils';
export class EventFlowPlugin extends Plugin {
static name = PluginName;
@ -41,58 +43,74 @@ export class EventFlowPlugin extends Plugin {
}
static isEqual(a: EventDefinition, b: EventDefinition) {
return a.name === b.name && a.uid === b.uid;
return a.name === b.name && a.uid === b.uid && a.pageUid === b.pageUid;
}
// 定义事件
define(definition: EventDefinition | EventDefinition[]) {
static getEventUniqueKey(event: EventSetting['event']) {
return `${event.definition}.${event.event}`;
}
/**
*
* @param definition
* @param fieldSchema schema
*/
define(definition: EventDefinition | EventDefinition[], fieldSchema?: ISchema) {
const uid = fieldSchema?.['x-uid'];
const pageSchema = getPageSchema(fieldSchema);
const pageUid = pageSchema?.['x-uid'];
if (!definition) {
return;
}
if (Array.isArray(definition)) {
this.definitions.push(...definition);
} else {
this.definitions.push(definition);
}
const definitions = Array.isArray(definition) ? definition : [definition];
definitions.forEach((item) => {
item.uid = uid;
item.pageUid = pageUid;
});
this.definitions.push(...definitions);
this.definitions = uniqBy(this.definitions, (item) => item.name + item.uid);
}
// 移除定义事件
removeDefinition(definition: EventDefinition | EventDefinition[]) {
if (!definition) {
return;
}
if (Array.isArray(definition)) {
this.definitions = this.definitions.filter((item) => !definition.some((d) => EventFlowPlugin.isEqual(item, d)));
} else {
this.definitions = this.definitions.filter((item) => !EventFlowPlugin.isEqual(item, definition));
}
}
// removeDefinition(definition: EventDefinition | EventDefinition[]) {
// if (!definition) {
// return;
// }
// const definitions = Array.isArray(definition) ? definition : [definition];
// this.definitions = this.definitions.filter((item) => !definitions.some((d) => EventFlowPlugin.isEqual(item, d)));
// }
// 运行时注册事件
register(events: EventSetting[]) {
console.log('todo register', events);
// events?.forEach((event) => {
// this.on(event);
// });
events?.forEach((event) => {
this.on(event);
});
}
// 触发事件
async emit({ name, eventName, uid, params }: { name: string; eventName: string; uid?: string; params?: any }) {
// console.log('emit', name, eventName, params);
// const event = this.events.find((event) => event.event === `${name}.${eventName}`);
// if (event) {
// event.actions.forEach((action) => {
// const actionModuleName = action.split('.')[0];
// const actionName = action.split('.')[1];
// const module = this.definitions.find((definition) => definition.name === name);
// const moduleAction = this.definitions
// .find((module) => module.name === actionModuleName)
// ?.actions?.find((action) => action.name === actionName);
// if (moduleAction) {
// moduleAction?.fn(params);
// }
// });
// }
/**
*
* @param p.event
* @param p.params
*/
async emit(p: { event: EventSetting['event']; params?: any }) {
console.log('emit', p);
const event = this.events.get(EventFlowPlugin.getEventUniqueKey(p.event));
if (event) {
const condition = event.condition;
const isCondition = false;
// todo 条件判断
if (!isCondition) {
return;
}
event.actions.forEach((act: EventActionSetting) => {
const definition = this.definitions.find((def) => def.name === act.definition);
const action = definition?.actions?.find((action) => action.name === act.action);
// todo 获取action的参数
const actionParams = act.params;
if (action) {
action.fn(actionParams);
}
});
}
}
on(event: EventSetting) {
this.events.set(event.event, event);
this.events.set(EventFlowPlugin.getEventUniqueKey(event.event), event);
}
}

View File

@ -64,155 +64,3 @@ export interface Props {
dynamicComponent: any;
definitions: EventDefinition[];
}
export const ActionsSetting = withDynamicSchemaProps(
observer((props: Props) => {
const fieldSchema = useFieldSchema();
const array = ArrayBase.useArray();
const recordValues = ArrayBase.useRecord();
const index = ArrayBase.useIndex();
const { options, defaultValues, collectionName, variables, localVariables, record, dynamicComponent } = props;
const { getAllCollectionsInheritChain } = useCollectionManager_deprecated();
const parentRecordData = useCollectionParentRecordData();
const { form } = useFormBlockContext();
const variableOptions = useVariableOptions();
console.log('variableOptions', variableOptions);
const components = useMemo(
() => ({
ArrayCollapse,
Filter,
Space,
ActionParamSelect,
ActionSelect,
ConditionSelect,
}),
[],
);
const schema = useMemo(
() => ({
type: 'object',
properties: {
rules: {
type: 'array',
// default: defaultValues,
'x-component': 'ArrayCollapse',
'x-decorator': 'FormItem',
'x-component-props': {
accordion: true,
titleRender: (item: any, index: number) => {
return `动作 ${index + 1}`;
},
showEmpty: false,
},
items: {
type: 'object',
'x-component': 'ArrayCollapse.CollapsePanel',
'x-component-props': {
// extra: <EnableLinkage />,
},
properties: {
layout: {
type: 'void',
'x-component': 'FormLayout',
'x-component-props': {
labelStyle: {
marginTop: '6px',
},
labelCol: 8,
wrapperCol: 16,
},
properties: {
conditionsTitle: {
'x-component': 'h4',
'x-content': '{{ t("Condition") }}',
},
condition: {
'x-component': 'ConditionSelect',
'x-reactions': {
dependencies: ['...event'],
fulfill: {
state: {
'componentProps.options3': '{{$deps[0]}}',
},
},
},
},
actionsTitle: {
'x-component': 'h4',
'x-content': '{{ t("动作") }}',
},
actionsBlock: actionsSchema,
},
},
remove: {
type: 'void',
'x-component': 'ArrayCollapse.Remove',
},
},
},
properties: {
add: {
type: 'void',
title: '{{ t("添加规则") }}',
'x-component': 'ArrayCollapse.Addition',
'x-reactions': {
dependencies: ['rules'],
fulfill: {
state: {
// disabled: '{{$deps[0].length >= 3}}',
},
},
},
},
},
},
},
}),
[
collectionName,
defaultValues,
form,
getAllCollectionsInheritChain,
localVariables,
options,
props,
record,
variables,
],
);
const value = useMemo(
() => ({ field: options, fieldSchema, dynamicComponent, options: options || [] }),
[dynamicComponent, fieldSchema, options],
);
return (
<SchemaComponent
components={components}
schema={schema}
scope={{
emptyParams: (field, target) => {
const params = field.query('.params').take(1);
params.value = [];
},
}}
/>
);
// return (
// // 这里使用 SubFormProvider 包裹,是为了让子表格的联动规则中 “当前对象” 的配置显示正确
// // <FormProvider form={form}>
// <SubFormProvider value={{ value: null, collection: { name: collectionName } as any }}>
// <RecordProvider record={record} parent={parentRecordData}>
// <FilterContext.Provider value={value}>
// <CollectionProvider name={collectionName}>
// <SchemaComponent components={components} schema={schema} />
// </CollectionProvider>
// </FilterContext.Provider>
// </RecordProvider>
// </SubFormProvider>
// // </FormProvider>
// );
}),
{ displayName: 'ActionsSetting' },
);

View File

@ -22,6 +22,5 @@ export function ActionParamSelect(props: { action: EventActionSetting }) {
value: params[key]?.name || key,
...params[key],
}));
console.log('ActionParamSelect', props);
return <Select options={options} {...rest} style={{ minWidth: 150 }}></Select>;
}

View File

@ -27,26 +27,22 @@ export const ActionParamValueInput = (props) => {
// return <CollectionField value={value} onChange={onChange} />;
// }, []);
console.log('ActionParamValueInput props', props);
return (
<div>
<VariableInput
{...props}
// form={form}
// record={record}
shouldChange={getShouldChange({
// collectionField,
// variables,
// localVariables,
// getAllCollectionsInheritChain,
})}
renderSchemaComponent={renderSchemaComponent}
// returnScope={(scope) => {
// return uniqBy([...scope, ...variableOptions], 'key');
// }}
style={{ minWidth: 200 }}
/>
</div>
<VariableInput
{...props}
// form={form}
// record={record}
shouldChange={getShouldChange({
// collectionField,
// variables,
// localVariables,
// getAllCollectionsInheritChain,
})}
renderSchemaComponent={renderSchemaComponent}
// returnScope={(scope) => {
// return uniqBy([...scope, ...variableOptions], 'key');
// }}
style={{ minWidth: 200 }}
/>
);
};

View File

@ -25,7 +25,6 @@ import { useUpdateEffect } from 'ahooks';
export default function ConditionSelect(props: { event?: EventSetting['event']; onChange?: any }) {
const filterOptions = useFilterOptions(props.event);
const variableOptions = useVariableOptions();
console.log('filterOptions', filterOptions, props);
const field = useField<ObjectField>();
useUpdateEffect(() => {
// 当 event 变化时,清空 condition

View File

@ -27,7 +27,6 @@ import { ISchema, useField } from '@formily/react';
import { SchemaSettingsKey, useEvent } from '..';
import { useFieldSchema } from '@formily/react';
import { useLinkageCollectionFieldOptions } from './ActionsSetting/action-hooks';
import { ActionsSetting } from './ActionsSetting';
import EventSelect from './EventSelect';
import { ArrayCollapse } from './components/LinkageHeader';
import { css } from '@emotion/css';
@ -43,20 +42,11 @@ import { ActionParamValueInput } from './components/ActionParamValueInput';
export const EventSettingItem = (props) => {
// const field = useField();
const filed = useField();
const schema = useFieldSchema();
const { patch } = useDesignable();
const app = useApp();
const { definitions, register } = useEvent();
const { dn } = useDesignable();
const fieldSchema = useFieldSchema();
const { readPretty, Component, afterSubmit } = props;
const collectionName = 't_aierml1wni1';
const options = useLinkageCollectionFilterOptions(collectionName);
const linkageOptions = useLinkageCollectionFieldOptions(collectionName, readPretty);
const ff = useFormBlockContext();
const variables = useVariables();
const localVariables = useLocalVariables();
const { type: formBlockType } = useFormBlockType();
return (
<SchemaSettingsModalItem
@ -73,7 +63,7 @@ export const EventSettingItem = (props) => {
ConditionSelect,
ActionParamValueInput,
}}
initialValues={{ events: schema[SchemaSettingsKey] }}
initialValues={{ events: fieldSchema[SchemaSettingsKey] }}
scope={{
emptyParams: (field, target) => {
const params = field.query('.params').take(1);

View File

@ -9,7 +9,7 @@
import { EventDefinition, EventSetting } from '../types';
import { useFieldSchema } from '@formily/react';
import { useApp, usePlugin, useSchemaSettings } from '@nocobase/client';
import { getPageSchema, useApp, usePlugin, useSchemaSettings } from '@nocobase/client';
import React from 'react';
import { ISchema, useField } from '@formily/react';
import { EventFlowPlugin } from '..';
@ -18,33 +18,33 @@ import { useMemoizedFn } from 'ahooks';
export const useEvent = () => {
const fieldSchema = useFieldSchema();
const uid = fieldSchema?.['x-uid'];
const pageUid = getPageSchema(fieldSchema)?.['x-uid'];
const eventFlowPlugin: EventFlowPlugin = usePlugin(EventFlowPlugin.name) as any;
const define = useMemoizedFn((definition: EventDefinition[] | EventDefinition) => {
if (Array.isArray(definition)) {
definition.forEach((item) => {
item.uid = uid;
});
} else if (definition) {
definition.uid = uid;
}
eventFlowPlugin?.define(definition);
eventFlowPlugin?.define(definition, fieldSchema);
});
const register = useMemoizedFn((events: EventSetting[]) => {
eventFlowPlugin?.register(events);
});
const emit = useMemoizedFn(async ({ name, eventName, params }: { name: string; eventName: string; params?: any }) => {
await eventFlowPlugin?.emit({ name, eventName, uid, params });
const emit = useMemoizedFn(async (p: { event: EventSetting['event']; params?: any }) => {
await eventFlowPlugin?.emit({
event: {
...p.event,
uid: uid,
},
params: p.params,
});
});
return {
definitions: eventFlowPlugin?.definitions,
definitions: eventFlowPlugin?.definitions.filter((item) => item.pageUid === pageUid || !item.pageUid || !pageUid),
// 定义事件
define,
// 移除事件
removeDefinition: eventFlowPlugin?.removeDefinition,
// removeDefinition: eventFlowPlugin?.removeDefinition,
// 运行时事件注册
register,
// 触发事件

View File

@ -52,6 +52,8 @@ export interface EventDefinition {
name: string;
/** 标识同一类型组件的不同实例 */
uid?: string;
/** 标识所属页面 */
pageUid?: string;
title: string;
description?: string;
events?: EventEvent[];
@ -69,7 +71,7 @@ export interface EventSetting {
uid?: string;
};
/** 标识同一类型组件的不同实例 */
uid?: string;
// uid?: string;
condition: string;
actions: Array<EventActionSetting>;
}

View File

@ -0,0 +1,20 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { ISchema } from '@formily/react';
export const getPageSchema = (schema: any) => {
if (schema?.['x-component'] === 'Page') {
return schema;
}
if (schema?.parent) {
return getPageSchema(schema?.parent);
}
return undefined;
};

View File

@ -52,7 +52,13 @@ export function useCreateFormBlockEventsDefine() {
console.log('type', type, payload, args);
// 表格重置后代表着添加成功
if (type === 'onFormReset') {
emit(inter.name, 'onSubmit', payload);
emit({
event: {
definition: inter.name,
event: 'onSubmit',
},
params: payload,
});
}
});