<template>
<div style="width: 98vw; height: 96vh" ref="demoWrapper">
<awesome-minder
:sourceData="sourceData"
:renderContent="renderContent"
ref="minderRef"
@contextmenu="handleMenu"
@node:select="handleNodeSelect"
>
<template #navbar>
<div class="navbar">
<div class="iconfont-wrapper" :class="[{ active: expandAll }]" @click="toggleExpandAll">
<i class="iconfont icon-a-icon-quanbuzhankaizhedie"></i>
</div>
<div
class="iconfont-wrapper"
:class="[{ active: nodeExpanded, disabled: nodeExpandDisabled }]"
@click="toggleNodeExpand"
>
<i class="iconfont icon-a-icon-tongjizhankaizhedie"></i>
</div>
<div class="iconfont-wrapper" @click="centerContent">
<i class="iconfont icon-icon-dingweijuzhong"></i>
</div>
<div class="iconfont-wrapper" @click="zoomIn">
<i class="iconfont icon-icon-fangda"></i>
</div>
<div class="iconfont-wrapper" @click="zoomOut">
<i class="iconfont icon-icon-suoxiao"></i>
</div>
<div class="iconfont-wrapper" @click="downloadImage">
<i class="iconfont icon-download"></i>
</div>
<div style="flex: 1"></div>
<el-select
v-model="searchVal"
placeholder="搜索结构"
@focus="initSearchOptions"
@change="handleSearch"
size="mini"
clearable
filterable
>
<el-option
v-for="item in searchOptions"
:key="item.id"
:label="item.text"
:value="item.id"
>
</el-option>
</el-select>
</div>
</template>
</awesome-minder>
<awesome-context-menu ref="menuRef">
<awesome-context-menu-item @click="handleAppend">
<span>添加下级</span>
</awesome-context-menu-item>
<awesome-context-menu-item @click="handleUpdate">
<span>编辑</span>
</awesome-context-menu-item>
<awesome-context-menu-item @click="handleDelete" v-if="!isRootNode">
<span style="color: #e63c28">删除</span>
</awesome-context-menu-item>
</awesome-context-menu>
</div>
</template>
<script lang="jsx">
export default {
name: 'Demo',
data() {
return {
sourceData: [
{
id: 1,
parentId: null,
text: '根节点'
}
],
selectedNode: null,
expandAll: false,
searchVal: '',
searchOptions: []
};
},
computed: {
nodeExpanded() {
return (
!!this.selectedNode &&
!!this.selectedNode.rightRelations.length &&
!!this.selectedNode.rightExpanded
);
},
nodeExpandDisabled() {
return !this.selectedNode || !this.selectedNode.rightRelations?.length;
},
isRootNode() {
return this.selectedNode && !this.selectedNode.parentId;
}
},
methods: {
renderContent(node) {
return <node-render text={node.text} />;
},
handleNodeSelect(node) {
this.selectedNode = node;
},
handleMenu({ e }) {
const wrapperPos = this.$refs.demoWrapper.getBoundingClientRect();
const clientX = e.clientX - wrapperPos.x;
const clientY = e.clientY - wrapperPos.y;
this.$refs.menuRef.openMenu({
clientX,
clientY
});
},
toggleExpandAll() {
this.expandAll = !this.expandAll;
this.$refs.minderRef.toggleExpandAll(this.expandAll);
},
toggleNodeExpand() {
this.$refs.minderRef.toggleExpandNode(this.selectedNode);
},
centerContent() {
this.$refs.minderRef.centerContent(false);
},
initSearchOptions() {
const options = this.$refs.minderRef.exportFlattenedDatasource();
this.searchOptions = options;
},
handleSearch() {
if (this.searchVal) {
this.$refs.minderRef.highlightNodeById(this.searchVal);
}
},
zoomIn() {
this.$refs.minderRef.zoomIn();
},
zoomOut() {
this.$refs.minderRef.zoomOut();
},
downloadImage() {
this.$refs.minderRef.exportImage('导出图片');
},
handleAppend() {
if (!this.selectedNode) return;
const id = new Date().getTime();
this.$refs.minderRef.appendNode(this.selectedNode.id, {
id,
parentId: this.selectedNode.id,
text: '测试' + id
});
},
handleUpdate() {
if (!this.selectedNode) return;
const id = new Date().getTime();
this.$refs.minderRef.editNode(this.selectedNode.id, {
text: '测试-更新' + id
});
},
handleDelete() {
if (!this.selectedNode) return;
this.$refs.minderRef.removeNode(this.selectedNode.id);
}
}
};
</script>
<style lang="scss" scoped>
.navbar {
position: absolute;
top: 20px;
left: 20px;
right: 20px;
padding: 8px;
background: #fff;
box-shadow: 0 1px 1px 1px rgba(170, 170, 170, 0.18);
overflow: hidden;
word-break: keep-all;
display: flex;
align-items: center;
gap: 8px;
.iconfont-wrapper {
align-items: center;
border-radius: 2px;
cursor: pointer;
display: flex;
height: 24px;
justify-content: center;
padding: 6px;
transition: all 0.1s ease;
width: 24px;
&:not(.disabled):hover {
background-color: #f2f3f4;
}
&.disabled {
color: #ccc;
cursor: not-allowed;
}
&.active {
background-color: #e7eefb;
color: #265cdd;
}
}
}
.demo-node {
user-select: none;
}
</style>