mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-04 21:08:55 +08:00
update: 优化动作配置部分
Change-Id: Ie01a37a1a50cec51efc9dfd178daff5208c3f4b3
This commit is contained in:
parent
463eb2df08
commit
a82d0e0566
@ -6,6 +6,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import React from 'react';
|
||||
import {
|
||||
FORMITEM_CMPTS,
|
||||
getArgsWrapper,
|
||||
IS_DATA_CONTAINER,
|
||||
renderCmptActionSelect,
|
||||
@ -29,8 +30,8 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '跳转链接',
|
||||
actionType: 'url',
|
||||
description: '跳转至指定链接的页面',
|
||||
config: ['url', 'params', 'blank'],
|
||||
desc: (info: any) => {
|
||||
innerArgs: ['url', 'params', 'blank'],
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
跳转<span className="variable-left">{info?.args?.url}</span>
|
||||
@ -98,8 +99,8 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '打开页面',
|
||||
actionType: 'link',
|
||||
description: '打开指定页面',
|
||||
config: ['link', 'params'],
|
||||
desc: (info: any) => {
|
||||
innerArgs: ['link', 'params'],
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
打开
|
||||
@ -127,7 +128,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '回退页面',
|
||||
actionType: 'goBack',
|
||||
description: '浏览器回退',
|
||||
desc: (info: any) => <div>返回上一页</div>
|
||||
descDetail: (info: any) => <div>返回上一页</div>
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -272,7 +273,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '消息提醒',
|
||||
actionType: 'toast',
|
||||
description: '弹出消息提醒',
|
||||
config: [
|
||||
innerArgs: [
|
||||
'title',
|
||||
'msgType',
|
||||
'msg',
|
||||
@ -281,7 +282,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
'closeButton',
|
||||
'showIcon'
|
||||
],
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">
|
||||
@ -407,8 +408,8 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '发送请求',
|
||||
actionType: 'ajax',
|
||||
description: '配置并发送API请求',
|
||||
config: ['api'],
|
||||
desc: (info: any) => {
|
||||
innerArgs: ['api'],
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
发送
|
||||
@ -436,7 +437,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '下载文件',
|
||||
actionType: 'download',
|
||||
description: '触发下载文件',
|
||||
config: ['api'],
|
||||
innerArgs: ['api'],
|
||||
schema: {
|
||||
type: 'wrapper',
|
||||
style: {padding: '0 0 0 32px'},
|
||||
@ -462,7 +463,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'show',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
显示
|
||||
@ -476,7 +477,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
},
|
||||
{
|
||||
actionType: 'hidden',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
隐藏
|
||||
@ -489,6 +490,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
}
|
||||
}
|
||||
],
|
||||
supportComponents: '*',
|
||||
schema: [
|
||||
...renderCmptSelect('选择组件', true),
|
||||
{
|
||||
@ -519,7 +521,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actions: [
|
||||
{
|
||||
actionType: 'enabled',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
启用
|
||||
@ -533,7 +535,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
},
|
||||
{
|
||||
actionType: 'disabled',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
禁用
|
||||
@ -546,6 +548,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
}
|
||||
}
|
||||
],
|
||||
supportComponents: ['form', ...FORMITEM_CMPTS],
|
||||
schema: [
|
||||
...renderCmptSelect('选择组件', true),
|
||||
{
|
||||
@ -573,7 +576,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '刷新组件',
|
||||
actionType: 'reload',
|
||||
description: '请求并重新加载所选组件的数据',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
刷新
|
||||
@ -590,8 +593,8 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '设置组件数据',
|
||||
actionType: 'setValue',
|
||||
description: '设置数据容器或表单项的数据',
|
||||
config: ['value', 'valueInput'],
|
||||
desc: (info: any) => {
|
||||
innerArgs: ['value', 'valueInput'],
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
设置
|
||||
@ -708,7 +711,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '提交表单',
|
||||
actionType: 'submit',
|
||||
description: '提交表单数据至数据源',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -716,13 +719,14 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
</div>
|
||||
);
|
||||
},
|
||||
supportComponents: 'form',
|
||||
schema: renderCmptSelect('选择组件', true)
|
||||
},
|
||||
{
|
||||
actionLabel: '清空表单',
|
||||
actionType: 'clear',
|
||||
description: '清空表单数据',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -730,13 +734,14 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
</div>
|
||||
);
|
||||
},
|
||||
supportComponents: 'form',
|
||||
schema: renderCmptSelect('选择组件', true)
|
||||
},
|
||||
{
|
||||
actionLabel: '重置表单',
|
||||
actionType: 'reset',
|
||||
description: '重置表单数据',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -744,13 +749,14 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
</div>
|
||||
);
|
||||
},
|
||||
supportComponents: 'form',
|
||||
schema: renderCmptSelect('选择组件', true)
|
||||
},
|
||||
{
|
||||
actionLabel: '校验表单',
|
||||
actionType: 'validate',
|
||||
description: '校验表单数据',
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -758,6 +764,7 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
</div>
|
||||
);
|
||||
},
|
||||
supportComponents: 'form',
|
||||
schema: renderCmptSelect('选择组件', true)
|
||||
},
|
||||
{
|
||||
@ -777,8 +784,8 @@ const ACTION_TYPE_TREE = (manager: any): RendererPluginAction[] => {
|
||||
actionLabel: '复制内容',
|
||||
actionType: 'copy',
|
||||
description: '复制文本内容至粘贴板',
|
||||
config: ['content', 'copyFormat'],
|
||||
desc: (info: any) => {
|
||||
innerArgs: ['content', 'copyFormat'],
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
复制内容:
|
||||
|
@ -5,7 +5,8 @@ import React from 'react';
|
||||
import {
|
||||
PluginActions,
|
||||
RendererPluginAction,
|
||||
RendererPluginEvent
|
||||
RendererPluginEvent,
|
||||
SubRendererPluginAction
|
||||
} from 'amis-editor-core';
|
||||
import {ActionConfig, ComponentInfo, ContextVariables} from './types';
|
||||
import {DataSchema, findTree} from 'amis-core';
|
||||
@ -28,361 +29,6 @@ export const IS_DATA_CONTAINER = `${JSON.stringify(
|
||||
DATA_CONTAINER
|
||||
)}.includes(__rendererName)`;
|
||||
|
||||
export const getArgsWrapper = (items: any, multiple: boolean = false) => ({
|
||||
type: 'combo',
|
||||
name: 'args',
|
||||
// label: '动作参数',
|
||||
multiple,
|
||||
strictMode: false,
|
||||
items: Array.isArray(items) ? items : [items]
|
||||
});
|
||||
|
||||
// 获取动作树中指定的动作
|
||||
export const findActionNode = (
|
||||
actions: RendererPluginAction[],
|
||||
actionType: string
|
||||
) => findTree(actions, node => node.actionType === actionType);
|
||||
|
||||
// 获取包含指定子动作的动作
|
||||
export const findHasSubActionNode = (
|
||||
actions: RendererPluginAction[],
|
||||
actionType: string
|
||||
) =>
|
||||
findTree(actions, node =>
|
||||
node.actions?.find(item => item.actionType === actionType)
|
||||
);
|
||||
|
||||
// 获取真实的动作类型
|
||||
export const getActionType = (
|
||||
action: ActionConfig,
|
||||
hasSubActionNode: RendererPluginAction | null
|
||||
) =>
|
||||
action.__isCmptAction
|
||||
? 'component'
|
||||
: hasSubActionNode
|
||||
? hasSubActionNode.actionType
|
||||
: action.actionType;
|
||||
|
||||
// 获取事件Label文案
|
||||
export const getEventLabel = (events: RendererPluginEvent[], name: string) =>
|
||||
events.find(item => item.eventName === name)?.eventLabel;
|
||||
|
||||
// 获取事件描述文案
|
||||
export const getEventDesc = (events: RendererPluginEvent[], name: string) =>
|
||||
events.find(item => item.eventName === name)?.description;
|
||||
|
||||
// 获取动作Label文案
|
||||
export const getActionLabel = (events: RendererPluginAction[], name: string) =>
|
||||
findTree(events, item => item.actionType === name)?.actionLabel;
|
||||
|
||||
// 根据动作类型获取过滤后的组件树
|
||||
export const getComponentTreeSource = (
|
||||
actionType: string,
|
||||
pluginActions: PluginActions,
|
||||
getComponents: () => ComponentInfo[],
|
||||
commonActions?: {[propName: string]: RendererPluginAction}
|
||||
) => {
|
||||
if (!actionType) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const commonActionConfig = {
|
||||
...COMMON_ACTION_SCHEMA_MAP,
|
||||
...commonActions
|
||||
};
|
||||
// 如果组件树结构没有传,则重新获取
|
||||
const components = getComponents ? getComponents() || [] : [];
|
||||
return getComponentTreeByType(
|
||||
components,
|
||||
actionType,
|
||||
pluginActions,
|
||||
commonActionConfig
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据不同的动作类型过滤组件树
|
||||
* @param componentsTree 组件树
|
||||
* @param actionType 动作类型
|
||||
* @returns
|
||||
*/
|
||||
export const getComponentTreeByType = (
|
||||
componentsTree: ComponentInfo[] = [],
|
||||
actionType: string = '',
|
||||
pluginActions: {
|
||||
[key: string]: any;
|
||||
} = {},
|
||||
actionConfigItems: {[propName: string]: RendererPluginAction}
|
||||
) => {
|
||||
const hasActionType = (actions?: RendererPluginAction[]) => {
|
||||
if (!Array.isArray(actions)) {
|
||||
return false;
|
||||
}
|
||||
return !!actions?.find(item =>
|
||||
[item.actionType, 'component'].includes(actionType)
|
||||
);
|
||||
};
|
||||
|
||||
const loopChildren = (nodes: ComponentInfo[]) => {
|
||||
const temp: ComponentInfo[] = [];
|
||||
for (let node of nodes) {
|
||||
const actions = pluginActions[node.type];
|
||||
|
||||
if (
|
||||
['visibility'].includes(actionType) ||
|
||||
(['usability'].includes(actionType) &&
|
||||
['form', ...FORMITEM_CMPTS].includes(node.type)) ||
|
||||
(!['submit', 'clear', 'reset', 'validate'].includes(actionType) &&
|
||||
node.type &&
|
||||
hasActionType(actions)) ||
|
||||
(['submit', 'clear', 'reset', 'validate'].includes(actionType) &&
|
||||
node.type === 'form') ||
|
||||
((actionType === 'component' ||
|
||||
actionConfigItems[actionType]?.withComponentId) &&
|
||||
actionConfigItems[actionType]?.supportComponents?.includes(node.type))
|
||||
) {
|
||||
// 组件特性动作,如果当前组件没有动作,则禁用
|
||||
const disabled =
|
||||
actionType === 'component' && (!actions || !actions.length);
|
||||
const newNode: ComponentInfo = {
|
||||
...node,
|
||||
disabled: disabled || node.disabled,
|
||||
children: []
|
||||
};
|
||||
if (node.children?.length) {
|
||||
// 检查子项
|
||||
newNode.children?.push(...loopChildren(node.children));
|
||||
}
|
||||
temp.push(newNode);
|
||||
} else if (node.children?.length) {
|
||||
const childNodes = loopChildren(node.children);
|
||||
if (childNodes.length) {
|
||||
temp.push(...childNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
};
|
||||
|
||||
return loopChildren(componentsTree);
|
||||
};
|
||||
|
||||
// 获取动作配置
|
||||
export const getAcionConfig = (
|
||||
action: ActionConfig,
|
||||
actionTree: RendererPluginAction[],
|
||||
pluginActions: PluginActions,
|
||||
commonActions?: {[propName: string]: RendererPluginAction}
|
||||
): RendererPluginAction | undefined => {
|
||||
const commonActionConfig = {
|
||||
...COMMON_ACTION_SCHEMA_MAP,
|
||||
...commonActions
|
||||
};
|
||||
const actionNode = findActionNode(actionTree, action.actionType);
|
||||
if (actionNode) {
|
||||
return actionNode;
|
||||
}
|
||||
|
||||
const hasSubActionNode = findHasSubActionNode(actionTree, action.actionType);
|
||||
let actionConfig: RendererPluginAction | undefined =
|
||||
hasSubActionNode?.actions?.find(
|
||||
item => item.actionType === action.actionType
|
||||
) ?? commonActionConfig[action.actionType];
|
||||
|
||||
if (!actionConfig && action.componentId) {
|
||||
// 尝试从actions中获取desc
|
||||
actionConfig = pluginActions[action.__rendererName]?.find(
|
||||
(item: RendererPluginAction) => item.actionType === action.actionType
|
||||
);
|
||||
}
|
||||
|
||||
return actionConfig;
|
||||
};
|
||||
|
||||
// 格式化初始化时的动作配置
|
||||
export const formatActionInitConfig = (
|
||||
action: ActionConfig,
|
||||
actionTree: RendererPluginAction[],
|
||||
pluginActions: PluginActions,
|
||||
getComponents: () => ComponentInfo[],
|
||||
commonActions?: {[propName: string]: RendererPluginAction}
|
||||
) => {
|
||||
let config = {...action};
|
||||
|
||||
if (['setValue', 'url', 'link'].includes(action.actionType) && action.args) {
|
||||
const prop = action.actionType === 'setValue' ? 'value' : 'params';
|
||||
!config.args && (config.args = {});
|
||||
if (Array.isArray(action.args[prop])) {
|
||||
config.args[prop] = action.args[prop].reduce(
|
||||
(arr: any, valueItem: any, index: number) => {
|
||||
if (!arr[index]) {
|
||||
arr[index] = {};
|
||||
}
|
||||
arr[index].item = Object.entries(valueItem).map(([key, val]) => ({
|
||||
key,
|
||||
val
|
||||
}));
|
||||
return arr;
|
||||
},
|
||||
[]
|
||||
);
|
||||
} else if (typeof action.args[prop] === 'object') {
|
||||
config.args[prop] = Object.keys(action.args[prop]).map(key => ({
|
||||
key,
|
||||
val: action.args?.[prop][key]
|
||||
}));
|
||||
} else if (
|
||||
action.actionType === 'setValue' &&
|
||||
typeof action.args[prop] === 'string'
|
||||
) {
|
||||
config.args['valueInput'] = config.args['value'];
|
||||
delete config.args?.value;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取动作配置
|
||||
const actionConfig: any = getAcionConfig(
|
||||
action,
|
||||
actionTree,
|
||||
pluginActions,
|
||||
commonActions
|
||||
);
|
||||
// 还原args为可视化配置结构(args + addOnArgs)
|
||||
if (config.args) {
|
||||
if (actionConfig?.config) {
|
||||
let tmpArgs = {};
|
||||
config.addOnArgs = [];
|
||||
Object.keys(config.args).forEach(key => {
|
||||
// 筛选出附加配置参数
|
||||
if (!actionConfig?.config.includes(key)) {
|
||||
config.addOnArgs = [
|
||||
...config.addOnArgs,
|
||||
{
|
||||
key: key,
|
||||
val: config.args?.[key]
|
||||
}
|
||||
];
|
||||
} else {
|
||||
tmpArgs = {
|
||||
...tmpArgs,
|
||||
[key]: config.args?.[key]
|
||||
};
|
||||
}
|
||||
});
|
||||
config.args = tmpArgs;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取左侧命中的动作节点
|
||||
const hasSubActionNode = findHasSubActionNode(actionTree, action.actionType);
|
||||
const actionType = getActionType(action, hasSubActionNode);
|
||||
|
||||
return {
|
||||
...config,
|
||||
actionType,
|
||||
__cmptTreeSource: getComponentTreeSource(
|
||||
actionType!,
|
||||
pluginActions,
|
||||
getComponents,
|
||||
commonActions
|
||||
),
|
||||
__cmptActionType:
|
||||
hasSubActionNode || action.componentId ? action.actionType : '',
|
||||
__actionDesc: action.__actionDesc ?? hasSubActionNode?.desc ?? actionConfig.schema, // 树节点描述
|
||||
__actionSchema: action.__actionSchema ?? hasSubActionNode?.schema ?? actionConfig.schema, // 树节点schema
|
||||
__subActions: hasSubActionNode?.actions // 树节点子动作
|
||||
// broadcastId: action.actionType === 'broadcast' ? action.eventName : ''
|
||||
};
|
||||
};
|
||||
|
||||
// 渲染组件选择配置项
|
||||
export function renderCmptSelect(
|
||||
componentLabel: string,
|
||||
required: boolean,
|
||||
onChange?: (value: string, oldVal: any, data: any, form: any) => void
|
||||
) {
|
||||
return [
|
||||
{
|
||||
type: 'tree-select',
|
||||
name: 'componentId',
|
||||
label: componentLabel,
|
||||
showIcon: false,
|
||||
searchable: true,
|
||||
required,
|
||||
selfDisabledAffectChildren: false,
|
||||
size: 'lg',
|
||||
source: '${__cmptTreeSource}',
|
||||
mode: 'horizontal',
|
||||
autoFill: {
|
||||
__rendererLabel: '${label}',
|
||||
__rendererName: '${type}',
|
||||
__nodeId: '${id}',
|
||||
__nodeSchema: '${schema}'
|
||||
},
|
||||
onChange: async (value: string, oldVal: any, data: any, form: any) => {
|
||||
onChange?.(value, oldVal, data, form);
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// 渲染组件特性动作配置项
|
||||
export function renderCmptActionSelect(
|
||||
componentLabel: string,
|
||||
required: boolean,
|
||||
onChange?: (value: string, oldVal: any, data: any, form: any) => void
|
||||
) {
|
||||
return [
|
||||
...renderCmptSelect(
|
||||
'选择组件',
|
||||
true,
|
||||
async (value: string, oldVal: any, data: any, form: any) => {
|
||||
// 获取组件上下文
|
||||
if (form.data.__nodeId) {
|
||||
const dataSchema: any = await form.data.getContextSchemas?.(
|
||||
form.data.__nodeId,
|
||||
true
|
||||
);
|
||||
const dataSchemaIns = new DataSchema(dataSchema || []);
|
||||
const variables = dataSchemaIns?.getDataPropsAsOptions() || [];
|
||||
|
||||
form.setValueByName('__cmptDataSchema', dataSchema);
|
||||
form.setValueByName('__cmptVariables', variables); // 组件上下文(不含父级)
|
||||
form.setValueByName('__cmptVariablesWithSys', [
|
||||
// 组件上下文+页面+系统
|
||||
{
|
||||
label: `${form.data.__rendererLabel}变量`,
|
||||
children: variables
|
||||
},
|
||||
...form.data.rawVariables.filter((item: ContextVariables) =>
|
||||
['页面变量', '系统变量'].includes(item.label)
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
if (form.data.actionType === 'setValue') {
|
||||
// todo:这里会闪一下,需要从amis查下问题
|
||||
form.setValueByName('args.value', undefined);
|
||||
form.setValueByName('args.valueInput', undefined);
|
||||
}
|
||||
form.setValueByName('__cmptActionType', '');
|
||||
|
||||
onChange?.(value, oldVal, data, form);
|
||||
}
|
||||
),
|
||||
{
|
||||
asFormItem: true,
|
||||
label: '组件动作',
|
||||
name: '__cmptActionType',
|
||||
mode: 'horizontal',
|
||||
required: true,
|
||||
visibleOn: 'data.actionType === "component"',
|
||||
component: CmptActionSelect,
|
||||
description: '${__cmptActionDesc}'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// 表单项组件
|
||||
export const FORMITEM_CMPTS = [
|
||||
'button-group-select',
|
||||
@ -449,13 +95,22 @@ export const FORMITEM_CMPTS = [
|
||||
'uuid'
|
||||
];
|
||||
|
||||
export const getArgsWrapper = (items: any, multiple: boolean = false) => ({
|
||||
type: 'combo',
|
||||
name: 'args',
|
||||
// label: '动作参数',
|
||||
multiple,
|
||||
strictMode: false,
|
||||
items: Array.isArray(items) ? items : [items]
|
||||
});
|
||||
|
||||
// 动作配置项schema map
|
||||
export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
[propName: string]: RendererPluginAction;
|
||||
} = {
|
||||
setValue: {
|
||||
config: ['value', 'valueInput'],
|
||||
desc: (info: any) => {
|
||||
innerArgs: ['value', 'valueInput'],
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
设置
|
||||
@ -566,7 +221,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
})
|
||||
},
|
||||
reload: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
刷新
|
||||
@ -579,7 +234,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
clear: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -589,7 +244,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
reset: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -599,7 +254,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
submit: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -610,7 +265,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
validate: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -620,7 +275,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
prev: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -631,7 +286,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
next: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -642,7 +297,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
collapse: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -652,7 +307,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
selectAll: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -662,7 +317,7 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
focus: {
|
||||
desc: (info: any) => {
|
||||
descDetail: (info: any) => {
|
||||
return (
|
||||
<div>
|
||||
<span className="variable-right">{info?.__rendererLabel}</span>
|
||||
@ -672,12 +327,192 @@ export const COMMON_ACTION_SCHEMA_MAP: {
|
||||
}
|
||||
},
|
||||
refresh: {
|
||||
desc: (info: any) => <div>刷新页面</div>
|
||||
descDetail: (info: any) => <div>刷新页面</div>
|
||||
},
|
||||
alert: {
|
||||
desc: (info: any) => <div>打开提示对话框</div>
|
||||
descDetail: (info: any) => <div>打开提示对话框</div>
|
||||
},
|
||||
confirm: {
|
||||
desc: (info: any) => <div>打开确认对话框</div>
|
||||
descDetail: (info: any) => <div>打开确认对话框</div>
|
||||
}
|
||||
};
|
||||
|
||||
// 获取动作树中指定的动作
|
||||
export const findActionNode = (
|
||||
actions: RendererPluginAction[],
|
||||
actionType: string
|
||||
) => findTree(actions, node => node.actionType === actionType);
|
||||
|
||||
// 获取包含指定子动作的动作
|
||||
export const findSubActionNode = (
|
||||
actions: RendererPluginAction[],
|
||||
actionType: string
|
||||
) =>
|
||||
findTree(actions, node =>
|
||||
node.actions?.find(
|
||||
(item: SubRendererPluginAction) => item.actionType === actionType
|
||||
)
|
||||
);
|
||||
|
||||
// 获取真实的动作类型
|
||||
export const getActionType = (
|
||||
action: ActionConfig,
|
||||
hasSubActionNode: RendererPluginAction | null
|
||||
) =>
|
||||
action.__isCmptAction
|
||||
? 'component'
|
||||
: hasSubActionNode
|
||||
? hasSubActionNode.actionType
|
||||
: action.actionType;
|
||||
|
||||
// 获取事件Label文案
|
||||
export const getEventLabel = (events: RendererPluginEvent[], name: string) =>
|
||||
events.find(item => item.eventName === name)?.eventLabel;
|
||||
|
||||
// 获取事件描述文案
|
||||
export const getEventDesc = (events: RendererPluginEvent[], name: string) =>
|
||||
events.find(item => item.eventName === name)?.description;
|
||||
|
||||
// 判断插件动作中是否存在指定动作
|
||||
export const hasActionType = (actionType: string, actions?: RendererPluginAction[]) => {
|
||||
if (!Array.isArray(actions)) {
|
||||
return false;
|
||||
}
|
||||
return !!actions?.find(item =>
|
||||
[item.actionType, 'component'].includes(actionType)
|
||||
);
|
||||
};
|
||||
|
||||
// 获取动作配置,主要是为了获取config和desc,schema强制捆绑在动作树节点(动作配置可能在插件动作中 > 树节点 or 子动作)
|
||||
export const getPropOfAcion = (
|
||||
action: ActionConfig,
|
||||
propName: string,
|
||||
actionTree: RendererPluginAction[],
|
||||
pluginActions: PluginActions,
|
||||
commonActions?: {[propName: string]: RendererPluginAction}
|
||||
): any => {
|
||||
let prop: any = null;
|
||||
if (action.componentId) {
|
||||
// 优先从组件特性动作中找
|
||||
pluginActions[action.__rendererName]?.find(
|
||||
(item: RendererPluginAction) => item.actionType === action.actionType
|
||||
)?.[propName as keyof RendererPluginAction];
|
||||
}
|
||||
|
||||
if (!prop) {
|
||||
prop = findActionNode(actionTree, action.actionType)?.[
|
||||
propName as keyof RendererPluginAction
|
||||
];
|
||||
}
|
||||
|
||||
if (!prop) {
|
||||
const commonActionConfig = {
|
||||
...COMMON_ACTION_SCHEMA_MAP,
|
||||
...commonActions
|
||||
};
|
||||
const hasSubActionNode = findSubActionNode(actionTree, action.actionType);
|
||||
|
||||
if (propName === 'actionLabel') {
|
||||
prop = hasSubActionNode?.actionLabel;
|
||||
}
|
||||
else {
|
||||
prop =
|
||||
hasSubActionNode?.actions?.find(
|
||||
(item: SubRendererPluginAction) => item.actionType === action.actionType
|
||||
)?.[propName as keyof SubRendererPluginAction] ??
|
||||
commonActionConfig[action.actionType]?.[
|
||||
propName as keyof RendererPluginAction
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return prop;
|
||||
};
|
||||
|
||||
// 渲染组件选择配置项
|
||||
export function renderCmptSelect(
|
||||
componentLabel: string,
|
||||
required: boolean,
|
||||
onChange?: (value: string, oldVal: any, data: any, form: any) => void
|
||||
) {
|
||||
return [
|
||||
{
|
||||
type: 'tree-select',
|
||||
name: 'componentId',
|
||||
label: componentLabel,
|
||||
showIcon: false,
|
||||
searchable: true,
|
||||
required,
|
||||
selfDisabledAffectChildren: false,
|
||||
size: 'lg',
|
||||
source: '${__cmptTreeSource}',
|
||||
mode: 'horizontal',
|
||||
autoFill: {
|
||||
__rendererLabel: '${label}',
|
||||
__rendererName: '${type}',
|
||||
__nodeId: '${id}',
|
||||
__nodeSchema: '${schema}'
|
||||
},
|
||||
onChange: async (value: string, oldVal: any, data: any, form: any) => {
|
||||
onChange?.(value, oldVal, data, form);
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
// 渲染组件特性动作配置项
|
||||
export function renderCmptActionSelect(
|
||||
componentLabel: string,
|
||||
required: boolean,
|
||||
onChange?: (value: string, oldVal: any, data: any, form: any) => void
|
||||
) {
|
||||
return [
|
||||
...renderCmptSelect(
|
||||
'选择组件',
|
||||
true,
|
||||
async (value: string, oldVal: any, data: any, form: any) => {
|
||||
// 获取组件上下文
|
||||
if (form.data.__nodeId) {
|
||||
const dataSchema: any = await form.data.getContextSchemas?.(
|
||||
form.data.__nodeId,
|
||||
true
|
||||
);
|
||||
const dataSchemaIns = new DataSchema(dataSchema || []);
|
||||
const variables = dataSchemaIns?.getDataPropsAsOptions() || [];
|
||||
|
||||
form.setValueByName('__cmptDataSchema', dataSchema);
|
||||
form.setValueByName('__cmptVariables', variables); // 组件上下文(不含父级)
|
||||
form.setValueByName('__cmptVariablesWithSys', [
|
||||
// 组件上下文+页面+系统
|
||||
{
|
||||
label: `${form.data.__rendererLabel}变量`,
|
||||
children: variables
|
||||
},
|
||||
...form.data.rawVariables.filter((item: ContextVariables) =>
|
||||
['页面变量', '系统变量'].includes(item.label)
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
if (form.data.actionType === 'setValue') {
|
||||
// todo:这里会闪一下,需要从amis查下问题
|
||||
form.setValueByName('args.value', undefined);
|
||||
form.setValueByName('args.valueInput', undefined);
|
||||
}
|
||||
form.setValueByName('__cmptActionType', '');
|
||||
|
||||
onChange?.(value, oldVal, data, form);
|
||||
}
|
||||
),
|
||||
{
|
||||
asFormItem: true,
|
||||
label: '组件动作',
|
||||
name: '__cmptActionType',
|
||||
mode: 'horizontal',
|
||||
required: true,
|
||||
visibleOn: 'data.actionType === "component"',
|
||||
component: CmptActionSelect,
|
||||
description: '${__cmptActionDesc}'
|
||||
}
|
||||
];
|
||||
}
|
||||
|
@ -3,22 +3,16 @@ import {findDOMNode} from 'react-dom';
|
||||
import cx from 'classnames';
|
||||
import Sortable from 'sortablejs';
|
||||
import {DataSchema, FormItem, Icon, TooltipWrapper} from 'amis';
|
||||
import {
|
||||
FormControlProps,
|
||||
autobind,
|
||||
render as amisRender
|
||||
} from 'amis-core';
|
||||
import {FormControlProps, autobind, render as amisRender} from 'amis-core';
|
||||
|
||||
import {BASE_ACTION_PROPS} from './comp-action-select';
|
||||
import ActionConfigPanel from './action-config-panel';
|
||||
import {
|
||||
findHasSubActionNode,
|
||||
formatActionInitConfig,
|
||||
getAcionConfig,
|
||||
getActionLabel,
|
||||
getComponentTreeSource,
|
||||
findActionNode,
|
||||
findSubActionNode,
|
||||
getEventDesc,
|
||||
getEventLabel
|
||||
getEventLabel,
|
||||
getPropOfAcion
|
||||
} from './helper';
|
||||
import {
|
||||
ActionConfig,
|
||||
@ -30,7 +24,8 @@ import {
|
||||
PluginActions,
|
||||
PluginEvents,
|
||||
RendererPluginAction,
|
||||
RendererPluginEvent
|
||||
RendererPluginEvent,
|
||||
SubRendererPluginAction
|
||||
} from 'amis-editor-core';
|
||||
|
||||
interface EventControlProps extends FormControlProps {
|
||||
@ -46,8 +41,10 @@ interface EventControlProps extends FormControlProps {
|
||||
) => void;
|
||||
addBroadcast?: (event: RendererPluginEvent) => void;
|
||||
removeBroadcast?: (eventName: string) => void;
|
||||
getComponents: () => ComponentInfo[]; // 当前页面组件树
|
||||
getComponents: (action: RendererPluginAction) => ComponentInfo[]; // 当前页面组件树
|
||||
getContextSchemas?: (id?: string, withoutSuper?: boolean) => DataSchema; // 获取上下文
|
||||
actionConfigInitFormatter?: (actionConfig: ActionConfig) => ActionConfig; // 动作配置初始化时格式化
|
||||
actionConfigSubmitFormatter?: (actionConfig: ActionConfig) => ActionConfig; // 动作配置提交时格式化
|
||||
owner?: string; // 组件标识
|
||||
}
|
||||
|
||||
@ -67,6 +64,11 @@ interface EventControlState {
|
||||
pluginActions: PluginActions;
|
||||
getContextSchemas?: (id?: string, withoutSuper?: boolean) => DataSchema;
|
||||
rawVariables: ContextVariables[];
|
||||
__cmptActionType?: string;
|
||||
__actionDesc?: string;
|
||||
__cmptTreeSource?: ComponentInfo[],
|
||||
__actionSchema?: any;
|
||||
__subActions?: SubRendererPluginAction[]
|
||||
}
|
||||
| undefined;
|
||||
type: 'update' | 'add';
|
||||
@ -425,9 +427,9 @@ export class EventControl extends React.Component<
|
||||
const {
|
||||
actions: pluginActions,
|
||||
getContextSchemas,
|
||||
actionTree,
|
||||
commonActions,
|
||||
getComponents
|
||||
actionConfigInitFormatter,
|
||||
getComponents,
|
||||
actionTree
|
||||
} = this.props;
|
||||
const {events, rawVariables} = this.state;
|
||||
|
||||
@ -454,6 +456,10 @@ export class EventControl extends React.Component<
|
||||
|
||||
// 编辑操作,需要格式化动作配置
|
||||
if (data.type === 'update') {
|
||||
const action = data.actionData!.action!;
|
||||
const actionConfig = actionConfigInitFormatter?.(action);
|
||||
const actionNode = findActionNode(actionTree, actionConfig?.actionType!);
|
||||
const hasSubActionNode = findSubActionNode(actionTree, action.actionType);
|
||||
data.actionData = {
|
||||
eventKey: data.actionData!.eventKey,
|
||||
actionIndex: data.actionData!.actionIndex,
|
||||
@ -461,13 +467,14 @@ export class EventControl extends React.Component<
|
||||
pluginActions,
|
||||
getContextSchemas,
|
||||
rawVariables,
|
||||
...formatActionInitConfig(
|
||||
data.actionData!.action!,
|
||||
actionTree,
|
||||
pluginActions,
|
||||
getComponents,
|
||||
commonActions
|
||||
)
|
||||
...actionConfig,
|
||||
__cmptTreeSource: getComponents?.(actionNode!) ?? [],
|
||||
__cmptActionType:
|
||||
hasSubActionNode || action.componentId ? action.actionType : '',
|
||||
__actionDesc: actionNode!.description!, // 树节点描述
|
||||
__actionSchema: actionNode!.schema, // 树节点schema
|
||||
__subActions: hasSubActionNode?.actions // 树节点子动作
|
||||
// broadcastId: action.actionType === 'broadcast' ? action.eventName : ''
|
||||
};
|
||||
} else {
|
||||
data.actionData = {
|
||||
@ -484,17 +491,14 @@ export class EventControl extends React.Component<
|
||||
|
||||
// 渲染描述信息
|
||||
renderDesc(action: ActionConfig) {
|
||||
const {
|
||||
actions: pluginActions,
|
||||
actionTree,
|
||||
commonActions
|
||||
} = this.props;
|
||||
const desc = getAcionConfig(
|
||||
const {actions: pluginActions, actionTree, commonActions} = this.props;
|
||||
const desc = getPropOfAcion(
|
||||
action,
|
||||
'descDetail',
|
||||
actionTree,
|
||||
pluginActions,
|
||||
commonActions
|
||||
)?.desc;
|
||||
);
|
||||
|
||||
return typeof desc === 'function' ? (
|
||||
<div className="action-control-content">{desc?.(action) || '-'}</div>
|
||||
@ -591,19 +595,16 @@ export class EventControl extends React.Component<
|
||||
__cmptActionType = 'enabled';
|
||||
}
|
||||
|
||||
const action = data.selectedOptions[0];
|
||||
|
||||
form.setValues({
|
||||
...removeKeys,
|
||||
__cmptTreeSource: getComponentTreeSource(
|
||||
value,
|
||||
pluginActions,
|
||||
getComponents,
|
||||
commonActions
|
||||
),
|
||||
__cmptActionType,
|
||||
componentId: form.data.componentId ? '' : undefined,
|
||||
__actionDesc: data.selectedOptions[0].description,
|
||||
__actionSchema: data.selectedOptions[0].schema,
|
||||
__subActions: data.selectedOptions[0].actions
|
||||
__cmptTreeSource: getComponents?.(action) ?? [],
|
||||
__cmptActionType,
|
||||
__actionDesc: action.description,
|
||||
__actionSchema: action.schema,
|
||||
__subActions: action.actions
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -681,78 +682,9 @@ export class EventControl extends React.Component<
|
||||
}
|
||||
|
||||
submitConfig(type: string, config: any) {
|
||||
const {actionTree} = this.props;
|
||||
const {actionConfigSubmitFormatter} = this.props;
|
||||
const action = actionConfigSubmitFormatter?.(config) ?? config;
|
||||
|
||||
let action = {...config};
|
||||
|
||||
// 修正动作名称
|
||||
if (config.actionType === 'component') {
|
||||
// 标记一下组件特性动作
|
||||
action.__isCmptAction = true;
|
||||
action.actionType = config.__cmptActionType;
|
||||
}
|
||||
const hasSubActionNode = findHasSubActionNode(
|
||||
actionTree,
|
||||
config.__cmptActionType
|
||||
);
|
||||
if (hasSubActionNode) {
|
||||
// 修正动作
|
||||
action.actionType = config.__cmptActionType;
|
||||
}
|
||||
action.__label = getActionLabel(actionTree, config.actionType);
|
||||
|
||||
// 合并附加的动作参数
|
||||
if (config.addOnArgs) {
|
||||
config.addOnArgs.forEach((args: any) => {
|
||||
action.args = action.args ?? {};
|
||||
action.args = {
|
||||
...action.args,
|
||||
[args.key]: args.val
|
||||
};
|
||||
});
|
||||
delete action.addOnArgs;
|
||||
}
|
||||
// 转换下格式
|
||||
if (['setValue', 'url', 'link'].includes(action.actionType)) {
|
||||
const prop = action.actionType === 'setValue' ? 'value' : 'params';
|
||||
|
||||
if (Array.isArray(config.args[prop])) {
|
||||
action.args = action.args ?? {};
|
||||
if (action.__rendererName === 'combo') {
|
||||
// combo特殊处理
|
||||
let tempArr: any = [];
|
||||
config.args?.[prop].forEach((valueItem: any, index: number) => {
|
||||
valueItem.item.forEach((item: any) => {
|
||||
if (!tempArr[index]) {
|
||||
tempArr[index] = {};
|
||||
}
|
||||
tempArr[index][item.key] = item.val;
|
||||
});
|
||||
});
|
||||
action.args = {
|
||||
...action.args,
|
||||
[prop]: tempArr
|
||||
};
|
||||
} else {
|
||||
let tmpObj: any = {};
|
||||
config.args[prop].forEach((item: any) => {
|
||||
tmpObj[item.key] = item.val;
|
||||
});
|
||||
action.args = {
|
||||
...action.args,
|
||||
[prop]: tmpObj
|
||||
};
|
||||
}
|
||||
} else if (action.actionType === 'setValue') {
|
||||
// 处理变量赋值非数组的情况
|
||||
action.args = {
|
||||
...action.args,
|
||||
value: config.args['valueInput']
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
delete action.config;
|
||||
if (type === 'add') {
|
||||
this.addAction(config.eventKey, action);
|
||||
} else if (type === 'update') {
|
||||
@ -763,6 +695,7 @@ export class EventControl extends React.Component<
|
||||
}
|
||||
|
||||
render() {
|
||||
const {actionTree, actions: pluginActions, commonActions} = this.props;
|
||||
const {
|
||||
onEvent,
|
||||
events,
|
||||
@ -868,7 +801,7 @@ export class EventControl extends React.Component<
|
||||
/>
|
||||
</div>
|
||||
<div className="action-item-actiontype">
|
||||
{action.__label || action.actionType}
|
||||
{getPropOfAcion(action, 'actionLabel', actionTree, pluginActions, commonActions) || action.actionType}
|
||||
</div>
|
||||
</div>
|
||||
<div className="action-control-header-right">
|
||||
|
@ -1,6 +1,20 @@
|
||||
import {BaseEventContext, EditorManager} from 'amis-editor-core';
|
||||
import {mapTree} from 'amis';
|
||||
import {
|
||||
BaseEventContext,
|
||||
EditorManager,
|
||||
RendererPluginAction
|
||||
} from 'amis-editor-core';
|
||||
import {filterTree, mapTree} from 'amis';
|
||||
import ACTION_TYPE_TREE from './renderer/event-control/actions';
|
||||
import {ActionConfig, ComponentInfo} from './renderer/event-control/types';
|
||||
import {
|
||||
COMMON_ACTION_SCHEMA_MAP,
|
||||
findActionNode,
|
||||
findSubActionNode,
|
||||
FORMITEM_CMPTS,
|
||||
getActionType,
|
||||
getPropOfAcion,
|
||||
hasActionType
|
||||
} from './renderer/event-control/helper';
|
||||
|
||||
/**
|
||||
* 获取事件动作面板所需属性配置
|
||||
@ -8,45 +22,253 @@ import ACTION_TYPE_TREE from './renderer/event-control/actions';
|
||||
export const getEventControlConfig = (
|
||||
manager: EditorManager,
|
||||
context: BaseEventContext
|
||||
) => ({
|
||||
actions: manager?.pluginActions,
|
||||
events: manager?.pluginEvents,
|
||||
getContextSchemas: async (id?: string, withoutSuper?: boolean) => {
|
||||
const dataSchema = await manager.getContextSchemas(
|
||||
id ?? context!.id,
|
||||
withoutSuper
|
||||
);
|
||||
// 存在指定id时,只需要当前层上下文
|
||||
if (id) {
|
||||
return dataSchema;
|
||||
}
|
||||
return manager.dataSchema;
|
||||
},
|
||||
getComponents: () =>
|
||||
mapTree(
|
||||
manager?.store?.outline ?? [],
|
||||
(item: any) => {
|
||||
const schema = manager?.store?.getSchema(item.id);
|
||||
return {
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
value: schema.id || item.id,
|
||||
type: schema.type,
|
||||
schema,
|
||||
disabled: !!item.region,
|
||||
children: item?.children
|
||||
};
|
||||
},
|
||||
1,
|
||||
true
|
||||
),
|
||||
actionTree: manager?.config.actionOptions?.actionTreeGetter
|
||||
) => {
|
||||
// 通用动作配置
|
||||
const commonActions =
|
||||
manager?.config.actionOptions?.customActionGetter?.(manager);
|
||||
// 动作树
|
||||
const actionTree = manager?.config.actionOptions?.actionTreeGetter
|
||||
? manager?.config.actionOptions?.actionTreeGetter(ACTION_TYPE_TREE(manager))
|
||||
: ACTION_TYPE_TREE(manager),
|
||||
commonActions: {
|
||||
...manager?.config.actionOptions?.customActionGetter?.(manager)
|
||||
},
|
||||
owner: '',
|
||||
addBroadcast: manager?.addBroadcast,
|
||||
removeBroadcast: manager?.removeBroadcast
|
||||
});
|
||||
: ACTION_TYPE_TREE(manager);
|
||||
const commonActionConfig = {
|
||||
...COMMON_ACTION_SCHEMA_MAP,
|
||||
...commonActions
|
||||
};
|
||||
return {
|
||||
actions: manager?.pluginActions,
|
||||
events: manager?.pluginEvents,
|
||||
actionTree,
|
||||
commonActions,
|
||||
owner: '',
|
||||
addBroadcast: manager?.addBroadcast,
|
||||
removeBroadcast: manager?.removeBroadcast,
|
||||
getContextSchemas: async (id?: string, withoutSuper?: boolean) => {
|
||||
const dataSchema = await manager.getContextSchemas(
|
||||
id ?? context!.id,
|
||||
withoutSuper
|
||||
);
|
||||
// 存在指定id时,只需要当前层上下文
|
||||
if (id) {
|
||||
return dataSchema;
|
||||
}
|
||||
return manager.dataSchema;
|
||||
},
|
||||
getComponents: (action: RendererPluginAction) => {
|
||||
const components = mapTree(
|
||||
manager?.store?.outline ?? [],
|
||||
(item: any) => {
|
||||
const schema = manager?.store?.getSchema(item.id);
|
||||
return {
|
||||
id: item.id,
|
||||
label: item.label,
|
||||
value: schema.id || item.id,
|
||||
type: schema.type,
|
||||
schema,
|
||||
disabled: !!item.region,
|
||||
children: item?.children
|
||||
};
|
||||
},
|
||||
1,
|
||||
true
|
||||
);
|
||||
|
||||
const actionType = action.actionType!;
|
||||
const loopChildren = (nodes: ComponentInfo[]) => {
|
||||
const temp: ComponentInfo[] = [];
|
||||
for (let node of nodes) {
|
||||
const actions = manager?.pluginActions[node.type];
|
||||
let isSupport = false;
|
||||
if (typeof action.supportComponents === 'string') {
|
||||
isSupport = action.supportComponents === '*' || action.supportComponents === node.type;
|
||||
}
|
||||
else if (Array.isArray(action.supportComponents)) {
|
||||
isSupport = action.supportComponents.includes(node.type);
|
||||
}
|
||||
else {
|
||||
isSupport = hasActionType(actionType, actions);
|
||||
}
|
||||
if (isSupport) {
|
||||
// 组件特性动作,如果当前组件没有动作,则禁用
|
||||
const disabled =
|
||||
actionType === 'component' && (!actions || !actions.length);
|
||||
const newNode: ComponentInfo = {
|
||||
...node,
|
||||
disabled: disabled || node.disabled,
|
||||
children: []
|
||||
};
|
||||
if (node.children?.length) {
|
||||
// 检查子项
|
||||
newNode.children?.push(...loopChildren(node.children));
|
||||
}
|
||||
temp.push(newNode);
|
||||
} else if (node.children?.length) {
|
||||
const childNodes = loopChildren(node.children);
|
||||
if (childNodes.length) {
|
||||
temp.push(...childNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
};
|
||||
|
||||
return loopChildren(components);
|
||||
},
|
||||
actionConfigInitFormatter: (action: ActionConfig) => {
|
||||
let config = {...action};
|
||||
|
||||
if (
|
||||
['setValue', 'url', 'link'].includes(action.actionType) &&
|
||||
action.args
|
||||
) {
|
||||
const prop = action.actionType === 'setValue' ? 'value' : 'params';
|
||||
!config.args && (config.args = {});
|
||||
if (Array.isArray(action.args[prop])) {
|
||||
config.args[prop] = action.args[prop].reduce(
|
||||
(arr: any, valueItem: any, index: number) => {
|
||||
if (!arr[index]) {
|
||||
arr[index] = {};
|
||||
}
|
||||
arr[index].item = Object.entries(valueItem).map(([key, val]) => ({
|
||||
key,
|
||||
val
|
||||
}));
|
||||
return arr;
|
||||
},
|
||||
[]
|
||||
);
|
||||
} else if (typeof action.args[prop] === 'object') {
|
||||
config.args[prop] = Object.keys(action.args[prop]).map(key => ({
|
||||
key,
|
||||
val: action.args?.[prop][key]
|
||||
}));
|
||||
} else if (
|
||||
action.actionType === 'setValue' &&
|
||||
typeof action.args[prop] === 'string'
|
||||
) {
|
||||
config.args['valueInput'] = config.args['value'];
|
||||
delete config.args?.value;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取动作专有配置参数
|
||||
const innerArgs: any = getPropOfAcion(
|
||||
action,
|
||||
'innerArgs',
|
||||
actionTree,
|
||||
manager.pluginActions,
|
||||
commonActions
|
||||
);
|
||||
|
||||
// 还原args为可视化配置结构(args + addOnArgs)
|
||||
if (config.args) {
|
||||
if (innerArgs?.config) {
|
||||
let tmpArgs = {};
|
||||
config.addOnArgs = [];
|
||||
Object.keys(config.args).forEach(key => {
|
||||
// 筛选出附加配置参数
|
||||
if (!innerArgs?.config.includes(key)) {
|
||||
config.addOnArgs = [
|
||||
...config.addOnArgs,
|
||||
{
|
||||
key: key,
|
||||
val: config.args?.[key]
|
||||
}
|
||||
];
|
||||
} else {
|
||||
tmpArgs = {
|
||||
...tmpArgs,
|
||||
[key]: config.args?.[key]
|
||||
};
|
||||
}
|
||||
});
|
||||
config.args = tmpArgs;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取左侧命中的动作节点
|
||||
const hasSubActionNode = findSubActionNode(actionTree, action.actionType);
|
||||
|
||||
return {
|
||||
...config,
|
||||
actionType: getActionType(action, hasSubActionNode)
|
||||
};
|
||||
},
|
||||
actionConfigSubmitFormatter: (config: ActionConfig) => {
|
||||
let action = {...config};
|
||||
action.__title = findActionNode(
|
||||
actionTree,
|
||||
config.actionType
|
||||
)?.actionLabel;
|
||||
|
||||
// 修正动作名称
|
||||
if (config.actionType === 'component') {
|
||||
// 标记一下组件特性动作
|
||||
action.__isCmptAction = true;
|
||||
action.actionType = config.__cmptActionType;
|
||||
}
|
||||
const hasSubActionNode = findSubActionNode(
|
||||
actionTree,
|
||||
config.__cmptActionType
|
||||
);
|
||||
if (hasSubActionNode) {
|
||||
// 修正动作
|
||||
action.actionType = config.__cmptActionType;
|
||||
}
|
||||
|
||||
// 合并附加的动作参数
|
||||
if (config.addOnArgs) {
|
||||
config.addOnArgs.forEach((args: any) => {
|
||||
action.args = action.args ?? {};
|
||||
action.args = {
|
||||
...action.args,
|
||||
[args.key]: args.val
|
||||
};
|
||||
});
|
||||
delete action.addOnArgs;
|
||||
}
|
||||
// 转换下格式
|
||||
if (['setValue', 'url', 'link'].includes(action.actionType)) {
|
||||
const propName = action.actionType === 'setValue' ? 'value' : 'params';
|
||||
|
||||
if (Array.isArray(config.args?.[propName])) {
|
||||
action.args = action.args ?? {};
|
||||
if (action.__rendererName === 'combo') {
|
||||
// combo特殊处理
|
||||
let tempArr: any = [];
|
||||
config.args?.[propName].forEach((valueItem: any, index: number) => {
|
||||
valueItem.item.forEach((item: any) => {
|
||||
if (!tempArr[index]) {
|
||||
tempArr[index] = {};
|
||||
}
|
||||
tempArr[index][item.key] = item.val;
|
||||
});
|
||||
});
|
||||
action.args = {
|
||||
...action.args,
|
||||
[propName]: tempArr
|
||||
};
|
||||
} else {
|
||||
let tmpObj: any = {};
|
||||
config.args?.[propName].forEach((item: any) => {
|
||||
tmpObj[item.key] = item.val;
|
||||
});
|
||||
action.args = {
|
||||
...action.args,
|
||||
[propName]: tmpObj
|
||||
};
|
||||
}
|
||||
} else if (action.actionType === 'setValue') {
|
||||
// 处理变量赋值非数组的情况
|
||||
action.args = {
|
||||
...action.args,
|
||||
value: config.args?.['valueInput']
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
delete action.config;
|
||||
|
||||
return action;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user