mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-07 22:49:26 +08:00
feat: support action add
This commit is contained in:
parent
e973756d5a
commit
c86d084f5a
@ -7,10 +7,10 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { ArrayField as ArrayFieldModel, VoidField } from '@formily/core';
|
||||
import { ArrayField as ArrayFieldModel, VoidField, ObjectField as ObjectFieldModel } from '@formily/core';
|
||||
import { ArrayField, ObjectField, observer, useField } from '@formily/react';
|
||||
import { Space, TreeSelect } from 'antd';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { Button, Cascader, Input, Space, TreeSelect } from 'antd';
|
||||
import React, { useCallback, useContext, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
|
||||
import {
|
||||
@ -20,40 +20,64 @@ import {
|
||||
} from './LinkageRuleAction';
|
||||
import { RemoveActionContext } from './context';
|
||||
import { useControllableValue } from 'ahooks';
|
||||
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||
import { useActionOptions } from './hooks/useActionOptions';
|
||||
|
||||
const ActionSelect = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const { definitions, className } = props;
|
||||
const [state, setState] = useControllableValue<String>(props, {
|
||||
defaultValue: undefined,
|
||||
});
|
||||
let treeData = definitions?.map((module) => ({
|
||||
value: module.name,
|
||||
title: module.title + ' - ' + module.uid,
|
||||
selectable: false,
|
||||
children:
|
||||
module?.events?.map((event) => ({
|
||||
value: module.name + '.' + event.name,
|
||||
title: event.title,
|
||||
})) || [],
|
||||
}));
|
||||
treeData = treeData?.filter((item) => item.children.length > 0);
|
||||
|
||||
const ActionParams = observer((props) => {
|
||||
const field = useField<ArrayFieldModel>();
|
||||
return (
|
||||
<TreeSelect
|
||||
value={state}
|
||||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
||||
placeholder="Please select"
|
||||
allowClear
|
||||
treeDefaultExpandAll
|
||||
onChange={(value) => {
|
||||
setState(value);
|
||||
}}
|
||||
treeData={treeData}
|
||||
className={className}
|
||||
/>
|
||||
<div>
|
||||
{field?.value?.map((item, index) => (
|
||||
<div key={index}>
|
||||
<Input />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export const ActionRow = observer(
|
||||
(props: any): any => {
|
||||
const { onRemove } = props;
|
||||
const options = useActionOptions();
|
||||
const field = useField<any>();
|
||||
const onClick = useCallback(() => {
|
||||
console.log('field2', field);
|
||||
// const f = field.query('.params').take() as ObjectFieldModel;
|
||||
// field.val = field.data || {};
|
||||
// field.data.params = field.data.params || [];
|
||||
// field.data.params.push({});
|
||||
// const items = f.value || [];
|
||||
// items.push({});
|
||||
// f.value = items;
|
||||
// f.initialValue = items;
|
||||
}, [field]);
|
||||
return (
|
||||
<div>
|
||||
<Space>
|
||||
<Cascader
|
||||
// value={state}
|
||||
options={options}
|
||||
onChange={(value) => {
|
||||
console.log('value', value);
|
||||
// setState(value);
|
||||
}}
|
||||
></Cascader>
|
||||
<div>
|
||||
<ArrayField name={'params'} component={[ActionParams, {}]} disabled={false} />
|
||||
<Button onClick={onClick}>添加参数</Button>
|
||||
</div>
|
||||
{!props.disabled && (
|
||||
<a role="button" aria-label="icon-close">
|
||||
<CloseCircleOutlined onClick={onRemove} style={{ color: '#bfbfbf' }} />
|
||||
</a>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{ displayName: 'ActionRow' },
|
||||
);
|
||||
|
||||
export const Action = observer(
|
||||
(props: any): any => {
|
||||
@ -67,13 +91,16 @@ export const Action = observer(
|
||||
field: FormFieldLinkageRuleAction,
|
||||
style: FormStyleLinkageRuleAction,
|
||||
};
|
||||
|
||||
// console.log('field?.value', field.value);
|
||||
|
||||
return field?.value?.map((item, index) => {
|
||||
return (
|
||||
<RemoveActionContext.Provider key={index} value={() => field.remove(index)}>
|
||||
<ObjectField name={index} component={[ActionSelect, { ...props, options: linkageOptions }]} />
|
||||
<ObjectField name={index} component={[ActionRow]} />
|
||||
</RemoveActionContext.Provider>
|
||||
);
|
||||
});
|
||||
},
|
||||
{ displayName: 'LinkageRuleActions' },
|
||||
{ displayName: 'Action' },
|
||||
);
|
||||
|
@ -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 { Field, ObjectField, observer, useField } from '@formily/react';
|
||||
import { Button, Input, Space } from 'antd';
|
||||
import React from 'react';
|
||||
import { ArrayField as ArrayFieldModel } from '@formily/core';
|
||||
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||
|
||||
const ActionParams = observer((props: any) => {
|
||||
return (
|
||||
<Space>
|
||||
<Field name="name" component={[Input]} />
|
||||
<span>等于</span>
|
||||
<Field name="value" component={[Input]} />
|
||||
{!props.disabled && (
|
||||
<a role="button" aria-label="icon-close">
|
||||
<CloseCircleOutlined onClick={props.onRemove} style={{ color: '#bfbfbf' }} />
|
||||
</a>
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
});
|
||||
|
||||
export const ActionParamsField = observer((props: { action: string }) => {
|
||||
const field = useField<ArrayFieldModel>();
|
||||
const { action } = props;
|
||||
console.log('ActionParamsField action', props);
|
||||
return (
|
||||
<Space direction="vertical">
|
||||
{field?.value?.map((item, index) => (
|
||||
<ObjectField key={index} name={index} component={[ActionParams, { onRemove: () => field.remove(index) }]} />
|
||||
))}
|
||||
<Button type="link" onClick={() => field.push({})}>
|
||||
添加参数
|
||||
</Button>
|
||||
</Space>
|
||||
);
|
||||
});
|
@ -8,13 +8,15 @@
|
||||
*/
|
||||
|
||||
import { ArrayField as ArrayFieldModel, VoidField } from '@formily/core';
|
||||
import { ArrayField, ObjectField, observer, useField } from '@formily/react';
|
||||
import { Space } from 'antd';
|
||||
import { ArrayField, ObjectField, observer, useField, Field } from '@formily/react';
|
||||
import { Space, Button, Cascader } from 'antd';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
|
||||
import { Action } from './Action';
|
||||
import { ArrayBase } from '@formily/antd-v5';
|
||||
import { useActionOptions } from './hooks/useActionOptions';
|
||||
import { CloseCircleOutlined } from '@ant-design/icons';
|
||||
import { ActionParamsField } from './ActionParams';
|
||||
|
||||
interface LinkageRuleActionGroupProps {
|
||||
type: 'button' | 'field' | 'style';
|
||||
@ -22,34 +24,48 @@ interface LinkageRuleActionGroupProps {
|
||||
collectionName: string;
|
||||
}
|
||||
|
||||
export const Actions = withDynamicSchemaProps(
|
||||
(props: LinkageRuleActionGroupProps) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useField<VoidField>();
|
||||
const { category, elementType, linkageOptions, collectionName } = props;
|
||||
|
||||
const components = useMemo(
|
||||
() => [Action, { category, elementType, linkageOptions, collectionName }],
|
||||
[collectionName, linkageOptions, category, elementType],
|
||||
);
|
||||
const spaceStyle = useMemo(() => ({ marginTop: 8, marginBottom: 8 }), []);
|
||||
const style = useMemo(() => ({ marginLeft: 10 }), []);
|
||||
const onClick = useCallback(() => {
|
||||
const f = field.query('.actions').take() as ArrayFieldModel;
|
||||
const items = f.value || [];
|
||||
items.push({});
|
||||
f.value = items;
|
||||
f.initialValue = items;
|
||||
}, [field]);
|
||||
|
||||
const Action = observer(
|
||||
(props: any): any => {
|
||||
const { onRemove } = props;
|
||||
const options = useActionOptions();
|
||||
const field = useField<any>();
|
||||
field.onFieldChange = (field) => {
|
||||
console.log('field', field);
|
||||
};
|
||||
return (
|
||||
<div style={style}>
|
||||
<ArrayField name={'actions'} component={components} disabled={false} />
|
||||
<Space size={16} style={spaceStyle}>
|
||||
<a onClick={onClick}>{t('添加动作')}</a>
|
||||
</Space>
|
||||
</div>
|
||||
<Space align="start">
|
||||
<Field name="action" component={[Cascader, { options, placeholder: '选择动作' }]} />
|
||||
<ArrayField name={'params'} component={[ActionParamsField, { action: field.value.action?.value }]} />
|
||||
{!props.disabled && (
|
||||
<a role="button" aria-label="icon-close">
|
||||
<CloseCircleOutlined onClick={onRemove} style={{ color: '#bfbfbf' }} />
|
||||
</a>
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
{ displayName: 'ActionRow' },
|
||||
);
|
||||
|
||||
const Actions = withDynamicSchemaProps(
|
||||
observer((props: LinkageRuleActionGroupProps) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useField<ArrayFieldModel>();
|
||||
return (
|
||||
<Space style={{ paddingLeft: 10 }} direction="vertical">
|
||||
{field?.value?.map((item, index) => {
|
||||
return <ObjectField key={index} name={index} component={[Action, { onRemove: () => field.remove(index) }]} />;
|
||||
})}
|
||||
<a onClick={() => field.push({})}>{t('添加动作')}</a>
|
||||
</Space>
|
||||
);
|
||||
}),
|
||||
{ displayName: 'Actions' },
|
||||
);
|
||||
|
||||
export const ActionsField = withDynamicSchemaProps(
|
||||
observer((props: LinkageRuleActionGroupProps) => {
|
||||
return <ArrayField name={'actions'} component={[Actions]} />;
|
||||
}),
|
||||
{ displayName: 'ActionsField' },
|
||||
);
|
||||
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
@ -20,7 +20,7 @@ import { SubFormProvider } from '../../../schema-component/antd/association-fiel
|
||||
import { DynamicComponentProps } from '../../../schema-component/antd/filter/DynamicComponent';
|
||||
import { FilterContext } from '../../../schema-component/antd/filter/context';
|
||||
import { VariableInput, getShouldChange } from '../../../schema-settings/VariableInput/VariableInput';
|
||||
import { Actions } from './Actions';
|
||||
import { ActionsField } from './Actions';
|
||||
import { FormProvider, createSchemaField } from '@formily/react';
|
||||
import { ArrayCollapse } from '../components/LinkageHeader';
|
||||
import { Filter } from '../Filter';
|
||||
@ -126,7 +126,6 @@ export const ActionsSetting = withDynamicSchemaProps(
|
||||
getAllCollectionsInheritChain,
|
||||
})}
|
||||
returnScope={(scope) => {
|
||||
// console.log('scope', [...scope, ...variableOptions]);
|
||||
return uniqBy([...scope, ...variableOptions], 'key');
|
||||
}}
|
||||
/>
|
||||
@ -140,7 +139,7 @@ export const ActionsSetting = withDynamicSchemaProps(
|
||||
},
|
||||
actions: {
|
||||
type: 'void',
|
||||
'x-component': (_props) => <Actions {..._props} {...props} />,
|
||||
'x-component': ActionsField,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user