chore: move event filter api into @nocobase/client lib

This commit is contained in:
gchust 2025-04-15 13:07:22 +08:00
parent db7c92c547
commit 505a952bce
28 changed files with 192 additions and 236 deletions

View File

@ -1,12 +1,18 @@
import React, { useState, useEffect, useMemo, useRef, useCallback } from 'react';
import { Button, Space, Card, Modal, App, Typography, Divider, Spin } from 'antd';
import { DeleteOutlined, RedoOutlined, SettingOutlined } from '@ant-design/icons';
import { EventBus } from './libs/event-bus';
import { EventFlowActionOptions, EventFlowManager } from './libs/eventflow-manager';
import { FilterFlowManager } from './libs/filterflow-manager';
import { EventContext, FilterContext, Filter } from './libs/types';
import {
EventBus,
EventFlowActionOptions,
EventFlowManager,
FilterFlowManager,
EventContext,
FilterHandlerContext,
IFilter,
useTabulatorBuiltinStyles,
useTabulatorStyles,
} from '@nocobase/client';
import { configureAction } from './actions/open-configure-dialog';
import { useTabulatorBuiltinStyles, useTabulatorStyles } from './libs/hooks';
import { useCompile } from '@nocobase/client';
import { TabulatorFull as Tabulator, ColumnDefinition } from 'tabulator-tables';
import ReactDOM from 'react-dom/client';
@ -113,7 +119,7 @@ eventFlowManager.addAction(openViewDialogAction);
eventFlowManager.addAction(configureAction); // 配置Action
// --- Filter 定义 ---
const showInitialColumnsFilter: Filter = {
const showInitialColumnsFilter: IFilter = {
name: 'showInitialColumns',
title: '显示初始列',
group: 'columns',
@ -160,7 +166,7 @@ const showInitialColumnsFilter: Filter = {
},
};
const addActionColumnFilter: Filter = {
const addActionColumnFilter: IFilter = {
name: 'addActionColumn',
title: '添加操作列',
group: 'columns',
@ -355,7 +361,7 @@ const EventFilterTableDemo: React.FC = (props) => {
// 应用 FilterFlow 获取列配置
const applyColumnFilter = useCallback(async () => {
const context: FilterContext = {
const context: FilterHandlerContext = {
props: {},
payload: {
hooks: hooks,

View File

@ -1,5 +1,5 @@
import React from 'react';
import { EventBus } from '../libs/event-bus';
import { EventBus } from '@nocobase/client';
import { openSimpleDialogAction } from '../actions/open-simple-dialog';
import { Button, Flex } from 'antd';

View File

@ -1,10 +1,9 @@
import { Button } from 'antd';
import React from 'react';
import { EventFlowManager } from '../libs/eventflow-manager';
import { EventFlowManager, EventBus } from '@nocobase/client';
import { openSimpleDialogAction } from '../actions/open-simple-dialog';
import { openNotificationAction } from '../actions/open-notification';
import { openFormDialogAction } from '../actions/open-form-dialog';
import { EventBus } from '../libs/event-bus';
// 创建事件总线实例
const eventBus = new EventBus();

View File

@ -1,5 +1,5 @@
import { Button, Space, Alert, Card, Divider } from 'antd';
import { EventBus } from '../libs/event-bus';
import { EventBus } from '@nocobase/client';
import React, { useState } from 'react';
import { openFormDialogAction } from '../actions/open-form-dialog';

View File

@ -1,5 +1,5 @@
import { Button } from 'antd';
import { EventBus } from '../libs/event-bus';
import { EventBus } from '@nocobase/client';
import React from 'react';
import { openSimpleDialogAction } from '../actions/open-simple-dialog';

View File

@ -1,9 +1,8 @@
import { Button, Radio, Space } from 'antd';
import React, { useState } from 'react';
import { EventFlowManager } from '../libs/eventflow-manager';
import { EventFlowManager, EventBus } from '@nocobase/client';
import { openSimpleDialogAction } from '../actions/open-simple-dialog';
import { openNotificationAction } from '../actions/open-notification';
import { EventBus } from '../libs/event-bus';
const eventBus = new EventBus();
const eventFlowManager = new EventFlowManager(eventBus);

View File

@ -1,9 +1,8 @@
import { Button, InputNumber, Space, Switch, Typography } from 'antd';
import React, { useState } from 'react';
import { EventFlowManager } from '../libs/eventflow-manager';
import { EventFlowManager, EventBus } from '@nocobase/client';
import { openSimpleDialogAction } from '../actions/open-simple-dialog';
import { openNotificationAction } from '../actions/open-notification';
import { EventBus } from '../libs/event-bus';
const { Text } = Typography;

View File

@ -1,7 +1,6 @@
import { Button, Space, Typography, message } from 'antd';
import React, { useState } from 'react';
import { EventFlowManager } from '../libs/eventflow-manager';
import { EventBus } from '../libs/event-bus';
import { EventFlowManager, EventBus } from '@nocobase/client';
import { configureAction } from '../actions/open-configure-dialog';
// 创建事件总线和事件流管理器

View File

@ -1,9 +1,8 @@
import { Button } from 'antd';
import React from 'react';
import { EventFlowManager } from '../libs/eventflow-manager';
import { EventFlowManager, EventBus } from '@nocobase/client';
import { openSimpleDialogAction } from '../actions/open-simple-dialog';
import { openNotificationAction } from '../actions/open-notification';
import { EventBus } from '../libs/event-bus';
// Create managers
const eventBus = new EventBus();

View File

@ -1,10 +1,9 @@
import { Button, Space, Divider } from 'antd';
import React from 'react';
import { EventFlowManager } from '../libs/eventflow-manager';
import { EventFlowManager, EventBus } from '@nocobase/client';
import { openSimpleDialogAction } from '../actions/open-simple-dialog';
import { openNotificationAction } from '../actions/open-notification';
import { openFormDialogAction } from '../actions/open-form-dialog';
import { EventBus } from '../libs/event-bus';
// 创建事件总线和事件流管理器
const eventBus = new EventBus();

View File

@ -1,5 +1,5 @@
import { Button } from 'antd';
import { EventBus } from '../libs/event-bus';
import { EventBus } from '@nocobase/client';
import React from 'react';
import openSimpleDialogAction from '../actions/open-simple-dialog';
import openNotificationAction from '../actions/open-notification';

View File

@ -1,5 +1,5 @@
import { Button } from 'antd';
import { EventBus } from '../libs/event-bus';
import { EventBus } from '@nocobase/client';
import React from 'react';
import openSimpleDialogAction from '../actions/open-simple-dialog';
import openNotificationAction from '../actions/open-notification';

View File

@ -1,11 +1,10 @@
import { Card, Space } from 'antd';
import React, { useEffect, useMemo, useState } from 'react';
import { Filter, FilterContext } from '../libs/types';
import { SchemaComponent, Checkbox, FormItem } from '@nocobase/client';
import { IFilter, FilterHandlerContext, SchemaComponent, Checkbox, FormItem } from '@nocobase/client';
import { createForm, onFormValuesChange } from '@formily/core';
import { FormContext } from '@formily/react';
const caseConvertFilter: Filter = {
const caseConvertFilter: IFilter = {
name: 'caseConvert',
title: '大小写转换',
description: '将输入文本转换为大写或小写',
@ -18,7 +17,7 @@ const caseConvertFilter: Filter = {
'x-component': 'Checkbox',
},
},
handler: async (text, params, context: FilterContext) => {
handler: async (text, params, context: FilterHandlerContext) => {
if (typeof text === 'string') {
if (params.uppercase) {
return text.toUpperCase();

View File

@ -1,6 +1,6 @@
import { Button, Card, Space, Typography } from 'antd';
import React, { useState } from 'react';
import { FilterFlowManager } from '../libs/filterflow-manager';
import { FilterFlowManager } from '@nocobase/client';
// 创建过滤器管理器实例
const filterFlowManager = new FilterFlowManager();

View File

@ -1,6 +1,6 @@
import { Button, Card, Input, Radio, Space, Typography } from 'antd';
import React, { useState } from 'react';
import { FilterFlowManager } from '../libs/filterflow-manager';
import { FilterFlowManager } from '@nocobase/client';
// 创建FilterFlowManager实例
const filterFlowManager = new FilterFlowManager();

View File

@ -1,6 +1,6 @@
import { Button, Card, Form, Input, Select, Space, Typography, Modal, Switch, InputNumber } from 'antd';
import React, { useState } from 'react';
import { FilterFlowManager } from '../libs/filterflow-manager';
import { FilterFlowManager } from '@nocobase/client';
import { configureAction } from '../actions/open-configure-dialog';
// 创建FilterFlowManager实例

View File

@ -1,6 +1,6 @@
import { Button, Card, Table, Space, Typography } from 'antd';
import React, { useState } from 'react';
import { FilterFlowManager } from '../libs/filterflow-manager';
import { FilterFlowManager } from '@nocobase/client';
// 创建FilterFlowManager实例
const filterFlowManager = new FilterFlowManager();

View File

@ -1,6 +1,6 @@
import { Button, Card, Input, Space, Typography } from 'antd';
import React, { useState } from 'react';
import { FilterFlowManager } from '../libs/filterflow-manager';
import { FilterFlowManager } from '@nocobase/client';
// 创建FilterFlowManager实例
const filterFlowManager = new FilterFlowManager();

View File

@ -1,134 +0,0 @@
/**
* 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/json-schema';
import { Resource } from '@nocobase/resourcer';
import { ComponentProps } from 'react';
export type UnregisterFunction = () => void;
// Event System Types
export interface EventContext<T = any> {
// 事件源 (dispatchEvent调用者) 信息
source?: {
id?: string;
type?: string; // 'user-interaction', 'system', 'workflow'
[key: string]: any;
};
// 用于指定接收者信息, 主要用于精准触发事件
target?: {
id?: string;
};
// 事件相关数据
payload?: T;
// 元数据
meta?: {
timestamp?: number;
userId?: string;
event?: string | string[];
[key: string]: any;
};
// 用于收集事件监听器的输出结果
results?: Record<string, any>;
}
export interface EventListenerOptions {
id?: string; // 监听器唯一标识
sort?: number; // 数值越大运行越靠后,默认为 0
once?: boolean; // 是否只执行一次,默认为 false
blocking?: boolean; // 是否为阻塞监听器默认false
condition?: (ctx: EventContext, options: EventListenerOptions) => boolean; // 运行条件
}
export type EventListener = (context: EventContext) => void | Promise<void>;
export type Unsubscriber = () => void;
export type LinkageRuleItem = {
actions: Array<{
operator: string;
targetFields: string[];
value: {
mode: string;
value: string;
};
}>;
condition: {
[type in '$and' | '$or']: Array<{
[field: string]: Record<string, string>;
}>;
};
};
export type LinkageRuleSettings = {
fields: Record<string, LinkageRuleItem>;
actions: Record<string, LinkageRuleItem>;
recordActions: Record<string, LinkageRuleItem>;
};
export type FieldSettings = Record<string, {}>;
export type ActionSettings = Record<string, {}>;
export type BlockSettings = {
linkageRules: Record<string, LinkageRuleSettings>;
fields: Record<string, FieldSettings>;
actions: Record<string, ActionSettings>;
recordActions: Record<string, ActionSettings>;
};
export type FilterContext = {
props?: ComponentProps<any>;
payload?: any;
_cancel?: boolean;
};
// FilterFlowManager Types
export type FilterHandler = (
currentValue: any,
params?: Record<string, any>,
context?: FilterContext,
) => any | Promise<any>;
/**
* Filter
*/
export interface Filter {
name: string; // 唯一标识符
title: string; // 显示名称
description?: string; // 描述
group?: string; // 所属分组
sort?: number; // 排序
uiSchema: Record<string, ISchema>; // 参数配置的 UI Schema
handler: FilterHandler; // 实际的过滤处理函数
}
export interface FilterGroupOptions {
name: string;
title: string;
sort?: number;
}
export interface FilterFlowStepOptions {
key?: string;
filterName: string;
title?: string;
params?: Record<string, any>;
condition?: string;
}
export interface FilterFlowOptions {
name: string;
title: string;
steps: FilterFlowStepOptions[];
}

View File

@ -3,66 +3,17 @@ import { observable } from '@formily/reactive';
import { uid } from '@formily/shared';
import _ from 'lodash';
import { EventBus } from './event-bus';
export type EventFlowEventHandler = (params: Record<string, any>, context: any) => Promise<any>;
export type EventFlowActionHandler = (params: Record<string, any>, context: any) => Promise<any>;
export type EventFlowEventGroupOptions = {
name: string;
title: string;
sort?: number;
};
export type EventFlowEventOptions = {
name: string;
title: string;
description?: string;
group: string;
sort?: number;
uiSchema: Record<string, ISchema>;
handler?: EventFlowEventHandler;
};
export type EventFlowActionGroupOptions = {
name: string;
title: string;
sort?: number;
};
export type EventFlowActionOptions = {
name: string;
title: string;
description?: string;
group: string;
sort?: number;
uiSchema: Record<string, ISchema>;
handler: EventFlowActionHandler;
};
export type EventFlowStepOptions = {
key?: string;
action: string;
title?: string;
params?: Record<string, any>;
condition?: string;
isAwait?: boolean;
};
export type EventFlowOnOptions = {
event?: string;
title?: string;
condition?: string;
params?: Record<string, any>;
};
export type EventFlowOptions = {
sort?: number;
isAwait?: boolean;
key?: string;
title?: string;
on?: EventFlowOnOptions;
steps?: EventFlowStepOptions[];
};
import type {
EventFlowActionHandler,
EventFlowActionGroupOptions,
EventFlowActionOptions,
EventFlowEventHandler,
EventFlowEventGroupOptions,
EventFlowEventOptions,
EventFlowOnOptions,
EventFlowOptions,
EventFlowStepOptions,
} from './types';
export class EventFlowStep {
options: EventFlowStepOptions;

View File

@ -0,0 +1,13 @@
/**
* 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.
*/
export * from './event-bus';
export * from './eventflow-manager';
export * from './hooks';
export * from './types';

View File

@ -0,0 +1,69 @@
/**
* 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/json-schema';
// Event System Types
export interface EventContext<T = any> {
source?: { id?: string; type?: string; [key: string]: any };
target?: { id?: string };
payload?: T;
meta?: { timestamp?: number; userId?: string; event?: string | string[]; [key: string]: any };
results?: Record<string, any>;
}
export interface EventListenerOptions {
id?: string;
sort?: number;
once?: boolean;
blocking?: boolean;
condition?: (ctx: EventContext, options: EventListenerOptions) => boolean;
}
export type EventListener = (context: EventContext) => void | Promise<void>;
export type Unsubscriber = () => void;
// EventFlow Types
export type EventFlowEventHandler = (params: Record<string, any>, context: any) => Promise<any>;
export type EventFlowActionHandler = (params: Record<string, any>, context: any) => Promise<any>;
export type EventFlowEventGroupOptions = { name: string; title: string; sort?: number };
export type EventFlowEventOptions = {
name: string;
title: string;
description?: string;
group: string;
sort?: number;
uiSchema: Record<string, ISchema>;
handler?: EventFlowEventHandler;
};
export type EventFlowActionGroupOptions = { name: string; title: string; sort?: number };
export type EventFlowActionOptions = {
name: string;
title: string;
description?: string;
group: string;
sort?: number;
uiSchema: Record<string, ISchema>;
handler: EventFlowActionHandler;
};
export type EventFlowStepOptions = {
key?: string;
action: string;
title?: string;
params?: Record<string, any>;
condition?: string;
isAwait?: boolean;
};
export type EventFlowOnOptions = { event?: string; title?: string; condition?: string; params?: Record<string, any> };
export type EventFlowOptions = {
sort?: number;
isAwait?: boolean;
key?: string;
title?: string;
on?: EventFlowOnOptions;
steps?: EventFlowStepOptions[];
};

View File

@ -3,12 +3,12 @@ import { observable } from '@formily/reactive';
import { uid } from '@nocobase/utils/client';
import _ from 'lodash';
import {
FilterContext,
FilterHandlerContext,
FilterFlowOptions,
FilterFlowStepOptions,
FilterHandler,
FilterGroupOptions,
Filter,
IFilter,
} from './types';
export class FilterFlowStep {
@ -166,7 +166,7 @@ export class FilterFlow {
* Filter
* FilterFlowManager
*/
getFilter(filterName: string): Filter | undefined {
getFilter(filterName: string): IFilter | undefined {
return this.filterFlowManager.getFilter(filterName);
}
@ -185,7 +185,7 @@ export class FilterFlow {
// --- FilterFlowManager Class ---
export class FilterFlowManager {
private filterGroups: Record<string, FilterGroupOptions> = {};
private filters: Record<string, Filter> = {};
private filters: Record<string, IFilter> = {};
private filterFlows: Map<string, FilterFlow>;
constructor() {
@ -206,14 +206,14 @@ export class FilterFlowManager {
/**
* Filter ( Filter )
*/
addFilter(filter: Filter) {
addFilter(filter: IFilter) {
this.filters[filter.name] = filter;
}
/**
* Filter
*/
getFilter(filterName: string): Filter | undefined {
getFilter(filterName: string): IFilter | undefined {
return this.filters[filterName];
}
@ -354,7 +354,7 @@ export class FilterFlowManager {
* @param context Filter上下文
* @returns Flow Filter
*/
async applyFilters(flowKey: string, initialValue: any, context: FilterContext): Promise<any> {
async applyFilters(flowKey: string, initialValue: any, context: FilterHandlerContext): Promise<any> {
const flow = this.getFlow(flowKey);
if (!flow) {
console.warn(`FilterFlow with key "${flowKey}" not found. Returning initial value.`);
@ -409,7 +409,7 @@ export class FilterFlowManager {
* @param context
* @returns boolean
*/
private checkCondition(condition?: string, context?: FilterContext): boolean {
private checkCondition(condition?: string, context?: FilterHandlerContext): boolean {
if (!condition) {
return true; // 没有条件,默认通过
}

View File

@ -0,0 +1,11 @@
/**
* 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.
*/
export * from './filterflow-manager';
export * from './types';

View File

@ -0,0 +1,45 @@
/**
* 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/json-schema';
import { ComponentProps } from 'react';
// Filter System Types
export type FilterHandlerContext = { props?: ComponentProps<any>; payload?: any; _cancel?: boolean };
export type FilterHandler = (
currentValue: any,
params?: Record<string, any>,
context?: FilterHandlerContext,
) => any | Promise<any>;
export interface IFilter {
name: string;
title: string;
description?: string;
group?: string;
sort?: number;
uiSchema: Record<string, ISchema>;
handler: FilterHandler;
}
export interface FilterGroupOptions {
name: string;
title: string;
sort?: number;
}
export interface FilterFlowStepOptions {
key?: string;
filterName: string;
title?: string;
params?: Record<string, any>;
condition?: string;
}
export interface FilterFlowOptions {
name: string;
title: string;
steps: FilterFlowStepOptions[];
}

View File

@ -59,6 +59,8 @@ export * from './system-settings';
export * from './testUtils';
export * from './user';
export * from './variables';
export * from './eventflow';
export * from './filterflow';
export { withDynamicSchemaProps } from './hoc/withDynamicSchemaProps';
export { withSkeletonComponent } from './hoc/withSkeletonComponent';