diff --git a/packages/core/client/src/block-provider/hooks/useFormEvents.ts b/packages/core/client/src/block-provider/hooks/useFormEvents.ts index b8cb10e80d..a311b85cf0 100644 --- a/packages/core/client/src/block-provider/hooks/useFormEvents.ts +++ b/packages/core/client/src/block-provider/hooks/useFormEvents.ts @@ -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, diff --git a/packages/core/client/src/block-provider/hooks/useSubmitEvents.ts b/packages/core/client/src/block-provider/hooks/useSubmitEvents.ts index e31f7fd741..f32c67c188 100644 --- a/packages/core/client/src/block-provider/hooks/useSubmitEvents.ts +++ b/packages/core/client/src/block-provider/hooks/useSubmitEvents.ts @@ -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 }, + }); }, }; } diff --git a/packages/core/client/src/event-flow/EventFlowPlugin.tsx b/packages/core/client/src/event-flow/EventFlowPlugin.tsx index a5ec856b2a..9175c35774 100644 --- a/packages/core/client/src/event-flow/EventFlowPlugin.tsx +++ b/packages/core/client/src/event-flow/EventFlowPlugin.tsx @@ -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); } } diff --git a/packages/core/client/src/event-flow/EventSettingItem/ActionsSetting/index.tsx b/packages/core/client/src/event-flow/EventSettingItem/ActionsSetting/index.tsx index 27bcac9de5..317c0921fd 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/ActionsSetting/index.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/ActionsSetting/index.tsx @@ -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: , - }, - 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 ( - { - const params = field.query('.params').take(1); - params.value = []; - }, - }} - /> - ); - - // return ( - // // 这里使用 SubFormProvider 包裹,是为了让子表格的联动规则中 “当前对象” 的配置显示正确 - // // - // - // - // - // - // - // - // - // - // - // // - // ); - }), - { displayName: 'ActionsSetting' }, -); diff --git a/packages/core/client/src/event-flow/EventSettingItem/components/ActionParamSelect.tsx b/packages/core/client/src/event-flow/EventSettingItem/components/ActionParamSelect.tsx index 6386be5f1b..1cce9ffcf9 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/components/ActionParamSelect.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/components/ActionParamSelect.tsx @@ -22,6 +22,5 @@ export function ActionParamSelect(props: { action: EventActionSetting }) { value: params[key]?.name || key, ...params[key], })); - console.log('ActionParamSelect', props); return ; } diff --git a/packages/core/client/src/event-flow/EventSettingItem/components/ActionParamValueInput.tsx b/packages/core/client/src/event-flow/EventSettingItem/components/ActionParamValueInput.tsx index b9359fd2e7..d338a2450c 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/components/ActionParamValueInput.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/components/ActionParamValueInput.tsx @@ -27,26 +27,22 @@ export const ActionParamValueInput = (props) => { // return ; // }, []); - console.log('ActionParamValueInput props', props); - return ( -
- { - // return uniqBy([...scope, ...variableOptions], 'key'); - // }} - style={{ minWidth: 200 }} - /> -
+ { + // return uniqBy([...scope, ...variableOptions], 'key'); + // }} + style={{ minWidth: 200 }} + /> ); }; diff --git a/packages/core/client/src/event-flow/EventSettingItem/components/ConditionSelect.tsx b/packages/core/client/src/event-flow/EventSettingItem/components/ConditionSelect.tsx index 7d668b421d..ff4254faf0 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/components/ConditionSelect.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/components/ConditionSelect.tsx @@ -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(); useUpdateEffect(() => { // 当 event 变化时,清空 condition diff --git a/packages/core/client/src/event-flow/EventSettingItem/index.tsx b/packages/core/client/src/event-flow/EventSettingItem/index.tsx index f7a23d3e21..cfc95a5ed5 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/index.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/index.tsx @@ -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 ( { ConditionSelect, ActionParamValueInput, }} - initialValues={{ events: schema[SchemaSettingsKey] }} + initialValues={{ events: fieldSchema[SchemaSettingsKey] }} scope={{ emptyParams: (field, target) => { const params = field.query('.params').take(1); diff --git a/packages/core/client/src/event-flow/hooks/useEvent.tsx b/packages/core/client/src/event-flow/hooks/useEvent.tsx index 31b29ec493..f4211a7f55 100644 --- a/packages/core/client/src/event-flow/hooks/useEvent.tsx +++ b/packages/core/client/src/event-flow/hooks/useEvent.tsx @@ -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, // 触发事件 diff --git a/packages/core/client/src/event-flow/types/index.ts b/packages/core/client/src/event-flow/types/index.ts index 734c0fd5e2..24e58dd18d 100644 --- a/packages/core/client/src/event-flow/types/index.ts +++ b/packages/core/client/src/event-flow/types/index.ts @@ -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; } diff --git a/packages/core/client/src/event-flow/utils/index.tsx b/packages/core/client/src/event-flow/utils/index.tsx new file mode 100644 index 0000000000..7f5039dd02 --- /dev/null +++ b/packages/core/client/src/event-flow/utils/index.tsx @@ -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; +}; diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/hooks/useCreateFormBlockEventsDefine.ts b/packages/core/client/src/modules/blocks/data-blocks/form/hooks/useCreateFormBlockEventsDefine.ts index 613ad5b010..4961fdfd3f 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/hooks/useCreateFormBlockEventsDefine.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/form/hooks/useCreateFormBlockEventsDefine.ts @@ -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, + }); } });