mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-13 12:13:10 +00:00
161 lines
4.8 KiB
TypeScript
161 lines
4.8 KiB
TypeScript
import { ActivityType, IPublicTypeNodeSchema, IPublicTypeRootSchema } from '@alilc/lowcode-types';
|
||
import { isJSBlock, isJSSlot } from './check-types';
|
||
import { isVariable } from './misc';
|
||
import { isPlainObject } from './is-plain-object';
|
||
|
||
function isJsObject(props: any) {
|
||
if (typeof props === 'object' && props !== null) {
|
||
return props.type && props.source && props.compiled;
|
||
}
|
||
}
|
||
function isActionRef(props: any): boolean {
|
||
return props.type && props.type === 'actionRef';
|
||
}
|
||
|
||
/**
|
||
* 将「乐高版本」协议升级成 JSExpression / JSSlot 等标准协议的结构
|
||
* @param props
|
||
* @returns
|
||
*/
|
||
export function compatibleLegaoSchema(props: any): any {
|
||
if (!props) {
|
||
return props;
|
||
}
|
||
|
||
if (Array.isArray(props)) {
|
||
return props.map(k => compatibleLegaoSchema(k));
|
||
}
|
||
|
||
if (!isPlainObject(props)) {
|
||
return props;
|
||
}
|
||
|
||
if (isJSBlock(props)) {
|
||
if (props.value.componentName === 'Slot') {
|
||
return {
|
||
type: 'JSSlot',
|
||
title: (props.value.props as any)?.slotTitle,
|
||
name: (props.value.props as any)?.slotName,
|
||
value: compatibleLegaoSchema(props.value.children),
|
||
params: (props.value.props as any)?.slotParams,
|
||
};
|
||
} else {
|
||
return props.value;
|
||
}
|
||
}
|
||
if (isVariable(props)) {
|
||
return {
|
||
type: 'JSExpression',
|
||
value: props.variable,
|
||
mock: props.value,
|
||
};
|
||
}
|
||
if (isJsObject(props)) {
|
||
return {
|
||
type: 'JSExpression',
|
||
value: props.compiled,
|
||
extType: 'function',
|
||
};
|
||
}
|
||
if (isActionRef(props)) {
|
||
return {
|
||
type: 'JSExpression',
|
||
value: `${props.id}.bind(this)`,
|
||
};
|
||
}
|
||
const newProps: any = {};
|
||
Object.keys(props).forEach((key) => {
|
||
if (/^__slot__/.test(key) && props[key] === true) {
|
||
return;
|
||
}
|
||
// TODO: 先移除,目前没有业务使用
|
||
// if (key === 'dataSource') {
|
||
// newProps[key] = props[key];
|
||
// return;
|
||
// }
|
||
newProps[key] = compatibleLegaoSchema(props[key]);
|
||
});
|
||
return newProps;
|
||
}
|
||
|
||
export function getNodeSchemaById(schema: IPublicTypeNodeSchema, nodeId: string): IPublicTypeNodeSchema | undefined {
|
||
let found: IPublicTypeNodeSchema | undefined;
|
||
if (schema.id === nodeId) {
|
||
return schema;
|
||
}
|
||
const { children, props } = schema;
|
||
// 查找 children
|
||
if (Array.isArray(children)) {
|
||
for (const child of children) {
|
||
found = getNodeSchemaById(child as IPublicTypeNodeSchema, nodeId);
|
||
if (found) return found;
|
||
}
|
||
}
|
||
if (isPlainObject(props)) {
|
||
// 查找 props,主要是 slot 类型
|
||
found = getNodeSchemaFromPropsById(props, nodeId);
|
||
if (found) return found;
|
||
}
|
||
}
|
||
|
||
function getNodeSchemaFromPropsById(props: any, nodeId: string): IPublicTypeNodeSchema | undefined {
|
||
let found: IPublicTypeNodeSchema | undefined;
|
||
for (const [_key, value] of Object.entries(props)) {
|
||
if (isJSSlot(value)) {
|
||
// value 是数组类型 { type: 'JSSlot', value: IPublicTypeNodeSchema[] }
|
||
if (Array.isArray(value.value)) {
|
||
for (const child of value.value) {
|
||
found = getNodeSchemaById(child as IPublicTypeNodeSchema, nodeId);
|
||
if (found) return found;
|
||
}
|
||
}
|
||
// value 是对象类型 { type: 'JSSlot', value: IPublicTypeNodeSchema }
|
||
found = getNodeSchemaById(value.value as IPublicTypeNodeSchema, nodeId);
|
||
if (found) return found;
|
||
} else if (isPlainObject(value)) {
|
||
found = getNodeSchemaFromPropsById(value, nodeId);
|
||
if (found) return found;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* TODO: not sure if this is used anywhere
|
||
* @deprecated
|
||
*/
|
||
export function applyActivities(pivotSchema: IPublicTypeRootSchema, activities: any): IPublicTypeRootSchema {
|
||
let schema = { ...pivotSchema };
|
||
if (!Array.isArray(activities)) {
|
||
activities = [activities];
|
||
}
|
||
return activities.reduce((accSchema: IPublicTypeRootSchema, activity: any) => {
|
||
if (activity.type === ActivityType.MODIFIED) {
|
||
const found = getNodeSchemaById(accSchema, activity.payload.schema.id);
|
||
if (!found) return accSchema;
|
||
Object.assign(found, activity.payload.schema);
|
||
} else if (activity.type === ActivityType.ADDED) {
|
||
const { payload } = activity;
|
||
const { location, schema } = payload;
|
||
const { parent } = location;
|
||
const found = getNodeSchemaById(accSchema, parent.nodeId);
|
||
if (found) {
|
||
if (Array.isArray(found.children)) {
|
||
found.children.splice(parent.index, 0, schema);
|
||
} else if (!found.children) {
|
||
found.children = [schema];
|
||
}
|
||
// TODO: 是 JSExpression / DOMText
|
||
}
|
||
} else if (activity.type === ActivityType.DELETED) {
|
||
const { payload } = activity;
|
||
const { location } = payload;
|
||
const { parent } = location;
|
||
const found = getNodeSchemaById(accSchema, parent.nodeId);
|
||
if (found && Array.isArray(found.children)) {
|
||
found.children.splice(parent.index, 1);
|
||
}
|
||
}
|
||
return accSchema;
|
||
}, schema);
|
||
}
|