mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 13:39:24 +08:00
feat: clean code
This commit is contained in:
parent
2f7660837d
commit
8ae3957578
@ -92,15 +92,33 @@ export function useFormEvents({ form }) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
fn: (params) => {
|
fn: (params) => {
|
||||||
form.setFieldState(params.fieldName, params.fieldState);
|
console.log('设置字段状态', params);
|
||||||
|
// form.setFieldState(params.fieldName, params.fieldState);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'setValues',
|
name: 'setValues',
|
||||||
title: '设置表单值',
|
title: '设置表单值',
|
||||||
description: '设置表单值',
|
description: '设置表单值',
|
||||||
|
params: {
|
||||||
|
name: {
|
||||||
|
name: 'name',
|
||||||
|
title: '字段名',
|
||||||
|
type: 'string',
|
||||||
|
description: '字段名',
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
name: 'value',
|
||||||
|
title: '字段值',
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
fn: (params) => {
|
fn: (params) => {
|
||||||
form.setValues(params.values);
|
console.log('设置表单值', params);
|
||||||
|
form.setValues({
|
||||||
|
...form.values,
|
||||||
|
[params.name]: params.value,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -114,8 +132,8 @@ export function useFormEvents({ form }) {
|
|||||||
event: 'valueChange',
|
event: 'valueChange',
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
// fieldName: payload?.props?.name,
|
fieldName: payload?.props?.name,
|
||||||
// fieldValue: payload?.inputValue,
|
fieldValue: payload?.inputValue,
|
||||||
values: form.values, // 用全量值代替某个值的改变,不太好传递动态的值类型
|
values: form.values, // 用全量值代替某个值的改变,不太好传递动态的值类型
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -8,13 +8,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Plugin } from '../application/Plugin';
|
import { Plugin } from '../application/Plugin';
|
||||||
import { EventActionSetting, EventSetting, PluginName } from './types';
|
import { EventActionSetting, EventParamKey, EventSetting, SystemParamKey, StateParamKey, PluginName } from './types';
|
||||||
import { EventSettingItem } from './EventSettingItem';
|
import { EventSettingItem } from './EventSettingItem';
|
||||||
import { uniqBy } from 'lodash';
|
import { uniqBy } from 'lodash';
|
||||||
import { EventFlowProvider } from './EventFlowProvider';
|
import { EventFlowProvider } from './EventFlowProvider';
|
||||||
import { EventDefinition } from './types';
|
import { EventDefinition } from './types';
|
||||||
import { ISchema } from '@formily/react';
|
import { ISchema } from '@formily/react';
|
||||||
import { getPageSchema } from './utils';
|
import { getConditionResult, getFieldValuesInCondition, getPageSchema } from './utils';
|
||||||
|
import { conditionAnalyses } from '../schema-component/common/utils/uitls';
|
||||||
|
import { VariableOption } from '../variables/types';
|
||||||
|
import { VariablesContextType } from '../variables/types';
|
||||||
|
import { parse, str2moment } from '@nocobase/utils/client';
|
||||||
|
|
||||||
export class EventFlowPlugin extends Plugin {
|
export class EventFlowPlugin extends Plugin {
|
||||||
static name = PluginName;
|
static name = PluginName;
|
||||||
@ -43,11 +47,16 @@ export class EventFlowPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isEqual(a: EventDefinition, b: EventDefinition) {
|
static isEqual(a: EventDefinition, b: EventDefinition) {
|
||||||
return a.name === b.name && a.uid === b.uid && a.pageUid === b.pageUid;
|
return a.name === b.name && a.pageUid === b.pageUid && a.blockUid === b.blockUid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getEventUniqueKey(event: EventSetting['event']) {
|
static getEventUniqueKey(event: EventSetting['event']) {
|
||||||
return `${event.definition}.${event.event}`;
|
return `${event.pageUid}.${event.blockUid}.${event.definition}.${event.event}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static parseEventUniqueKey(key: string) {
|
||||||
|
const [pageUid, blockUid, definition, event] = key?.split('.') || [];
|
||||||
|
return { pageUid, blockUid, definition, event };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,20 +64,16 @@ export class EventFlowPlugin extends Plugin {
|
|||||||
* @param definition 事件定义
|
* @param definition 事件定义
|
||||||
* @param fieldSchema 字段对应schema
|
* @param fieldSchema 字段对应schema
|
||||||
*/
|
*/
|
||||||
define(definition: EventDefinition | EventDefinition[], fieldSchema?: ISchema) {
|
define(definitions: EventDefinition[]) {
|
||||||
const uid = fieldSchema?.['x-uid'];
|
|
||||||
const pageSchema = getPageSchema(fieldSchema);
|
|
||||||
const pageUid = pageSchema?.['x-uid'];
|
|
||||||
if (!definition) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const definitions = Array.isArray(definition) ? definition : [definition];
|
|
||||||
definitions.forEach((item) => {
|
definitions.forEach((item) => {
|
||||||
item.uid = uid;
|
const exist = this.definitions.find((def) => EventFlowPlugin.isEqual(def, item));
|
||||||
item.pageUid = pageUid;
|
if (exist) {
|
||||||
|
Object.assign(exist, item);
|
||||||
|
} else {
|
||||||
|
this.definitions.push(item);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.definitions.push(...definitions);
|
console.log('definitions', this.definitions);
|
||||||
this.definitions = uniqBy(this.definitions, (item) => item.name + item.uid);
|
|
||||||
}
|
}
|
||||||
// 移除定义事件
|
// 移除定义事件
|
||||||
// removeDefinition(definition: EventDefinition | EventDefinition[]) {
|
// removeDefinition(definition: EventDefinition | EventDefinition[]) {
|
||||||
@ -89,28 +94,62 @@ export class EventFlowPlugin extends Plugin {
|
|||||||
* @param p.event 事件
|
* @param p.event 事件
|
||||||
* @param p.params 事件上报的参数
|
* @param p.params 事件上报的参数
|
||||||
*/
|
*/
|
||||||
async emit(p: { event: EventSetting['event']; params?: any }) {
|
async emit(p: {
|
||||||
console.log('emit', p);
|
event: EventSetting['event'];
|
||||||
const event = this.events.get(EventFlowPlugin.getEventUniqueKey(p.event));
|
params?: any;
|
||||||
if (event) {
|
variables: VariablesContextType;
|
||||||
const condition = event.condition;
|
localVariables: VariableOption[];
|
||||||
const isCondition = false;
|
}) {
|
||||||
// todo 条件判断
|
const rules = this.events.get(EventFlowPlugin.getEventUniqueKey(p.event))?.rules;
|
||||||
if (!isCondition) {
|
const getParsedValue = (expression: string) => {
|
||||||
return;
|
const template = parse(expression);
|
||||||
}
|
return template(p.variables);
|
||||||
event.actions.forEach((act: EventActionSetting) => {
|
};
|
||||||
const definition = this.definitions.find((def) => def.name === act.definition);
|
if (rules) {
|
||||||
const action = definition?.actions?.find((action) => action.name === act.action);
|
for (const rule of rules) {
|
||||||
|
const condition = rule.condition;
|
||||||
|
const conditionValues = {
|
||||||
|
[EventParamKey]: p.params,
|
||||||
|
[StateParamKey]: {},
|
||||||
|
[SystemParamKey]: {},
|
||||||
|
};
|
||||||
|
console.log('conditionValues', condition, p, conditionValues);
|
||||||
|
// const isConditionPass = getConditionResult({ condition, values: conditionValues });
|
||||||
|
const isConditionPass = await conditionAnalyses({
|
||||||
|
ruleGroup: condition,
|
||||||
|
variables: p.variables,
|
||||||
|
localVariables: [
|
||||||
|
...p.localVariables,
|
||||||
|
{
|
||||||
|
name: '$eventValues',
|
||||||
|
ctx: conditionValues,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
variableNameOfLeftCondition: '$eventValues',
|
||||||
|
});
|
||||||
|
console.log('isConditionPass', isConditionPass);
|
||||||
|
if (isConditionPass) {
|
||||||
|
rule.actions.forEach((act: EventActionSetting) => {
|
||||||
|
const definition = this.definitions.find((def) => def.name === act.action.definition);
|
||||||
|
const action = definition?.actions?.find((action) => action.name === act.action.action);
|
||||||
// todo 获取action的参数
|
// todo 获取action的参数
|
||||||
const actionParams = act.params;
|
const actionParams = {};
|
||||||
|
act.params?.forEach((param) => {
|
||||||
|
actionParams[param.name] = getParsedValue(param.value);
|
||||||
|
});
|
||||||
|
console.log('执行动作3', act, action, actionParams);
|
||||||
if (action) {
|
if (action) {
|
||||||
action.fn(actionParams);
|
action.fn(actionParams);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
on(event: EventSetting) {
|
on(event: EventSetting) {
|
||||||
|
if (!event.event) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.events.set(EventFlowPlugin.getEventUniqueKey(event.event), event);
|
this.events.set(EventFlowPlugin.getEventUniqueKey(event.event), event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,14 @@ import { EventActionSetting } from '../../types';
|
|||||||
import { useEvent } from '../../hooks/useEvent';
|
import { useEvent } from '../../hooks/useEvent';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export function ActionParamSelect(props: { action: EventActionSetting }) {
|
export function ActionParamSelect(props: { action: EventActionSetting['action'] }) {
|
||||||
const { action, ...rest } = props;
|
const { action, ...rest } = props;
|
||||||
const { definitions } = useEvent();
|
const { definitions } = useEvent();
|
||||||
const params = definitions.find((x) => x.uid === action?.uid)?.actions?.find((x) => x.name === action.event)?.params;
|
const definition = definitions.find(
|
||||||
|
(x) => x.name === action?.definition && x.blockUid === action?.blockUid && x.pageUid === action?.pageUid,
|
||||||
|
);
|
||||||
|
const actionDef = definition?.actions?.find((x) => x.name === action.action);
|
||||||
|
const params = actionDef?.params;
|
||||||
const options = Object.keys(params || {}).map((key) => ({
|
const options = Object.keys(params || {}).map((key) => ({
|
||||||
name: key,
|
name: key,
|
||||||
label: params[key]?.title,
|
label: params[key]?.title,
|
||||||
|
@ -9,33 +9,52 @@
|
|||||||
|
|
||||||
import { observer } from '@formily/react';
|
import { observer } from '@formily/react';
|
||||||
import { Cascader } from 'antd';
|
import { Cascader } from 'antd';
|
||||||
import React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useActionOptions } from '../hooks/useActionOptions';
|
|
||||||
import { EventActionSetting } from '../../types';
|
import { EventActionSetting } from '../../types';
|
||||||
|
import { useEvent } from '../../hooks/useEvent';
|
||||||
|
import { useControllableValue } from 'ahooks';
|
||||||
|
|
||||||
export const ActionSelect = observer((props: any) => {
|
export const ActionSelect = observer((props: any) => {
|
||||||
const options = useActionOptions();
|
const { definitions } = useEvent();
|
||||||
|
const [state, setState] = useControllableValue<EventActionSetting['action']>(props, {
|
||||||
|
defaultValue: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
let treeData = definitions?.map((definition) => ({
|
||||||
|
value: `${definition.name}.${definition.blockUid}`,
|
||||||
|
label: definition.title + '-' + definition.blockUid,
|
||||||
|
children:
|
||||||
|
definition?.actions?.map((action) => ({
|
||||||
|
value: `${definition.pageUid || ''}.${definition.blockUid || ''}.${definition.name}.${action.name}`,
|
||||||
|
label: action.title,
|
||||||
|
})) || [],
|
||||||
|
}));
|
||||||
|
treeData = treeData?.filter((item) => item.children.length > 0);
|
||||||
|
|
||||||
const { onChange, value, ...rest } = props;
|
const { onChange, value, ...rest } = props;
|
||||||
const _onChange = (value: any, selectedOptions: any) => {
|
|
||||||
const v = value[1];
|
const selectedAction = useMemo(() => {
|
||||||
if (v) {
|
if (!state) return undefined;
|
||||||
const res: EventActionSetting = {
|
return [
|
||||||
definition: v.split('.')[0],
|
`${state.definition}.${state.blockUid}`,
|
||||||
event: v.split('.')[1],
|
`${state.pageUid || ''}.${state.blockUid || ''}.${state.definition}.${state.action}`,
|
||||||
uid: v.split('.')[2],
|
];
|
||||||
};
|
}, [state]);
|
||||||
onChange?.(res);
|
|
||||||
} else {
|
|
||||||
onChange?.(undefined);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const _value = value ? [value.definition, `${value.definition}.${value.event}.${value.uid}`] : [];
|
|
||||||
return (
|
return (
|
||||||
<Cascader
|
<Cascader
|
||||||
placeholder="请选择动作"
|
placeholder="请选择动作"
|
||||||
options={options}
|
options={treeData}
|
||||||
onChange={_onChange}
|
onChange={(value: any, selectedOptions: any) => {
|
||||||
value={_value}
|
const v = value[1];
|
||||||
|
if (v) {
|
||||||
|
const [pageUid, blockUid, definition, action] = v.split('.');
|
||||||
|
setState({ pageUid, blockUid, definition, action });
|
||||||
|
} else {
|
||||||
|
setState(undefined);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={selectedAction}
|
||||||
style={{ minWidth: 300 }}
|
style={{ minWidth: 300 }}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* 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, { createContext } from 'react';
|
||||||
|
|
||||||
|
export const eventContext = createContext<{ pageUid: string }>({ pageUid: '' });
|
||||||
|
|
||||||
|
export const EventProvider = (props: { pageUid: string; children: React.ReactNode }) => {
|
||||||
|
const { pageUid } = props;
|
||||||
|
return <eventContext.Provider value={{ pageUid }}>{props.children}</eventContext.Provider>;
|
||||||
|
};
|
@ -10,7 +10,7 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useControllableValue } from 'ahooks';
|
import { useControllableValue } from 'ahooks';
|
||||||
import { Card, Space, TreeSelect } from 'antd';
|
import { Card, Space, TreeSelect } from 'antd';
|
||||||
import { EventDefinition, EventSetting } from '../types';
|
import { EventDefinition, EventSetting } from '../../types';
|
||||||
|
|
||||||
export default function EventSelect(props: {
|
export default function EventSelect(props: {
|
||||||
definitions?: EventDefinition[];
|
definitions?: EventDefinition[];
|
||||||
@ -25,11 +25,11 @@ export default function EventSelect(props: {
|
|||||||
|
|
||||||
let treeData = definitions?.map((module) => ({
|
let treeData = definitions?.map((module) => ({
|
||||||
value: module.name,
|
value: module.name,
|
||||||
title: module.title + ' - ' + module.uid,
|
title: module.title + ' - ' + module.blockUid,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
children:
|
children:
|
||||||
module?.events?.map((event) => ({
|
module?.events?.map((event) => ({
|
||||||
value: `${module.name}.${event.name}${module.uid ? `.${module.uid}` : ''}`,
|
value: `${module.pageUid || ''}.${module.blockUid || ''}.${module.name}.${event.name}`,
|
||||||
title: event.title,
|
title: event.title,
|
||||||
})) || [],
|
})) || [],
|
||||||
}));
|
}));
|
||||||
@ -37,7 +37,7 @@ export default function EventSelect(props: {
|
|||||||
|
|
||||||
const selectedEvent = useMemo(() => {
|
const selectedEvent = useMemo(() => {
|
||||||
if (!state) return undefined;
|
if (!state) return undefined;
|
||||||
return `${state.definition}.${state.event}${state.uid ? `.${state.uid}` : ''}`;
|
return `${state.pageUid || ''}.${state.blockUid || ''}.${state.definition}.${state.event}`;
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -48,12 +48,16 @@ export default function EventSelect(props: {
|
|||||||
allowClear
|
allowClear
|
||||||
treeDefaultExpandAll
|
treeDefaultExpandAll
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
console.log('value', value);
|
if (!value) {
|
||||||
const [definition, event, uid] = (value as any).split('.');
|
setState(undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [pageUid, blockUid, definition, event] = value?.split('.') || [];
|
||||||
setState({
|
setState({
|
||||||
|
pageUid,
|
||||||
|
blockUid,
|
||||||
definition,
|
definition,
|
||||||
event,
|
event,
|
||||||
uid,
|
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
treeData={treeData}
|
treeData={treeData}
|
@ -1,27 +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 { useEvent } from '../../hooks/useEvent';
|
|
||||||
|
|
||||||
export function useActionOptions() {
|
|
||||||
const { definitions } = useEvent();
|
|
||||||
|
|
||||||
let treeData = definitions?.map((module) => ({
|
|
||||||
value: module.name,
|
|
||||||
label: module.title + ' - ' + module.uid,
|
|
||||||
children:
|
|
||||||
module?.actions?.map((event) => ({
|
|
||||||
value: `${module.name}.${event.name}${module.uid ? `.${module.uid}` : ''}`,
|
|
||||||
label: event.title,
|
|
||||||
})) || [],
|
|
||||||
}));
|
|
||||||
treeData = treeData?.filter((item) => item.children.length > 0);
|
|
||||||
|
|
||||||
return treeData;
|
|
||||||
}
|
|
@ -9,24 +9,26 @@
|
|||||||
|
|
||||||
import { useDataSourceManager } from '../../../data-source/data-source';
|
import { useDataSourceManager } from '../../../data-source/data-source';
|
||||||
import { useEvent } from '../../hooks/useEvent';
|
import { useEvent } from '../../hooks/useEvent';
|
||||||
import { EventParam, EventSetting, EventDefinition } from '../../types';
|
import { EventParam, EventSetting, EventDefinition, EventParamKey, StateParamKey, SystemParamKey } from '../../types';
|
||||||
|
|
||||||
const useCurrentEventParams: (event?: EventSetting['event']) => {
|
const useCurrentEventParams = (event?: EventSetting['event']) => {
|
||||||
[key: string]: EventParam;
|
|
||||||
} = (event) => {
|
|
||||||
const { definitions } = useEvent();
|
const { definitions } = useEvent();
|
||||||
const definition = definitions?.find((d) => d.name === event?.definition && d.uid === event.uid);
|
const definition = definitions?.find(
|
||||||
|
(d) => d.name === event?.definition && d.pageUid === event.pageUid && d.blockUid === event.blockUid,
|
||||||
|
);
|
||||||
const eventParams = definition?.events?.find((e) => e.name === event?.event)?.params;
|
const eventParams = definition?.events?.find((e) => e.name === event?.event)?.params;
|
||||||
return eventParams;
|
return eventParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useStateDefine = ({ definitions }: { definitions: EventDefinition[] }) => {
|
const useStateDefine = () => {
|
||||||
const stateDefine = definitions.filter((item) => item.uid && item.states);
|
const { definitions } = useEvent();
|
||||||
const stateDefineOptions = {};
|
const stateDefineOptions = {};
|
||||||
stateDefine.forEach((definition) => {
|
definitions
|
||||||
stateDefineOptions[definition.uid] = {
|
.filter((item) => item.states && item.blockUid) // 必须为区块的数据
|
||||||
name: definition.uid,
|
.forEach((definition) => {
|
||||||
title: `${definition.title}-${definition.uid}`,
|
stateDefineOptions[definition.blockUid] = {
|
||||||
|
name: definition.blockUid,
|
||||||
|
title: `${definition.title}-${definition.blockUid}`,
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: definition.states,
|
properties: definition.states,
|
||||||
};
|
};
|
||||||
@ -36,29 +38,29 @@ const useStateDefine = ({ definitions }: { definitions: EventDefinition[] }) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useFilterOptions = (event?: EventSetting['event']) => {
|
export const useFilterOptions = (event?: EventSetting['event']) => {
|
||||||
const currentEventParamsDefine = useCurrentEventParams(event);
|
const currentEventParamsDefine: EventParam[] = useCurrentEventParams(event);
|
||||||
const { definitions } = useEvent();
|
const { stateDefineOptions } = useStateDefine();
|
||||||
const { stateDefineOptions } = useStateDefine({ definitions });
|
console.log('useFilterOptions', event, currentEventParamsDefine, stateDefineOptions);
|
||||||
|
|
||||||
const options: EventParam[] = [
|
const options: EventParam[] = [
|
||||||
{
|
{
|
||||||
name: '_eventParams',
|
name: EventParamKey,
|
||||||
title: '事件参数',
|
title: '事件参数',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: currentEventParamsDefine,
|
properties: currentEventParamsDefine,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '_state',
|
name: StateParamKey,
|
||||||
title: '组件数据',
|
title: '组件数据',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: stateDefineOptions,
|
properties: stateDefineOptions,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// name: '_system',
|
name: SystemParamKey,
|
||||||
// title: '系统参数',
|
title: '应用数据',
|
||||||
// type: 'object',
|
type: 'object',
|
||||||
// properties: {},
|
properties: {},
|
||||||
// },
|
},
|
||||||
];
|
];
|
||||||
const dm = useDataSourceManager();
|
const dm = useDataSourceManager();
|
||||||
|
|
||||||
|
@ -21,13 +21,14 @@ import {
|
|||||||
useFormBlockType,
|
useFormBlockType,
|
||||||
useRecord,
|
useRecord,
|
||||||
Filter,
|
Filter,
|
||||||
|
getPageSchema,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import React, { useEffect, useMemo } from 'react';
|
import React, { useEffect, useMemo } from 'react';
|
||||||
import { ISchema, useField } from '@formily/react';
|
import { ISchema, useField } from '@formily/react';
|
||||||
import { SchemaSettingsKey, useEvent } from '..';
|
import { SchemaSettingsKey, useEvent } from '..';
|
||||||
import { useFieldSchema } from '@formily/react';
|
import { useFieldSchema } from '@formily/react';
|
||||||
import { useLinkageCollectionFieldOptions } from './ActionsSetting/action-hooks';
|
import { useLinkageCollectionFieldOptions } from './ActionsSetting/action-hooks';
|
||||||
import EventSelect from './EventSelect';
|
import EventSelect from './components/EventSelect';
|
||||||
import { ArrayCollapse } from './components/LinkageHeader';
|
import { ArrayCollapse } from './components/LinkageHeader';
|
||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { FormItem, FormLayout } from '@formily/antd-v5';
|
import { FormItem, FormLayout } from '@formily/antd-v5';
|
||||||
@ -37,6 +38,7 @@ import { ActionParamSelect } from './components/ActionParamSelect';
|
|||||||
import ConditionSelect from './components/ConditionSelect';
|
import ConditionSelect from './components/ConditionSelect';
|
||||||
import { Space } from 'antd';
|
import { Space } from 'antd';
|
||||||
import { ActionParamValueInput } from './components/ActionParamValueInput';
|
import { ActionParamValueInput } from './components/ActionParamValueInput';
|
||||||
|
import { EventProvider } from './components/EventProvider';
|
||||||
|
|
||||||
// packages/core/client/src/schema-settings/SchemaSettings.tsx
|
// packages/core/client/src/schema-settings/SchemaSettings.tsx
|
||||||
export const EventSettingItem = (props) => {
|
export const EventSettingItem = (props) => {
|
||||||
@ -47,6 +49,7 @@ export const EventSettingItem = (props) => {
|
|||||||
const { definitions, register } = useEvent();
|
const { definitions, register } = useEvent();
|
||||||
const { dn } = useDesignable();
|
const { dn } = useDesignable();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
|
const pageUid = getPageSchema(fieldSchema)?.['x-uid'];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SchemaSettingsModalItem
|
<SchemaSettingsModalItem
|
||||||
@ -80,7 +83,10 @@ export const EventSettingItem = (props) => {
|
|||||||
type: 'array',
|
type: 'array',
|
||||||
// default: defaultValues,
|
// default: defaultValues,
|
||||||
'x-component': 'ArrayCollapse',
|
'x-component': 'ArrayCollapse',
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': EventProvider,
|
||||||
|
'x-decorator-props': {
|
||||||
|
pageUid,
|
||||||
|
},
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
accordion: true,
|
accordion: true,
|
||||||
titleRender: (item: any, index: number) => {
|
titleRender: (item: any, index: number) => {
|
||||||
@ -101,6 +107,7 @@ export const EventSettingItem = (props) => {
|
|||||||
definitions,
|
definitions,
|
||||||
className: css`
|
className: css`
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
width: 100%;
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -109,23 +116,6 @@ export const EventSettingItem = (props) => {
|
|||||||
'x-content': '{{ t("执行规则") }}',
|
'x-content': '{{ t("执行规则") }}',
|
||||||
},
|
},
|
||||||
actionsBlock: rulesSchema,
|
actionsBlock: rulesSchema,
|
||||||
// actionsBlock: {
|
|
||||||
// type: 'void',
|
|
||||||
// 'x-component': ActionsSetting,
|
|
||||||
// 'x-use-component-props': () => {
|
|
||||||
// return {
|
|
||||||
// options,
|
|
||||||
// linkageOptions,
|
|
||||||
// category: 'default',
|
|
||||||
// elementType: 'field',
|
|
||||||
// collectionName,
|
|
||||||
// // form,
|
|
||||||
// variables,
|
|
||||||
// localVariables,
|
|
||||||
// formBlockType,
|
|
||||||
// };
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
remove: {
|
remove: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'ArrayCollapse.Remove',
|
'x-component': 'ArrayCollapse.Remove',
|
||||||
|
@ -9,20 +9,32 @@
|
|||||||
|
|
||||||
import { EventDefinition, EventSetting } from '../types';
|
import { EventDefinition, EventSetting } from '../types';
|
||||||
import { useFieldSchema } from '@formily/react';
|
import { useFieldSchema } from '@formily/react';
|
||||||
import { getPageSchema, useApp, usePlugin, useSchemaSettings } from '@nocobase/client';
|
import { getPageSchema, useApp, useLocalVariables, usePlugin, useVariables, useSchemaSettings } from '@nocobase/client';
|
||||||
import React from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { ISchema, useField } from '@formily/react';
|
import { ISchema, useField } from '@formily/react';
|
||||||
import { EventFlowPlugin } from '..';
|
import { EventFlowPlugin } from '..';
|
||||||
import { useMemoizedFn } from 'ahooks';
|
import { useMemoizedFn } from 'ahooks';
|
||||||
|
import { eventContext } from '../EventSettingItem/components/EventProvider';
|
||||||
|
|
||||||
export const useEvent = () => {
|
export const useEvent = () => {
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const uid = fieldSchema?.['x-uid'];
|
const context = useContext(eventContext);
|
||||||
const pageUid = getPageSchema(fieldSchema)?.['x-uid'];
|
const pageUid = context.pageUid || getPageSchema(fieldSchema)?.['x-uid'];
|
||||||
|
const blockUid = fieldSchema?.['x-uid'];
|
||||||
const eventFlowPlugin: EventFlowPlugin = usePlugin(EventFlowPlugin.name) as any;
|
const eventFlowPlugin: EventFlowPlugin = usePlugin(EventFlowPlugin.name) as any;
|
||||||
|
const variables = useVariables();
|
||||||
|
const localVariables = useLocalVariables({ currentForm: null });
|
||||||
|
|
||||||
const define = useMemoizedFn((definition: EventDefinition[] | EventDefinition) => {
|
const define = useMemoizedFn((definition: EventDefinition[] | EventDefinition) => {
|
||||||
eventFlowPlugin?.define(definition, fieldSchema);
|
if (!definition) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const definitions = Array.isArray(definition) ? definition : [definition];
|
||||||
|
definitions.forEach((item) => {
|
||||||
|
item.pageUid = pageUid;
|
||||||
|
item.blockUid = blockUid;
|
||||||
|
});
|
||||||
|
eventFlowPlugin?.define(definitions);
|
||||||
});
|
});
|
||||||
|
|
||||||
const register = useMemoizedFn((events: EventSetting[]) => {
|
const register = useMemoizedFn((events: EventSetting[]) => {
|
||||||
@ -33,14 +45,19 @@ export const useEvent = () => {
|
|||||||
await eventFlowPlugin?.emit({
|
await eventFlowPlugin?.emit({
|
||||||
event: {
|
event: {
|
||||||
...p.event,
|
...p.event,
|
||||||
uid: uid,
|
pageUid,
|
||||||
|
blockUid,
|
||||||
},
|
},
|
||||||
params: p.params,
|
params: p.params,
|
||||||
|
variables,
|
||||||
|
localVariables,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('event pageUid', pageUid);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
definitions: eventFlowPlugin?.definitions.filter((item) => item.pageUid === pageUid || !item.pageUid || !pageUid),
|
definitions: eventFlowPlugin?.definitions.filter((item) => item.pageUid === pageUid || !item.pageUid),
|
||||||
// 定义事件
|
// 定义事件
|
||||||
define,
|
define,
|
||||||
// 移除事件
|
// 移除事件
|
||||||
|
@ -10,7 +10,9 @@
|
|||||||
export const PluginName = 'event';
|
export const PluginName = 'event';
|
||||||
export const SchemaSettingsKey = 'x-event-settings';
|
export const SchemaSettingsKey = 'x-event-settings';
|
||||||
export const SchemaDefinitionsKey = 'x-event-definitions';
|
export const SchemaDefinitionsKey = 'x-event-definitions';
|
||||||
|
export const EventParamKey = '$eventParams';
|
||||||
|
export const StateParamKey = '_state';
|
||||||
|
export const SystemParamKey = '_system';
|
||||||
export interface EventParam {
|
export interface EventParam {
|
||||||
name?: string; // 在item 情况下没有name https://json-schema.org/understanding-json-schema/reference/array
|
name?: string; // 在item 情况下没有name https://json-schema.org/understanding-json-schema/reference/array
|
||||||
title?: string;
|
title?: string;
|
||||||
@ -26,41 +28,52 @@ export interface EventParam {
|
|||||||
|
|
||||||
/** 事件动作 */
|
/** 事件动作 */
|
||||||
export interface EventAction {
|
export interface EventAction {
|
||||||
|
/** 动作名称 英文,全局唯一 */
|
||||||
name: string;
|
name: string;
|
||||||
|
/** 动作标题 */
|
||||||
title: string;
|
title: string;
|
||||||
|
/** 动作描述 */
|
||||||
description?: string;
|
description?: string;
|
||||||
params?: {
|
/** 动作参数 */
|
||||||
[key: string]: EventParam;
|
params?: EventParam[];
|
||||||
};
|
/** 动作返回值 */
|
||||||
|
return?: EventParam;
|
||||||
|
/** 动作执行函数 */
|
||||||
fn: (params?: any) => void;
|
fn: (params?: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 事件事件 */
|
/** 具体事件定义 */
|
||||||
export interface EventEvent {
|
export interface EventEvent {
|
||||||
|
/** 事件名称 英文,全局唯一 */
|
||||||
name: string;
|
name: string;
|
||||||
|
/** 事件标题 */
|
||||||
title: string;
|
title: string;
|
||||||
uid?: string;
|
/** 事件描述 */
|
||||||
description?: string;
|
description?: string;
|
||||||
params?: {
|
/** 事件参数, 可以配置多个参数 */
|
||||||
[key: string]: EventParam;
|
params?: EventParam[];
|
||||||
};
|
|
||||||
value?: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 事件定义 */
|
/** 事件模块定义 */
|
||||||
export interface EventDefinition {
|
export interface EventDefinition {
|
||||||
|
/** 定义名称 英文,全局唯一 */
|
||||||
name: string;
|
name: string;
|
||||||
/** 标识同一类型组件的不同实例 */
|
/** 定义所属页面uid, 系统级别定义该字段为 'app' */
|
||||||
uid?: string;
|
|
||||||
/** 标识所属页面 */
|
|
||||||
pageUid?: string;
|
pageUid?: string;
|
||||||
|
/** 定义所属区块uid,系统级别定义该字段为空 */
|
||||||
|
blockUid?: string;
|
||||||
|
/** 定义标题 */
|
||||||
title: string;
|
title: string;
|
||||||
|
/** 定义描述 */
|
||||||
description?: string;
|
description?: string;
|
||||||
|
/** 事件 */
|
||||||
events?: EventEvent[];
|
events?: EventEvent[];
|
||||||
|
/** 动作 */
|
||||||
|
actions?: EventAction[];
|
||||||
|
/** 区块内暴露的数据 */
|
||||||
states?: {
|
states?: {
|
||||||
[key: string]: EventParam;
|
[key: string]: EventParam;
|
||||||
};
|
};
|
||||||
actions?: EventAction[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 事件设置 */
|
/** 事件设置 */
|
||||||
@ -68,17 +81,23 @@ export interface EventSetting {
|
|||||||
event: {
|
event: {
|
||||||
definition: string;
|
definition: string;
|
||||||
event: string;
|
event: string;
|
||||||
uid?: string;
|
pageUid?: string;
|
||||||
|
blockUid?: string;
|
||||||
};
|
};
|
||||||
/** 标识同一类型组件的不同实例 */
|
rules?: Array<{
|
||||||
// uid?: string;
|
|
||||||
condition: string;
|
condition: string;
|
||||||
actions: Array<EventActionSetting>;
|
actions: Array<EventActionSetting>;
|
||||||
|
}>;
|
||||||
|
/** 标识同一类型组件的不同实例 */
|
||||||
|
// uid?: string;
|
||||||
}
|
}
|
||||||
export interface EventActionSetting {
|
export interface EventActionSetting {
|
||||||
|
action: {
|
||||||
definition: string;
|
definition: string;
|
||||||
action: string;
|
action: string;
|
||||||
uid?: string;
|
pageUid?: string;
|
||||||
|
blockUid?: string;
|
||||||
|
};
|
||||||
params?: Array<EventActionSettingParams>;
|
params?: Array<EventActionSettingParams>;
|
||||||
}
|
}
|
||||||
export interface EventActionSettingParams {
|
export interface EventActionSettingParams {
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ISchema } from '@formily/react';
|
import { ISchema } from '@formily/react';
|
||||||
|
import { every, findIndex, some } from 'lodash';
|
||||||
|
import { getValuesByPath, uid } from '@nocobase/utils/client';
|
||||||
|
|
||||||
export const getPageSchema = (schema: any) => {
|
export const getPageSchema = (schema: any) => {
|
||||||
if (schema?.['x-component'] === 'Page') {
|
if (schema?.['x-component'] === 'Page') {
|
||||||
@ -18,3 +20,79 @@ export const getPageSchema = (schema: any) => {
|
|||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getAllKeys(obj) {
|
||||||
|
const keys = [];
|
||||||
|
function traverse(o) {
|
||||||
|
Object.keys(o)
|
||||||
|
.sort()
|
||||||
|
.forEach(function (key) {
|
||||||
|
keys.push(key);
|
||||||
|
if (o[key] && typeof o[key] === 'object') {
|
||||||
|
traverse(o[key]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
traverse(obj);
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTargetField = (obj) => {
|
||||||
|
const keys = getAllKeys(obj);
|
||||||
|
const index = findIndex(keys, (key, index, keys) => {
|
||||||
|
if (key.includes('$') && index > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const result = keys.slice(0, index);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getFieldValuesInCondition({ linkageRules, formValues }) {
|
||||||
|
return linkageRules.map((rule) => {
|
||||||
|
const run = (condition) => {
|
||||||
|
const type = Object.keys(condition)[0] || '$and';
|
||||||
|
const conditions = condition[type];
|
||||||
|
|
||||||
|
return conditions
|
||||||
|
.map((condition) => {
|
||||||
|
if ('$and' in condition || '$or' in condition) {
|
||||||
|
return run(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = getTargetField(condition).join('.');
|
||||||
|
return getValuesByPath(formValues, path);
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
};
|
||||||
|
|
||||||
|
return run(rule.condition);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getConditionResult({ condition, values }) {
|
||||||
|
const run = (condition) => {
|
||||||
|
const type = Object.keys(condition)[0] || '$and';
|
||||||
|
const conditions = condition[type];
|
||||||
|
|
||||||
|
const ress = conditions.map((condition) => {
|
||||||
|
if ('$and' in condition || '$or' in condition) {
|
||||||
|
return run(condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = getTargetField(condition).join('.');
|
||||||
|
console.log('path', path, values);
|
||||||
|
const v = getValuesByPath(values, path);
|
||||||
|
console.log('v', v);
|
||||||
|
return v;
|
||||||
|
});
|
||||||
|
if (type === '$and') {
|
||||||
|
return every(ress, Boolean);
|
||||||
|
}
|
||||||
|
if (type === '$or') {
|
||||||
|
return some(ress, Boolean);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return run(condition);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user