2022-03-11 11:24:45 +08:00

404 lines
8.1 KiB
TypeScript

import {
DocumentModel as InnerDocumentModel,
Node as InnerNode,
getConvertedExtraKey,
} from '@alilc/lowcode-designer';
import { CompositeValue, NodeSchema, TransformStage } from '@alilc/lowcode-types';
import Prop from './prop';
import Props from './props';
import DocumentModel from './document-model';
import NodeChildren from './node-children';
import ComponentMeta from './component-meta';
import { documentSymbol, nodeSymbol } from './symbols';
const shellNodeSymbol = Symbol('shellNodeSymbol');
export default class Node {
private readonly [documentSymbol]: InnerDocumentModel;
private readonly [nodeSymbol]: InnerNode;
constructor(node: InnerNode) {
this[nodeSymbol] = node;
this[documentSymbol] = node.document;
}
static create(node: InnerNode | null | undefined) {
if (!node) return null;
// @ts-ignore 直接返回已挂载的 shell node 实例
if (node[shellNodeSymbol]) return node[shellNodeSymbol];
const shellNode = new Node(node);
// @ts-ignore 挂载 shell node 实例
node[shellNodeSymbol] = shellNode;
return shellNode;
}
/**
* 节点 id
*/
get id() {
return this[nodeSymbol].id;
}
/**
* 节点标题
*/
get title() {
return this[nodeSymbol].title;
}
/**
* 是否为「容器型」节点
*/
get isContainer() {
return this[nodeSymbol].isContainer();
}
/**
* 是否为根节点
*/
get isRoot() {
return this[nodeSymbol].isRoot();
}
/**
* 是否为空节点(无 children 或者 children 为空)
*/
get isEmpty() {
return this[nodeSymbol].isEmpty();
}
/**
* 是否为 Page 节点
*/
get isPage() {
return this[nodeSymbol].isPage();
}
/**
* 是否为 Component 节点
*/
get isComponent() {
return this[nodeSymbol].isComponent();
}
/**
* 是否为「模态框」节点
*/
get isModal() {
return this[nodeSymbol].isModal();
}
/**
* 是否为插槽节点
*/
get isSlot() {
return this[nodeSymbol].isSlot();
}
/**
* 是否为父类/分支节点
*/
get isParental() {
return this[nodeSymbol].isParental();
}
/**
* 是否为叶子节点
*/
get isLeaf() {
return this[nodeSymbol].isLeaf();
}
/**
* 下标
*/
get index() {
return this[nodeSymbol].index;
}
/**
* 图标
*/
get icon() {
return this[nodeSymbol].icon;
}
/**
* 节点所在树的层级深度,根节点深度为 0
*/
get zLevel() {
return this[nodeSymbol].zLevel;
}
/**
* 节点 componentName
*/
get componentName() {
return this[nodeSymbol].componentName;
}
/**
* 节点的物料元数据
*/
get componentMeta() {
return ComponentMeta.create(this[nodeSymbol].componentMeta);
}
/**
* 获取节点所属的文档模型对象
* @returns
*/
get document() {
return DocumentModel.create(this[documentSymbol]);
}
/**
* 获取当前节点的前一个兄弟节点
* @returns
*/
get prevSibling(): Node | null {
return Node.create(this[nodeSymbol].prevSibling);
}
/**
* 获取当前节点的后一个兄弟节点
* @returns
*/
get nextSibling(): Node | null {
return Node.create(this[nodeSymbol].nextSibling);
}
/**
* 获取当前节点的父亲节点
* @returns
*/
get parent(): Node | null {
return Node.create(this[nodeSymbol].parent);
}
/**
* 获取当前节点的孩子节点模型
* @returns
*/
get children() {
return NodeChildren.create(this[nodeSymbol].children);
}
/**
* 节点上挂载的插槽节点们
*/
get slots(): Node[] {
return this[nodeSymbol].slots.map((node: InnerNode) => Node.create(node)!);
}
/**
* 当前节点为插槽节点时,返回节点对应的属性实例
*/
get slotFor() {
return Prop.create(this[nodeSymbol].slotFor);
}
/**
* 返回节点的属性集
*/
get props() {
return Props.create(this[nodeSymbol].props);
}
/**
* 返回节点的属性集
*/
get propsData() {
return this[nodeSymbol].propsData;
}
/**
* @deprecated use .children instead
*/
getChildren() {
return this.children;
}
/**
* 获取节点实例对应的 dom 节点
*/
getDOMNode() {
return this[nodeSymbol].getDOMNode();
}
/**
* 返回节点的尺寸、位置信息
* @returns
*/
getRect() {
return this[nodeSymbol].getRect();
}
/**
* 是否有挂载插槽节点
* @returns
*/
hasSlots() {
return this[nodeSymbol].hasSlots();
}
/**
* 是否设定了渲染条件
* @returns
*/
hasCondition() {
return this[nodeSymbol].hasCondition();
}
/**
* 是否设定了循环数据
* @returns
*/
hasLoop() {
return this[nodeSymbol].hasLoop();
}
/**
* @deprecated use .props instead
*/
getProps() {
return this.props;
}
/**
* 获取指定 path 的属性模型实例
* @param path 属性路径,支持 a / a.b / a.0 等格式
* @returns
*/
getProp(path: string): Prop | null {
return Prop.create(this[nodeSymbol].getProp(path));
}
/**
* 获取指定 path 的属性模型实例值
* @param path 属性路径,支持 a / a.b / a.0 等格式
* @returns
*/
getPropValue(path: string) {
return this.getProp(path)?.getValue();
}
/**
* 获取指定 path 的属性模型实例,
* 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级
* @param path 属性路径,支持 a / a.b / a.0 等格式
* @returns
*/
getExtraProp(path: string): Prop | null {
return Prop.create(this[nodeSymbol].getProp(getConvertedExtraKey(path)));
}
/**
* 获取指定 path 的属性模型实例,
* 注:导出时,不同于普通属性,该属性并不挂载在 props 之下,而是与 props 同级
* @param path 属性路径,支持 a / a.b / a.0 等格式
* @returns
*/
getExtraPropValue(path: string) {
return this.getExtraProp(path)?.getValue();
}
/**
* 设置指定 path 的属性模型实例值
* @param path 属性路径,支持 a / a.b / a.0 等格式
* @param value 值
* @returns
*/
setPropValue(path: string, value: CompositeValue) {
return this.getProp(path)?.setValue(value);
}
/**
* 设置指定 path 的属性模型实例值
* @param path 属性路径,支持 a / a.b / a.0 等格式
* @param value 值
* @returns
*/
setExtraPropValue(path: string, value: CompositeValue) {
return this.getExtraProp(path)?.setValue(value);
}
/**
* 导入节点数据
* @param data
*/
importSchema(data: NodeSchema) {
this[nodeSymbol].import(data);
}
/**
* 导出节点数据
* @param stage
* @param options
* @returns
*/
exportSchema(stage: TransformStage = TransformStage.Render, options?: any) {
return this[nodeSymbol].export(stage, options);
}
/**
* 在指定位置之前插入一个节点
* @param node
* @param ref
* @param useMutator
*/
insertBefore(node: Node, ref?: Node | undefined, useMutator?: boolean) {
this[nodeSymbol].insertBefore(node[nodeSymbol] || node, ref?.[nodeSymbol], useMutator);
}
/**
* 在指定位置之后插入一个节点
* @param node
* @param ref
* @param useMutator
*/
insertAfter(node: Node, ref?: Node | undefined, useMutator?: boolean) {
this[nodeSymbol].insertAfter(node[nodeSymbol] || node, ref?.[nodeSymbol], useMutator);
}
/**
* 替换指定节点
* @param node 待替换的子节点
* @param data 用作替换的节点对象或者节点描述
* @returns
*/
replaceChild(node: Node, data: any) {
return Node.create(this[nodeSymbol].replaceChild(node[nodeSymbol], data));
}
/**
* 将当前节点替换成指定节点描述
* @param schema
*/
replaceWith(schema: NodeSchema) {
this[nodeSymbol].replaceWith(schema);
}
/**
* 选中当前节点实例
*/
select() {
this[nodeSymbol].select();
}
/**
* 设置悬停态
* @param flag
*/
hover(flag = true) {
this[nodeSymbol].hover(flag);
}
/**
* 删除当前节点实例
*/
remove() {
this[nodeSymbol].remove();
}
}