fastlion-amis
Version:
一种MIS页面生成工具
139 lines (117 loc) • 4.15 kB
text/typescript
import {extendObject} from '../utils/helper';
import {RendererEvent} from '../utils/renderer-event';
import {evalExpression} from '../utils/tpl';
import {dataMapping} from '../utils/tpl-builtin';
// 逻辑动作类型,支持并行、排他(switch)、循环(支持continue和break)
type LogicActionType = 'parallel' | 'switch' | 'loop' | 'continue' | 'break';
// 循环动作执行状态
export enum LoopStatus {
NORMAL,
BREAK,
CONTINUE
}
// 监听器动作定义
export interface ListenerAction {
actionType: 'broadcast' | LogicActionType | 'custom' | string; // 动作类型 逻辑动作|自定义(脚本支撑)|reload|url|ajax|dialog|drawer 其他扩充的组件动作
eventName?: string; // 事件名称,actionType: broadcast
description?: string; // 事件描述,actionType: broadcast
componentId?: string; // 组件ID,用于直接执行指定组件的动作
args?: any; // 参数,可以配置数据映射
preventDefault?: boolean; // 阻止原有组件的动作行为
stopPropagation?: boolean; // 阻止后续的事件处理器执行
execOn?: string; // 执行条件
script?: string; // 自定义JS,actionType: custom
[propName: string]: any; // 扩展各种Action
}
export interface LogicAction extends ListenerAction {
children?: ListenerAction[]; // 子动作
}
export interface ListenerContext {
[propName: string]: any;
}
// Action 基础接口
export interface Action {
// 运行这个 Action,每个类型的 Action 都只有一个实例,run 函数是个可重入的函数
run: (
action: ListenerAction,
renderer: ListenerContext,
event: RendererEvent<any>,
mergeData?: any // 有些Action内部需要通过上下文数据处理专有逻辑,这里的数据是事件数据+渲染器数据
) => Promise<void>;
}
// 存储 Action 和类型的映射关系,用于后续查找
const ActionTypeMap: {[key: string]: Action} = {};
// 注册 Action
export const registerAction = (type: string, action: Action) => {
ActionTypeMap[type] = action;
};
// 通过类型获取 Action 实例
export const getActionByType = (type: string) => {
return ActionTypeMap[type];
};
export const runActions = async (
actions: ListenerAction | ListenerAction[],
renderer: ListenerContext,
event: any
) => {
if (!Array.isArray(actions)) {
actions = [actions];
}
for (const actionConfig of actions) {
let actionInstrance = getActionByType(actionConfig.actionType);
// 如果存在指定组件ID,说明是组件专有动作
if (actionConfig.componentId) {
actionInstrance = getActionByType('component');
} else if (
actionConfig.actionType === 'url' ||
actionConfig.actionType === 'link' ||
actionConfig.actionType === 'jump'
) {
// 打开页面动作
actionInstrance = getActionByType('openpage');
}
// 找不到就通过组件专有动作完成
if (!actionInstrance) {
actionInstrance = getActionByType('component');
}
// 这些节点的子节点运行逻辑由节点内部实现
await runAction(actionInstrance, actionConfig, renderer, event);
if (event.stoped) {
break;
}
}
};
// 执行动作,与原有动作处理打通
export const runAction = async (
actionInstrance: Action,
actionConfig: ListenerAction,
renderer: ListenerContext,
event: any
) => {
// 用户可能,需要用到事件数据和当前域的数据,因此merge事件数据和当前渲染器数据
// 需要保持渲染器数据链完整
const mergeData = extendObject(renderer.props.data, {
event
});
if (actionConfig.execOn && !evalExpression(actionConfig.execOn, mergeData)) {
return;
}
// 修正参数,处理数据映射
let args = event.data;
if (actionConfig.args) {
args = dataMapping(actionConfig.args, mergeData);
}
await actionInstrance.run(
{
...actionConfig,
args
},
renderer,
event,
mergeData
);
// 阻止原有动作执行
actionConfig.preventDefault && event.preventDefault();
// 阻止后续动作执行
actionConfig.stopPropagation && event.stopPropagation();
};