diff --git a/packages/core/client/src/application/Application.tsx b/packages/core/client/src/application/Application.tsx index f66810ace7..2839218fac 100644 --- a/packages/core/client/src/application/Application.tsx +++ b/packages/core/client/src/application/Application.tsx @@ -45,6 +45,7 @@ import { OpenModeProvider } from '../modules/popup/OpenModeProvider'; import { AppSchemaComponentProvider } from './AppSchemaComponentProvider'; import type { Plugin } from './Plugin'; import type { RequireJS } from './utils/requirejs'; +import { withSchemaEvent } from '../event-flow'; declare global { interface Window { @@ -426,7 +427,12 @@ export class Application { console.error('Component must have a displayName or pass name as second argument'); return; } - set(this.components, componentName, component); + // event: add pasre of event schema + if (['Page'].includes(componentName)) { + set(this.components, componentName, withSchemaEvent(component)); + } else { + set(this.components, componentName, component); + } } addComponents(components: Record) { diff --git a/packages/core/client/src/event-flow/EventFlowPlugin.tsx b/packages/core/client/src/event-flow/EventFlowPlugin.tsx new file mode 100644 index 0000000000..1e27b6d507 --- /dev/null +++ b/packages/core/client/src/event-flow/EventFlowPlugin.tsx @@ -0,0 +1,71 @@ +/** + * 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 { Plugin } from '../application/Plugin'; +import { EventSetting, PluginName } from './types'; +import { EventSettingItem } from './EventSettingItem'; +import { uniqBy } from 'lodash'; +import { EventFlowProvider } from './EventFlowProvider'; +import { EventDefinition } from './types'; + +export class EventFlowPlugin extends Plugin { + static name = PluginName; + modules: EventDefinition[] = []; + events: Map = new Map(); + async afterAdd() { + // await this.app.pm.add() + } + + async beforeLoad() {} + + // You can get and modify the app instance here + async load() { + this.schemaSettingsManager.addItem('PageSettings', PluginName, { + Component: EventSettingItem, + }); + this.app.use(EventFlowProvider); + // this.app.addComponents({}) + // this.app.addScopes({}) + // this.app.addProvider() + // this.app.addProviders() + // this.app.router.add() + } + register(values: EventDefinition) { + console.log('register', values); + this.modules.push(values); + this.modules = uniqBy(this.modules, 'name'); + } + // 触发事件 + emit(moduleName: string, eventName: string, params: any) { + console.log('emit', moduleName, eventName, params); + const event = this.events.find((event) => event.event === `${moduleName}.${eventName}`); + if (event) { + event.actions.forEach((action) => { + const actionModuleName = action.split('.')[0]; + const actionName = action.split('.')[1]; + const module = this.modules.find((module) => module.name === moduleName); + const moduleAction = this.modules + .find((module) => module.name === actionModuleName) + ?.actions?.find((action) => action.name === actionName); + console.log('moduleAction', moduleAction); + if (moduleAction) { + moduleAction?.fn(params); + } + }); + } + } + on(event: EventSetting) { + this.events.set(event.event, event); + } + registerEvents(events: EventSetting[]) { + events.forEach((event) => { + this.on(event); + }); + } +} diff --git a/packages/core/client/src/event-flow/EventSettingItem/ActionsInput.tsx b/packages/core/client/src/event-flow/EventSettingItem/ActionsInput.tsx index 51cbdc513c..45ed6b5ff0 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/ActionsInput.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/ActionsInput.tsx @@ -11,9 +11,9 @@ import React from 'react'; import { useControllableValue } from 'ahooks'; import { Card, Space, Button, Tag, Tooltip, Select, TreeSelect } from 'antd'; import { CloseOutlined, PlusOutlined, SettingFilled } from '@ant-design/icons'; -import { IEventFlowModule } from '../index'; +import { EventDefinition } from '../types'; -export default function ActionsInput(props: { modules: IEventFlowModule[]; value: any; onChange: (v: any) => void }) { +export default function ActionsInput(props: { modules: EventDefinition[]; value: any; onChange: (v: any) => void }) { const { modules } = props; const [state, setState] = useControllableValue>(props, { defaultValue: [], diff --git a/packages/core/client/src/event-flow/EventSettingItem/EventSelect.tsx b/packages/core/client/src/event-flow/EventSettingItem/EventSelect.tsx index 7394a66df3..4843d74265 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/EventSelect.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/EventSelect.tsx @@ -10,9 +10,9 @@ import React from 'react'; import { useControllableValue } from 'ahooks'; import { Card, Space, TreeSelect } from 'antd'; -import { IEventFlowModule } from '../index'; +import { EventDefinition } from '../types'; -export default function EventSelect(props: { modules: IEventFlowModule[]; value: any; onChange: (v: any) => void }) { +export default function EventSelect(props: { modules: EventDefinition[]; value: any; onChange: (v: any) => void }) { const { modules, onChange } = props; const [state, setState] = useControllableValue>(props, { defaultValue: undefined, diff --git a/packages/core/client/src/event-flow/EventSettingItem/EventsSetting.tsx b/packages/core/client/src/event-flow/EventSettingItem/EventsSetting.tsx index b32efe4bbc..c2d0fdf3bb 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/EventsSetting.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/EventsSetting.tsx @@ -14,7 +14,7 @@ import EventSelect from './EventSelect'; import ConditionInput from './ConditionInput'; import ActionsInput from './ActionsInput'; import { CloseOutlined, PlusOutlined } from '@ant-design/icons'; -import { IEventFlowEvent } from '../types'; +import { EventSetting } from '../types'; const EventCard = (props) => { const { modules, onDelete } = props; @@ -46,7 +46,7 @@ const EventCard = (props) => { export default function EventsSetting(props) { const { modules, value } = props; - const [state, setState] = useControllableValue>(props, { + const [state, setState] = useControllableValue>(props, { defaultValue: [], }); console.log('modules', state, value); diff --git a/packages/core/client/src/event-flow/EventSettingItem/index.tsx b/packages/core/client/src/event-flow/EventSettingItem/index.tsx index dd768e5016..b84532f6b8 100644 --- a/packages/core/client/src/event-flow/EventSettingItem/index.tsx +++ b/packages/core/client/src/event-flow/EventSettingItem/index.tsx @@ -18,7 +18,7 @@ import { import React from 'react'; import { ISchema, useField } from '@formily/react'; import EventsSetting from './EventsSetting'; -import { EventFlowPlugin } from '..'; +import { EventFlowPlugin, SchemaSettingsKey } from '..'; import { useFieldSchema } from '@formily/react'; export const EventSettingItem = () => { @@ -28,7 +28,7 @@ export const EventSettingItem = () => { const { patch } = useDesignable(); const app = useApp(); const eventFlowPlugin = usePlugin(EventFlowPlugin.name) as any; - console.log('eventFlowPlugin', schema); + console.log('eventFlowPlugin', eventFlowPlugin); const { dn } = useDesignable(); const fieldSchema = useFieldSchema(); console.log('fieldSchema', fieldSchema); @@ -45,7 +45,7 @@ export const EventSettingItem = () => { properties: { events: { type: 'array', - default: fieldSchema?.['x-event-flow-setting'] || [], + default: fieldSchema?.[SchemaSettingsKey] || [], 'x-decorator': 'FormItem', 'x-component': 'EventsSetting', 'x-component-props': { @@ -57,11 +57,11 @@ export const EventSettingItem = () => { } onSubmit={({ events }) => { console.log('onSubmit', events); - fieldSchema['x-event-flow-setting'] = events; + fieldSchema[SchemaSettingsKey] = events; dn.emit('patch', { schema: { 'x-uid': fieldSchema['x-uid'], - 'x-event-flow-setting': events, + [SchemaSettingsKey]: events, }, }); eventFlowPlugin.registerEvents(events); diff --git a/packages/core/client/src/event-flow/hoc/withSchemaEvent.tsx b/packages/core/client/src/event-flow/hoc/withSchemaEvent.tsx new file mode 100644 index 0000000000..e58df970bc --- /dev/null +++ b/packages/core/client/src/event-flow/hoc/withSchemaEvent.tsx @@ -0,0 +1,35 @@ +/** + * 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 React, { ComponentType } from 'react'; +import { observer, useFieldSchema } from '@formily/react'; +import { useEventDefinitions, useEventSettings } from '../hooks'; +import { SchemaSettingsKey, SchemaDefinitionsKey } from '../types'; + +const WarpComponent = (props: any) => { + const fieldSchema = useFieldSchema(); + useEventDefinitions(fieldSchema?.[SchemaDefinitionsKey]); + useEventSettings(fieldSchema?.[SchemaSettingsKey]); + return props.children; +}; + +export const withSchemaEvent = (Component: ComponentType) => { + const displayName = Component.displayName || Component.name; + + const ComponentParse = (props: any) => { + return ( + + {props.children} + + ); + }; + Component.displayName = displayName; + ComponentParse.displayName = `withSchemaEvent(${displayName})`; + return ComponentParse; +}; diff --git a/packages/core/client/src/event-flow/hooks/index.ts b/packages/core/client/src/event-flow/hooks/index.ts index 4b8d7a802c..0e5745c660 100644 --- a/packages/core/client/src/event-flow/hooks/index.ts +++ b/packages/core/client/src/event-flow/hooks/index.ts @@ -7,4 +7,5 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -export * from './useEventFlow'; +export * from './useEventDefinitions'; +export * from './useEventSettings'; diff --git a/packages/core/client/src/event-flow/hooks/useEvent.tsx b/packages/core/client/src/event-flow/hooks/useEvent.tsx new file mode 100644 index 0000000000..2a0a2c6a4a --- /dev/null +++ b/packages/core/client/src/event-flow/hooks/useEvent.tsx @@ -0,0 +1,33 @@ +/** + * 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 { EventDefinition, EventSetting } from '../types'; +import { useFieldSchema } from '@formily/react'; +import { useApp, usePlugin, useSchemaSettings } from '@nocobase/client'; +import React from 'react'; +import { ISchema, useField } from '@formily/react'; +import { EventFlowPlugin } from '..'; + +export const useEvent = () => { + const eventFlowPlugin = usePlugin(EventFlowPlugin.name) as any; + return { + // 定义事件 + define: (events: EventDefinition[]) => { + eventFlowPlugin.registerEvents(events); + }, + // 注册事件 + register: (events: EventSetting[]) => { + eventFlowPlugin.registerEvents(events); + }, + // 触发事件 + emit: (event: EventDefinition) => { + eventFlowPlugin.emit(event); + }, + }; +}; diff --git a/packages/core/client/src/event-flow/hooks/useEventDefinitions.tsx b/packages/core/client/src/event-flow/hooks/useEventDefinitions.tsx new file mode 100644 index 0000000000..5c8988cc8d --- /dev/null +++ b/packages/core/client/src/event-flow/hooks/useEventDefinitions.tsx @@ -0,0 +1,14 @@ +/** + * 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 { EventDefinition } from '../types'; + +export const useEventDefinitions = (definitions?: EventDefinition[]) => { + // console.log(definitions); +}; diff --git a/packages/core/client/src/event-flow/hooks/useEventFlow.tsx b/packages/core/client/src/event-flow/hooks/useEventSettings.tsx similarity index 61% rename from packages/core/client/src/event-flow/hooks/useEventFlow.tsx rename to packages/core/client/src/event-flow/hooks/useEventSettings.tsx index ee5de4b6e2..5d45e07934 100644 --- a/packages/core/client/src/event-flow/hooks/useEventFlow.tsx +++ b/packages/core/client/src/event-flow/hooks/useEventSettings.tsx @@ -7,16 +7,15 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ +import { EventSetting } from '../types'; import { useFieldSchema } from '@formily/react'; import { useApp, usePlugin, useSchemaSettings } from '@nocobase/client'; import React from 'react'; import { ISchema, useField } from '@formily/react'; -import EventsSetting from '../components/EventsSetting'; import { EventFlowPlugin } from '..'; +import { useEvent } from './useEvent'; -export const useEventFlow = () => { - const fieldSchema = useFieldSchema(); - const eventFlowPlugin = usePlugin(EventFlowPlugin.name) as any; - console.log('eventFlowPlugin', eventFlowPlugin, fieldSchema); - eventFlowPlugin.registerEvents(fieldSchema?.['x-event-flow-setting'] || []); +export const useEventSettings = (settings?: EventSetting[]) => { + const { register } = useEvent(); + register(settings || []); }; diff --git a/packages/core/client/src/event-flow/index.tsx b/packages/core/client/src/event-flow/index.tsx index 2e481e6313..6c54a4880b 100644 --- a/packages/core/client/src/event-flow/index.tsx +++ b/packages/core/client/src/event-flow/index.tsx @@ -7,90 +7,6 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { Plugin } from '../application/Plugin'; -import { IEventFlowEvent, PluginName } from './types'; -import { EventSettingItem } from './EventSettingItem'; -import { uniqBy } from 'lodash'; -import { EventFlowProvider } from './EventFlowProvider'; - -interface IEventParam { - name: string; - title: string; - description: string; - type: string; -} - -export interface IEventFlowModule { - name: string; - title: string; - description: string; - actions?: Array<{ - name: string; - title: string; - description?: string; - params: IEventParam[]; - fn: (params: any) => void; - }>; - events?: Array<{ - name: string; - title: string; - description: string; - params: IEventParam[]; - }>; - states?: IEventParam[]; -} - -export class EventFlowPlugin extends Plugin { - static name = PluginName; - modules: IEventFlowModule[] = []; - events: Map = new Map(); - async afterAdd() { - // await this.app.pm.add() - } - - async beforeLoad() {} - - // You can get and modify the app instance here - async load() { - this.schemaSettingsManager.addItem('PageSettings', PluginName, { - Component: EventSettingItem, - }); - this.app.use(EventFlowProvider); - // this.app.addComponents({}) - // this.app.addScopes({}) - // this.app.addProvider() - // this.app.addProviders() - // this.app.router.add() - } - register(values: IEventFlowModule) { - this.modules.push(values); - this.modules = uniqBy(this.modules, 'name'); - } - // 触发事件 - emit(moduleName: string, eventName: string, params: any) { - console.log('emit', moduleName, eventName, params); - const event = this.events.find((event) => event.event === `${moduleName}.${eventName}`); - if (event) { - event.actions.forEach((action) => { - const actionModuleName = action.split('.')[0]; - const actionName = action.split('.')[1]; - const module = this.modules.find((module) => module.name === moduleName); - const moduleAction = this.modules - .find((module) => module.name === actionModuleName) - ?.actions?.find((action) => action.name === actionName); - console.log('moduleAction', moduleAction); - if (moduleAction) { - moduleAction?.fn(params); - } - }); - } - } - on(event: IEventFlowEvent) { - this.events.set(event.event, event); - } - registerEvents(events: IEventFlowEvent[]) { - events.forEach((event) => { - this.on(event); - }); - } -} +export * from './types'; +export * from './hoc/withSchemaEvent'; +export * from './EventFlowPlugin'; diff --git a/packages/core/client/src/event-flow/types/index.ts b/packages/core/client/src/event-flow/types/index.ts index 3d37143e80..03fcc66559 100644 --- a/packages/core/client/src/event-flow/types/index.ts +++ b/packages/core/client/src/event-flow/types/index.ts @@ -7,9 +7,46 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -export const PluginName = 'event-flow'; +export const PluginName = 'event'; +export const SchemaSettingsKey = 'x-event-settings'; +export const SchemaDefinitionsKey = 'x-event-definitions'; -export interface IEventFlowEvent { +interface IEventParam { + name: string; + title: string; + description: string; + type: string; +} + +/** 事件动作 */ +export interface EventAction { + name: string; + title: string; + description?: string; + params: IEventParam[]; + fn: (params: any) => void; +} + +/** 事件事件 */ +export interface EventEvent { + name: string; + title: string; + description: string; + params: IEventParam[]; +} + +/** 事件定义 */ +export interface EventDefinition { + name: string; + title: string; + description: string; + actions?: EventAction[]; + events?: EventEvent[]; + states?: IEventParam[]; +} + +/** 事件设置 */ +export interface EventSetting { event: string; condition: string; actions: string[]; diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/hooks/useCreateFormBlockProps.ts b/packages/core/client/src/modules/blocks/data-blocks/form/hooks/useCreateFormBlockProps.ts index 0e259321fc..52cc4fa548 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/hooks/useCreateFormBlockProps.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/form/hooks/useCreateFormBlockProps.ts @@ -12,5 +12,6 @@ import { useCreateFormBlockEventsInterface } from './useCreateFormBlockEventsInt export function useCreateFormBlockProps() { useCreateFormBlockEventsInterface(); + console.log('11111'); return useFormBlockProps(); } diff --git a/packages/core/client/src/schema-component/antd/page/Page.tsx b/packages/core/client/src/schema-component/antd/page/Page.tsx index 28e1a3e098..0724a917c0 100644 --- a/packages/core/client/src/schema-component/antd/page/Page.tsx +++ b/packages/core/client/src/schema-component/antd/page/Page.tsx @@ -42,7 +42,6 @@ import { ErrorFallback } from '../error-fallback'; import { useStyles } from './Page.style'; import { PageDesigner, PageTabDesigner } from './PageTabDesigner'; import { PopupRouteContextResetter } from './PopupRouteContextResetter'; -import { useEventFlow } from '../../../event-flow/hooks'; interface PageProps { currentTabUid: string; @@ -50,7 +49,6 @@ interface PageProps { } const InternalPage = React.memo((props: PageProps) => { - useEventFlow(); const fieldSchema = useFieldSchema(); const currentTabUid = props.currentTabUid; const disablePageHeader = fieldSchema['x-component-props']?.disablePageHeader;