需求和效果
需求:
1.可编辑:鼠标悬浮出现目录编辑图标,点击编辑图标,弹出树节点名称修改弹出框进行修改,同时弹出框具备校验功能。
2.可删除:点击删除图标,删除相对应节点。
代码
<template>
<div class="editable-tree l-box-col">
<div class="editable-tree-header l-mt-12 l-mb-12">
<el-button
class="market-standard-sidebar-btn"
type="primary"
@click="() => this.$emit('showDirectoryDialog', 'directory')"
size="medium"
>
<i class="el-icon-folder"></i>
新建目录
</el-button>
<el-button
v-if="menuType == 'info'"
class="market-standard-sidebar-btn"
@click="() => this.$emit('showDirectoryDialog', 'specification')"
size="medium"
>
<i class="el-icon-document"></i>
新建规范集
</el-button>
</div>
<div class="editable-tree-body l-flex" @click="cancleSelect">
<el-tree
:data="data"
node-key="id"
default-expand-all
:expand-on-click-node="false"
@node-click="handleNodeClick"
ref="treeComp"
>
<div
class="custom-tree-node"
slot-scope="{ node, data }"
@mouseenter="() => mouseenter(data)"
@mouseleave="() => mouseout(data)"
>
<div class="custom-tree-node-label">
<span v-show="data.directoryType == '00'" class="l-mr-10">
<i class="el-icon-folder"></i>
</span>
<span v-show="data.directoryType == '01'" class="l-mr-10">
<i class="el-icon-document"></i>
</span>
<div><title-tip :content="node.label" /></div>
<!-- <span>{{ node.label }}</span> -->
</div>
<div class="custom-tree-node-operate">
<i
v-show="data.showEdit"
@click="() => edit(node, data)"
class="el-icon-edit l-mr-8"
></i>
<i
v-show="data.showDel"
@click="() => remove(node, data)"
class="el-icon-delete delete-icon"
></i>
</div>
</div>
</el-tree>
</div>
</div>
</template>
<script>
import * as api from '@/api/tree'
let id = 10
export default {
name: 'EditableTree',
props: {
data: {
type: Array,
default: () => [],
},
menuType: {
type: String,
default: '',
},
applicationType: {
type: String,
default: '',
},
defaultCheckTreeKeys: {
type: Array,
default: () => [],
},
},
computed: {
treeData() {
return JSON.parse(JSON.stringify(this.data))
},
},
data() {
return {
firstInit: true,
}
},
methods: {
remove(node, data) {
const id = data.id
const params = {
id,
applicationType: this.applicationType,
}
api.deleteDirectory(params).then((res) => {
if (res.responseCode == 200) {
this.removeTreeData(node, data)
this.$message({
showClose: true,
message: '删除成功',
type: 'success',
})
this.$emit('queryTreeData')
} else {
this.$message({
message: res.message,
type: 'warning',
})
}
})
},
edit(node, data) {
const nodeInfo = {
id: data.id,
directoryType: data.directoryType,
directoryName: data.label,
}
this.$emit('editDirectoryDialog', nodeInfo)
},
removeTreeData(node, data) {
const parent = node.parent
const children = parent.data.children || parent.data
const index = children.findIndex((d) => d.id === data.id)
children.splice(index, 1)
},
mouseenter(data) {
this.showEdit && this.$set(data, 'showEdit', true)
if (data.children.length !== 0) return
this.$set(data, 'showDel', true)
},
mouseout(data) {
this.showEdit && this.$set(data, 'showEdit', false)
if (data.children.length !== 0) return
this.$set(data, 'showDel', false)
},
handleNodeClick(data) {
this.$emit('getDirectoryId', data)
},
cancleSelect() {
// this.$refs.treeComp.setCurrentKey(null)
// this.$emit('clearDirectoryId')
},
// createDirectoryDialog(type) {
// this.dialogData.dialogVisible = true
// this.dialogData.width = '30%'
// this.dialogData.top = 'calc(50vh - 116px)'
// this.dialogData.title = type == 'directory' ? '新建目录' : '新建规范集'
// this.dialogData.component = 'MarketCreateDirectory'
// this.dialogData.transferData = { type }
// this.directoryDialogType = type
// this.dialogData.buttons = [
// {
// type: 'primary',
// size: 'medium',
// label: '确定',
// event: 'modifyTreeData',
// },
// {
// size: 'medium',
// label: '取消',
// event: 'close',
// },
// ]
// },
},
watch: {
defaultCheckTreeKeys: {
handler: function (newVal, oldVal) {
this.$nextTick(() => {
this.$refs.treeComp.setCurrentKey(newVal[0])
})
},
},
$route: {
handler: function (to, from) {
// 只有当前页面为集市规范化-数据规范信息时
const curPage = to.query.index.replace('/', '')
this.showEdit = curPage == 'info'
},
immediate: true,
},
},
}
</script>
<style lang="less" scoped>
.editable-tree {
&-body {
overflow: scroll;
::v-deep {
.el-button {
color: #d2d2d2;
border: none;
margin-left: 20px;
padding: 0;
display: none;
}
}
}
::v-deep .el-tree-node__content:hover {
.el-button {
display: inline-block;
}
}
::v-deep .custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 8px;
}
::v-deep .custom-tree-node-label {
display: flex;
width: 180px;
}
// ::v-deep .custom-tree-node-operate {
// width: 40px;
// height: 15px;
// }
::v-deep.el-tree-node.is-current > .el-tree-node__content {
background: #f0f4ff;
color: #358df6;
font-weight: bold;
i {
color: #358df6;
font-weight: bold;
}
}
::v-deep .el-tree-node__content {
font-size: 14px;
}
}
</style>