mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-19 22:58:15 +00:00
feat: 大纲树支持模态视图
This commit is contained in:
parent
353fb10e21
commit
3785e1c171
@ -10,7 +10,7 @@ import { Selection } from './selection';
|
|||||||
import { History } from './history';
|
import { History } from './history';
|
||||||
import { TransformStage } from './node';
|
import { TransformStage } from './node';
|
||||||
import { uniqueId } from '@ali/lowcode-utils';
|
import { uniqueId } from '@ali/lowcode-utils';
|
||||||
import ModalNodesManager from './node/modalNodesManager';
|
import { ModalNodesManager } from './node';
|
||||||
|
|
||||||
export type GetDataType<T, NodeType> = T extends undefined
|
export type GetDataType<T, NodeType> = T extends undefined
|
||||||
? NodeType extends {
|
? NodeType extends {
|
||||||
@ -37,6 +37,10 @@ export class DocumentModel {
|
|||||||
* 操作记录控制
|
* 操作记录控制
|
||||||
*/
|
*/
|
||||||
readonly history: History;
|
readonly history: History;
|
||||||
|
/**
|
||||||
|
* 模态节点管理
|
||||||
|
*/
|
||||||
|
readonly modalNodesManager: ModalNodesManager;
|
||||||
|
|
||||||
private nodesMap = new Map<string, Node>();
|
private nodesMap = new Map<string, Node>();
|
||||||
@obx.val private nodes = new Set<Node>();
|
@obx.val private nodes = new Set<Node>();
|
||||||
@ -44,7 +48,6 @@ export class DocumentModel {
|
|||||||
private _simulator?: ISimulatorHost;
|
private _simulator?: ISimulatorHost;
|
||||||
private emitter: EventEmitter;
|
private emitter: EventEmitter;
|
||||||
private rootNodeVisitorMap: { [visitorName: string]: any } = {};
|
private rootNodeVisitorMap: { [visitorName: string]: any } = {};
|
||||||
private modalNodesManager: ModalNodesManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模拟器
|
* 模拟器
|
||||||
|
|||||||
@ -5,3 +5,4 @@ export * from './props/prop';
|
|||||||
export * from './props/prop-stash';
|
export * from './props/prop-stash';
|
||||||
export * from './props/props';
|
export * from './props/props';
|
||||||
export * from './transform-stage';
|
export * from './transform-stage';
|
||||||
|
export * from './modal-nodes-manager';
|
||||||
|
|||||||
@ -17,11 +17,11 @@ function getModalNodes(node: Node) {
|
|||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ModalNodesManager {
|
export class ModalNodesManager {
|
||||||
public willDestroy: any;
|
public willDestroy: any;
|
||||||
|
|
||||||
private page: DocumentModel;
|
private page: DocumentModel;
|
||||||
private modalNodes: [Node];
|
private modalNodes: Node[];
|
||||||
private nodeRemoveEvents: any;
|
private nodeRemoveEvents: any;
|
||||||
private emitter: EventEmitter;
|
private emitter: EventEmitter;
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ export default class ModalNodesManager {
|
|||||||
public getVisibleModalNode() {
|
public getVisibleModalNode() {
|
||||||
const visibleNode = this.modalNodes
|
const visibleNode = this.modalNodes
|
||||||
? this.modalNodes.find((node: Node) => {
|
? this.modalNodes.find((node: Node) => {
|
||||||
return !node.getExtraProp('hidden');
|
return node.getVisible();
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
return visibleNode;
|
return visibleNode;
|
||||||
@ -53,18 +53,18 @@ export default class ModalNodesManager {
|
|||||||
public hideModalNodes() {
|
public hideModalNodes() {
|
||||||
if (this.modalNodes) {
|
if (this.modalNodes) {
|
||||||
this.modalNodes.forEach((node: Node) => {
|
this.modalNodes.forEach((node: Node) => {
|
||||||
node.getExtraProp('hidden')?.setValue(true);
|
node.setVisible(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setVisible(node: Node) {
|
public setVisible(node: Node) {
|
||||||
this.hideModalNodes();
|
this.hideModalNodes();
|
||||||
node.getExtraProp('hidden')?.setValue(false);
|
node.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setInvisible(node: Node) {
|
public setInvisible(node: Node) {
|
||||||
node.getExtraProp('hidden')?.setValue(true);
|
node.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onVisibleChange(func: () => any) {
|
public onVisibleChange(func: () => any) {
|
||||||
@ -101,26 +101,24 @@ export default class ModalNodesManager {
|
|||||||
}
|
}
|
||||||
this.removeNodeEvent(node);
|
this.removeNodeEvent(node);
|
||||||
this.emitter.emit('modalNodesChange');
|
this.emitter.emit('modalNodesChange');
|
||||||
if (!node.getExtraProp('hidden')) {
|
if (node.getVisible()) {
|
||||||
this.emitter.emit('visibleChange');
|
this.emitter.emit('visibleChange');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private addNodeEvent(node: Node) {
|
private addNodeEvent(node: Node) {
|
||||||
// this.nodeRemoveEvents[node.getId()] =
|
this.nodeRemoveEvents[node.getId()] =
|
||||||
// node.onStatusChange((status: any, field: any) => {
|
node.onVisibleChange((flag) => {
|
||||||
// if (field === 'visibility') {
|
this.emitter.emit('visibleChange');
|
||||||
// this.emitter.emit('visibleChange');
|
});
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeNodeEvent(node: Node) {
|
private removeNodeEvent(node: Node) {
|
||||||
// if (this.nodeRemoveEvents[node.getId()]) {
|
if (this.nodeRemoveEvents[node.getId()]) {
|
||||||
// this.nodeRemoveEvents[node.getId()]();
|
this.nodeRemoveEvents[node.getId()]();
|
||||||
// delete this.nodeRemoveEvents[node.getId()];
|
delete this.nodeRemoveEvents[node.getId()];
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setNodes() {
|
private setNodes() {
|
||||||
@ -22,6 +22,7 @@ import { ExclusiveGroup, isExclusiveGroup } from './exclusive-group';
|
|||||||
import { TransformStage } from './transform-stage';
|
import { TransformStage } from './transform-stage';
|
||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
import { SettingTopEntry } from 'designer/src/designer';
|
import { SettingTopEntry } from 'designer/src/designer';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基础节点
|
* 基础节点
|
||||||
@ -72,6 +73,7 @@ import { SettingTopEntry } from 'designer/src/designer';
|
|||||||
* hidden
|
* hidden
|
||||||
*/
|
*/
|
||||||
export class Node<Schema extends NodeSchema = NodeSchema> {
|
export class Node<Schema extends NodeSchema = NodeSchema> {
|
||||||
|
private emitter: EventEmitter;
|
||||||
/**
|
/**
|
||||||
* 是节点实例
|
* 是节点实例
|
||||||
*/
|
*/
|
||||||
@ -162,6 +164,7 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.settingEntry = this.document.designer.createSettingEntry([ this ]);
|
this.settingEntry = this.document.designer.createSettingEntry([ this ]);
|
||||||
|
this.emitter = new EventEmitter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private transformProps(props: any): any {
|
private transformProps(props: any): any {
|
||||||
@ -414,6 +417,22 @@ export class Node<Schema extends NodeSchema = NodeSchema> {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setVisible(flag: boolean): void {
|
||||||
|
this.getExtraProp('hidden')?.setValue(!flag);
|
||||||
|
this.emitter.emit('visibleChange', flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
getVisible(): boolean {
|
||||||
|
return !this.getExtraProp('hidden', false)?.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChange(func: (flag: boolean) => any) {
|
||||||
|
this.emitter.on('visibleChange', func);
|
||||||
|
return () => {
|
||||||
|
this.emitter.removeListener('visibleChange', func);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
getProp(path: string, stash = true): Prop | null {
|
getProp(path: string, stash = true): Prop | null {
|
||||||
return this.props.query(path, stash as any) || null;
|
return this.props.query(path, stash as any) || null;
|
||||||
}
|
}
|
||||||
|
|||||||
14
packages/plugin-outline-pane/src/icons/radio-active.tsx
Normal file
14
packages/plugin-outline-pane/src/icons/radio-active.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconRadioActive(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M512 1024A512 512 0 1 1 512 0a512 512 0 0 1 0 1024z m0-256a256 256 0 1 0 0-512 256 256 0 0 0 0 512z"></path>
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconRadioActive.displayName = 'IconRadioActive';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
14
packages/plugin-outline-pane/src/icons/radio.tsx
Normal file
14
packages/plugin-outline-pane/src/icons/radio.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { SVGIcon, IconProps } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
|
export function IconRadio(props: IconProps) {
|
||||||
|
return (
|
||||||
|
<SVGIcon viewBox="0 0 1024 1024" {...props}>
|
||||||
|
<path d="M512 1024A512 512 0 1 1 512 0a512 512 0 0 1 0 1024z m0-64A448 448 0 1 0 512 64a448 448 0 0 0 0 896z"></path>
|
||||||
|
</SVGIcon>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
IconRadio.displayName = 'IconRadio';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ export default class TreeNode {
|
|||||||
@computed get hidden(): boolean {
|
@computed get hidden(): boolean {
|
||||||
const cv = this.node.isConditionalVisible();
|
const cv = this.node.isConditionalVisible();
|
||||||
if (cv == null) {
|
if (cv == null) {
|
||||||
return this.node.getExtraProp('hidden', false)?.getValue() === true;
|
return !this.node.getVisible();
|
||||||
}
|
}
|
||||||
return !cv;
|
return !cv;
|
||||||
}
|
}
|
||||||
@ -81,11 +81,7 @@ export default class TreeNode {
|
|||||||
if (this.node.conditionGroup) {
|
if (this.node.conditionGroup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (flag) {
|
this.node.setVisible(!flag);
|
||||||
this.node.getExtraProp('hidden', true)?.setValue(true);
|
|
||||||
} else {
|
|
||||||
this.node.getExtraProp('hidden', false)?.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get locked(): boolean {
|
@computed get locked(): boolean {
|
||||||
|
|||||||
151
packages/plugin-outline-pane/src/views/root-tree-node.tsx
Normal file
151
packages/plugin-outline-pane/src/views/root-tree-node.tsx
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
import TreeNodeView from './tree-node';
|
||||||
|
import { Component } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { observer } from '@ali/lowcode-editor-core';
|
||||||
|
import TreeNode from '../tree-node';
|
||||||
|
import TreeTitle from './tree-title';
|
||||||
|
import TreeBranches from './tree-branches';
|
||||||
|
import { ModalNodesManager } from '@ali/lowcode-designer';
|
||||||
|
import { IconEyeClose } from '../icons/eye-close';
|
||||||
|
import { IconEye } from '../icons/eye';
|
||||||
|
|
||||||
|
@observer
|
||||||
|
class ModalTreeNodeView extends Component<{ treeNode: TreeNode }> {
|
||||||
|
private modalNodesManager: ModalNodesManager;
|
||||||
|
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
// 模态管理对象
|
||||||
|
this.modalNodesManager = props.treeNode.document.modalNodesManager;
|
||||||
|
if (!this.modalNodesManager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 当前选中的节点
|
||||||
|
let selectedNode;
|
||||||
|
const modalNodes = this.modalNodesManager.getModalNodes();
|
||||||
|
if (modalNodes && modalNodes.length > 0) {
|
||||||
|
const visibleModalNode = this.modalNodesManager.getVisibleModalNode();
|
||||||
|
if (visibleModalNode) {
|
||||||
|
selectedNode = visibleModalNode;
|
||||||
|
} else {
|
||||||
|
selectedNode = modalNodes[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
selectedNode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// componentWillMount() {
|
||||||
|
// if (!this.modalNodesManager) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.willDetach = [
|
||||||
|
// this.modalNodesManager.onModalNodesChange(() => {
|
||||||
|
// console.log('onModalNodesChange');
|
||||||
|
// setTimeout(() => {
|
||||||
|
// this.modalNodesChangeHandler();
|
||||||
|
// });
|
||||||
|
// }),
|
||||||
|
// this.modalNodesManager.onVisibleChange(() => {
|
||||||
|
// console.log('onVisibleChange');
|
||||||
|
// this.modalNodesChangeHandler();
|
||||||
|
// }),
|
||||||
|
// ];
|
||||||
|
// }
|
||||||
|
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// componentWillUnmount() {
|
||||||
|
// if (this.willDetach) {
|
||||||
|
// this.willDetach.forEach((off: any) => {
|
||||||
|
// off();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 模态节点改变的处理函数
|
||||||
|
// modalNodesChangeHandler() {
|
||||||
|
// if (!this.modalNodesManager) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// const visibleNode = this.modalNodesManager.getVisibleModalNode();
|
||||||
|
// if (visibleNode) {
|
||||||
|
// this.setState({
|
||||||
|
// selectedNode: visibleNode,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// this.forceUpdate();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// selectNode(leaf) {
|
||||||
|
// this.modalNodesManager.setVisible(leaf.getNode());
|
||||||
|
// }
|
||||||
|
|
||||||
|
hideAllNodes() {
|
||||||
|
this.modalNodesManager.hideModalNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode } = this.props;
|
||||||
|
const hasVisibleModalNode = !!this.modalNodesManager.getVisibleModalNode();
|
||||||
|
return (
|
||||||
|
<div className="tree-node-modal">
|
||||||
|
<div className="tree-node-modal-title">
|
||||||
|
<span>模态视图层</span>
|
||||||
|
<div className="tree-node-modal-title-visible-icon"
|
||||||
|
onClick={this.hideAllNodes.bind(this)}>
|
||||||
|
{hasVisibleModalNode ? <IconEyeClose /> : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="tree-pane-modal-content">
|
||||||
|
<TreeBranches treeNode={treeNode} isModal={true}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export default class RootTreeNodeView extends Component<{ treeNode: TreeNode }> {
|
||||||
|
shouldComponentUpdate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { treeNode } = this.props;
|
||||||
|
const className = classNames('tree-node', {
|
||||||
|
// 是否展开
|
||||||
|
expanded: treeNode.expanded,
|
||||||
|
// 是否悬停中
|
||||||
|
detecting: treeNode.detecting,
|
||||||
|
// 是否选中的
|
||||||
|
selected: treeNode.selected,
|
||||||
|
// 是否隐藏的
|
||||||
|
hidden: treeNode.hidden,
|
||||||
|
// 是否忽略的
|
||||||
|
// ignored: treeNode.ignored,
|
||||||
|
// 是否锁定的
|
||||||
|
locked: treeNode.locked,
|
||||||
|
// 是否投放响应
|
||||||
|
dropping: treeNode.dropDetail?.index != null,
|
||||||
|
'is-root': treeNode.isRoot(),
|
||||||
|
'condition-flow': treeNode.node.conditionGroup != null,
|
||||||
|
highlight: treeNode.isFocusingNode(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={className} data-id={treeNode.id}>
|
||||||
|
<TreeTitle treeNode={treeNode} />
|
||||||
|
<ModalTreeNodeView treeNode={treeNode} />
|
||||||
|
<TreeBranches treeNode={treeNode}/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,6 +21,46 @@
|
|||||||
margin-bottom: @treeNodeHeight;
|
margin-bottom: @treeNodeHeight;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
|
.tree-node-modal {
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid rgba(31, 56, 88, 0.2);
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 1px 4px 0 rgba(31, 56, 88, 0.15);
|
||||||
|
|
||||||
|
.tree-node-modal-title {
|
||||||
|
position: relative;
|
||||||
|
background: rgba(31, 56, 88, 0.04);
|
||||||
|
padding: 0 10px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-bottom: 1px solid rgba(31, 56, 88, 0.2);
|
||||||
|
|
||||||
|
.tree-node-modal-title-visible-icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
right: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-pane-modal-content {
|
||||||
|
& > .tree-node-branches::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-node-modal-radio, .tree-node-modal-radio-active {
|
||||||
|
margin-right: 4px;
|
||||||
|
opacity: 0.8;
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
.tree-node-modal-radio-active {
|
||||||
|
color: #006cff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.tree-node-branches::before {
|
.tree-node-branches::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@ -9,13 +9,14 @@ import { intlNode } from '../locale';
|
|||||||
@observer
|
@observer
|
||||||
export default class TreeBranches extends Component<{
|
export default class TreeBranches extends Component<{
|
||||||
treeNode: TreeNode;
|
treeNode: TreeNode;
|
||||||
|
isModal?: boolean;
|
||||||
}> {
|
}> {
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const treeNode = this.props.treeNode;
|
const { treeNode, isModal } = this.props;
|
||||||
const { expanded } = treeNode;
|
const { expanded } = treeNode;
|
||||||
|
|
||||||
if (!expanded) {
|
if (!expanded) {
|
||||||
@ -24,8 +25,10 @@ export default class TreeBranches extends Component<{
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tree-node-branches">
|
<div className="tree-node-branches">
|
||||||
<TreeNodeSlots treeNode={treeNode} />
|
{
|
||||||
<TreeNodeChildren treeNode={treeNode} />
|
!isModal && <TreeNodeSlots treeNode={treeNode}/>
|
||||||
|
}
|
||||||
|
<TreeNodeChildren treeNode={treeNode} isModal={isModal || false}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -34,12 +37,13 @@ export default class TreeBranches extends Component<{
|
|||||||
@observer
|
@observer
|
||||||
class TreeNodeChildren extends Component<{
|
class TreeNodeChildren extends Component<{
|
||||||
treeNode: TreeNode;
|
treeNode: TreeNode;
|
||||||
|
isModal?: boolean;
|
||||||
}> {
|
}> {
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const { treeNode } = this.props;
|
const { treeNode, isModal } = this.props;
|
||||||
let children: any = [];
|
let children: any = [];
|
||||||
let groupContents: any[] = [];
|
let groupContents: any[] = [];
|
||||||
let currentGrp: ExclusiveGroup;
|
let currentGrp: ExclusiveGroup;
|
||||||
@ -67,6 +71,10 @@ class TreeNodeChildren extends Component<{
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
treeNode.children?.forEach((child, index) => {
|
treeNode.children?.forEach((child, index) => {
|
||||||
|
const childIsModal = child.node.getPrototype().isModal();
|
||||||
|
if (isModal != childIsModal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const { conditionGroup } = child.node;
|
const { conditionGroup } = child.node;
|
||||||
if (conditionGroup !== currentGrp) {
|
if (conditionGroup !== currentGrp) {
|
||||||
endGroup();
|
endGroup();
|
||||||
@ -81,12 +89,12 @@ class TreeNodeChildren extends Component<{
|
|||||||
children.push(insertion);
|
children.push(insertion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
groupContents.push(<TreeNodeView key={child.id} treeNode={child} />);
|
groupContents.push(<TreeNodeView key={child.id} treeNode={child} isModal={isModal}/>);
|
||||||
} else {
|
} else {
|
||||||
if (index === dropIndex) {
|
if (index === dropIndex) {
|
||||||
children.push(insertion);
|
children.push(insertion);
|
||||||
}
|
}
|
||||||
children.push(<TreeNodeView key={child.id} treeNode={child} />);
|
children.push(<TreeNodeView key={child.id} treeNode={child} isModal={isModal}/>);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
endGroup();
|
endGroup();
|
||||||
|
|||||||
@ -6,13 +6,16 @@ import TreeTitle from './tree-title';
|
|||||||
import TreeBranches from './tree-branches';
|
import TreeBranches from './tree-branches';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export default class TreeNodeView extends Component<{ treeNode: TreeNode }> {
|
export default class TreeNodeView extends Component<{
|
||||||
|
treeNode: TreeNode;
|
||||||
|
isModal?: boolean;
|
||||||
|
}> {
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { treeNode } = this.props;
|
const { treeNode, isModal } = this.props;
|
||||||
const className = classNames('tree-node', {
|
const className = classNames('tree-node', {
|
||||||
// 是否展开
|
// 是否展开
|
||||||
expanded: treeNode.expanded,
|
expanded: treeNode.expanded,
|
||||||
@ -35,8 +38,8 @@ export default class TreeNodeView extends Component<{ treeNode: TreeNode }> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className} data-id={treeNode.id}>
|
<div className={className} data-id={treeNode.id}>
|
||||||
<TreeTitle treeNode={treeNode} />
|
<TreeTitle treeNode={treeNode} isModal={isModal}/>
|
||||||
<TreeBranches treeNode={treeNode} />
|
<TreeBranches treeNode={treeNode} isModal={false}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,11 +10,14 @@ import TreeNode from '../tree-node';
|
|||||||
import { IconEye } from '../icons/eye';
|
import { IconEye } from '../icons/eye';
|
||||||
import { IconCond } from '../icons/cond';
|
import { IconCond } from '../icons/cond';
|
||||||
import { IconLoop } from '../icons/loop';
|
import { IconLoop } from '../icons/loop';
|
||||||
|
import { IconRadioActive } from '../icons/radio-active';
|
||||||
|
import { IconRadio } from '../icons/radio';
|
||||||
import { createIcon } from '@ali/lowcode-utils';
|
import { createIcon } from '@ali/lowcode-utils';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export default class TreeTitle extends Component<{
|
export default class TreeTitle extends Component<{
|
||||||
treeNode: TreeNode;
|
treeNode: TreeNode;
|
||||||
|
isModal?: boolean;
|
||||||
}> {
|
}> {
|
||||||
state: {
|
state: {
|
||||||
editing: boolean;
|
editing: boolean;
|
||||||
@ -62,7 +65,7 @@ export default class TreeTitle extends Component<{
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { treeNode } = this.props;
|
const { treeNode, isModal } = this.props;
|
||||||
const { editing } = this.state;
|
const { editing } = this.state;
|
||||||
const isCNode = !treeNode.isRoot();
|
const isCNode = !treeNode.isRoot();
|
||||||
const { node } = treeNode;
|
const { node } = treeNode;
|
||||||
@ -72,7 +75,7 @@ export default class TreeTitle extends Component<{
|
|||||||
const depth = treeNode.depth;
|
const depth = treeNode.depth;
|
||||||
const indent = depth * 12;
|
const indent = depth * 12;
|
||||||
style = {
|
style = {
|
||||||
paddingLeft: indent,
|
paddingLeft: indent + (isModal ? 12 : 0),
|
||||||
marginLeft: -indent,
|
marginLeft: -indent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -84,8 +87,31 @@ export default class TreeTitle extends Component<{
|
|||||||
})}
|
})}
|
||||||
style={style}
|
style={style}
|
||||||
data-id={treeNode.id}
|
data-id={treeNode.id}
|
||||||
onClick={node.conditionGroup ? () => node.setConditionalVisible() : undefined}
|
onClick={() => {
|
||||||
|
if (isModal) {
|
||||||
|
node.document.modalNodesManager.setVisible(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (node.conditionGroup) {
|
||||||
|
node.setConditionalVisible();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
|
{isModal && node.getVisible() && (
|
||||||
|
<div onClick={() => {
|
||||||
|
node.document.modalNodesManager.setInvisible(node);
|
||||||
|
}}>
|
||||||
|
<IconRadioActive className="tree-node-modal-radio-active"/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isModal && !node.getVisible() && (
|
||||||
|
<div onClick={() => {
|
||||||
|
node.document.modalNodesManager.setVisible(node);
|
||||||
|
}}>
|
||||||
|
<IconRadio className="tree-node-modal-radio"/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{isCNode && <ExpandBtn treeNode={treeNode} />}
|
{isCNode && <ExpandBtn treeNode={treeNode} />}
|
||||||
<div className="tree-node-icon">{createIcon(treeNode.icon)}</div>
|
<div className="tree-node-icon">{createIcon(treeNode.icon)}</div>
|
||||||
<div className="tree-node-title-label" onDoubleClick={isNodeParent ? this.enableEdit : undefined}>
|
<div className="tree-node-title-label" onDoubleClick={isNodeParent ? this.enableEdit : undefined}>
|
||||||
@ -123,7 +149,7 @@ export default class TreeTitle extends Component<{
|
|||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isCNode && isNodeParent && <HideBtn treeNode={treeNode} />}
|
{isCNode && isNodeParent && !isModal && <HideBtn treeNode={treeNode} />}
|
||||||
{/*isCNode && isNodeParent && <LockBtn treeNode={treeNode} />*/}
|
{/*isCNode && isNodeParent && <LockBtn treeNode={treeNode} />*/}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { observer, Editor, globalContext } from '@ali/lowcode-editor-core';
|
|||||||
import { isRootNode, Node, DragObjectType, isShaken } from '@ali/lowcode-designer';
|
import { isRootNode, Node, DragObjectType, isShaken } from '@ali/lowcode-designer';
|
||||||
import { isFormEvent } from '@ali/lowcode-utils';
|
import { isFormEvent } from '@ali/lowcode-utils';
|
||||||
import { Tree } from '../tree';
|
import { Tree } from '../tree';
|
||||||
import TreeNodeView from './tree-node';
|
import RootTreeNodeView from './root-tree-node';
|
||||||
|
|
||||||
function getTreeNodeIdByEvent(e: ReactMouseEvent, stop: Element): null | string {
|
function getTreeNodeIdByEvent(e: ReactMouseEvent, stop: Element): null | string {
|
||||||
let target: Element | null = e.target as Element;
|
let target: Element | null = e.target as Element;
|
||||||
@ -155,7 +155,7 @@ export default class TreeView extends Component<{ tree: Tree }> {
|
|||||||
onClick={this.onClick}
|
onClick={this.onClick}
|
||||||
onMouseLeave={this.onMouseLeave}
|
onMouseLeave={this.onMouseLeave}
|
||||||
>
|
>
|
||||||
<TreeNodeView key={root.id} treeNode={root} />
|
<RootTreeNodeView key={root.id} treeNode={root} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user