话不多说直接上干货,大家可以直接根据需求改造后去复用
1.创建index文件
<template>
<div class="white-body-view">
<!-- 树 -->
<tree
ref="customTree"
:tree-data="treeData"
:tree-expand-all="treeExpandAll"
:tree-node-key="treeNodeKey"
@handleCurrentNodeKeyClick="handleCurrentNodeKeyClick"
@addTreeItem="addTreeItem"
@addItem="addItem"
@deleteItem="deleteItem"
@editItem="editItem"
/>
<!-- 树弹窗 -->
<tree-dialog ref="treeDialog" @addData="addData" @editData="editData" />
</div>
</template>
<script>
import Tree from '@/views/testTree/components/tree.vue'
import treeDialog from '@/views/testTree/components/treeDialog.vue'
export default {
components: {
Tree,
treeDialog,
},
created() {
this.getTreeList()
},
data() {
return {
treeData: [],
treeExpandAll: true,
treeNodeKey: 'treeId',
treeId: '',
}
},
methods: {
// 树点击选中行
handleCurrentNodeKeyClick(data) {
this.currentNodeKey = data.treeId
},
// 新增表单数据
addData(data) {
// 新增树节点
this.$refs.customTree.addItem(data)
this.closeGroupDialog()
},
// 修改表单数据
editData(data) {
// 修改树节点
this.$refs.customTree.editItem(data)
// 调详情回显接口
apt.getData({ id: data.treeId }).then((res) => {
const { data } = res
// 表单回显需要的参数
this.treeParams.treeName = data.treeName
this.treeParams.treeId = data.treeId
this.treeParams.parentTreeId = data.parentTreeId
this.treeParams.parentTreeName = data.parentTreeName
})
},
// 添加主节点
addTreeItem() {
this.$refs.treeDialog.openDialog(1, false, '', {})
},
// 添加子节点
addItem(data) {
this.$refs.treeDialog.openDialog(0, false, data.treeId, data) //传递需要的参数
},
// ---删除树节点
deleteItem(data) {
this.$confirm('确认要删除当前节点吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
// 删除树节点
// 根据需求修改调用接口的操作
api.delete(data.treeId, 1).then((res) => {
this.$message({ type: 'success', message: '删除成功' })
this.$refs.customTree.treedeleteItem(data)
})
})
.catch(() => {})
},
// 修改树节点
editItem(data) {
// 打开地点编辑弹窗
this.$refs.treeDialog.openDialog(0, true, data.treeId, data) //传递需要的参数
}
}
}
</script>
2.引入 tree.vue文件
<template>
<div class="container">
<el-row class="container-block">
<!-- 左侧树结构 -->
<el-col :span="6" style="padding: 15px" class="tree-content">
<el-input
size="small"
placeholder="请输入分组名称查询"
suffix-icon="el-icon-search"
v-model="filterText"
class="tree-ipt"
clearable
>
</el-input>
<div class="left-container">
<el-tree
v-loading="treeLoading"
:data="treeDataList"
default-expand-all
node-key="treeId"
:highlight-current="true"
:filter-node-method="filterNode"
ref="fatherTree"
@node-click="handleCurrentNodeKeyClick"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span class="txt-cont" :title="data.treeName">{{
data.treeName
}}</span>
<span>
<el-button
type="text"
v-if="node.level !== 3"
class="el-icon-plus"
size="mini"
@click="appendTreeGroup(data)"
></el-button>
<el-button
type="text"
class="el-icon-delete"
size="mini"
@click="removeGroup(data)"
></el-button>
<el-button
type="text"
class="el-icon-edit"
size="mini"
@click="editGroup(data)"
></el-button>
</span>
</span>
</el-tree>
</div>
<div class="left-button">
<el-button type="primary" @click="appendGroup()"
>新增主分组</el-button
>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
props: {
// 源数据
treeData: {
type: Array,
default: function () {
return []
},
},
// 树节点是否默认展开
treeExpandAll: {
type: Boolean,
default: true,
},
// 树节点唯一标识
treeNodeKey: {
type: String,
default: '',
},
},
watch: {
filterText(val) {
this.$refs.fatherTree.filter(val)
},
},
data() {
return {
filterText: '', //树查询
treeType: '1', //标识符
currentNodeKey: '', //选中treeId
treeDataList: [], //
treeId: '', //
treeLoading: false, // 技能组树加载遮罩
// 树级分组添加弹出框
treeParams: {
treeName: '', //分组名称
type: '1', //分组添加类型:1加主分组,0加子分组
treeType: '1', //分组类型标识符
treeCode: '', //分组编码
treeLevel: 1, //层级
parentTreeId: '', //父级分组ID
parentTreeName: '', //父级分组名称
parentTreeCode: '', //父级分组编码
children: [],
},
defaultProps: {
children: 'children',
label: 'name',
},
selectItem: {},
}
},
created() {
this.getTreeList()
},
methods: {
// 获取树列表
getTreeList() {
this.treeLoading = true
let params = {
// 需要的参数
}
// 发起请求获取数据
api
.test(params)
.then((res) => {
const { data } = res
this.treeDataList = data
this.treeLoading = false
})
.catch((err) => {})
.finally(() => {
this.treeLoading = false
})
},
// 添加主分组
appendGroup() {
this.$emit('addTreeItem')
},
// 添加子分组
appendTreeGroup(data) {
this.$emit('addItem', data)
},
// 点击删除按钮
removeGroup(data) {
this.$emit('deleteItem', data)
},
editGroup(data) {
this.selectItem = data
this.$emit('editItem', JSON.parse(JSON.stringify(data)))
},
// 过滤树
filterNode(value, data) {
if (!value) return true
return data.treeName.indexOf(value) !== -1
},
// 树点击选中行
handleCurrentNodeKeyClick(data) {
this.$emit('handleCurrentNodeKeyClick', data)
},
//-----------------------------------父组件回调事件 开始=============
// 添加新记录,树形列表回显
treeAddItem(data) {
this.$refs.tree.append(data, data.treeId)
},
// 删除节点
treeDeleteItem(val) {
this.$refs.tree.remove(val)
},
// 修改记录,树形列表回显
editTreeItem(val) {
Object.assign(this.selectItem, val)
this.selectItem = {}
},
// ============== 父组件回调事件 结束=============
},
}
</script>
<style lang="scss" scoped>
.container {
background: #f2f6fc;
padding: 13px;
height: calc(100vh - 120px);
}
.container-block {
height: 100%;
}
.left-container {
height: calc(100% - 80px);
overflow: auto;
}
.left-button {
margin-top: 8px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.tree-content {
background: white;
border-radius: 4px;
height: 100%;
}
.tree-ipt {
margin-bottom: 8px;
}
.custom-tree-node {
flex: 1;
display: flex;
width: 90%;
align-items: center;
justify-content: space-between;
font-size: 14px !important;
padding-right: 8px;
}
.custom-tree-node .txt-cont {
display: inline-block;
width: 186px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.container-query {
margin: 16px 0 88px -40px;
}
.main-content {
background: white;
border-left: 8px solid #f2f6fc;
border-radius: 4px;
height: 100%;
}
.add-button {
margin: -72px 0 8px 16px;
}
.container-table {
margin: 16px;
}
.handle_edit {
color: #1890ff;
padding: 0;
}
.handle_del {
color: #f5222d;
padding: 0;
}
</style>
3.引入 treeDialog.vue文件
<template>
<div>
<el-dialog
width="500px"
:title="dialogName"
:append-to-body="false"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
>
<el-form
ref="groupTreeTable"
:model="treeParams"
label-width="90px"
size="small"
:rules="rules"
>
<el-form-item
label="分组名称"
v-if="this.dialogName !== '添加子分组'"
prop="treeName"
>
<el-input v-model="treeParams.treeName"></el-input>
</el-form-item>
<el-form-item
v-if="this.dialogName == '添加子分组'"
label="子分组名称"
prop="treeName"
>
<el-input v-model="treeParams.treeName"></el-input>
</el-form-item>
</el-form>
<!-- 弹出层按钮 -->
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitGroup">确 定</el-button>
<el-button @click="closeGroupDialog">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
let that = this
return {
dialogVisible: false,
dialogName: '', //增加分组弹窗
// 树级分组添加弹出框
treeType: '1',
treeParams: {
treeId: '', //分组类型标识符,
treeName: '', //分组名称
type: '1', //分组添加类型
treeType: '1', //分组类型标识符,
treeCode: '', //分组编码
treeLevel: 1, //层级
parentTreeId: '-', //父级分组ID
parentTreeName: '-', //父级分组名称
parentTreeCode: '', //父级分组编码
children: [],
},
rules: {
treeName: [
{ required: true, message: '请输入分组名称', trigger: 'blur' },
],
},
isEdit: false,
data: {},
}
},
methods: {
openDialog(type, isEdit, treeId, data) {
this.treeParams.type = type
this.treeParams.treeId = treeId
this.isEdit = isEdit
this.data = data
this.dialogVisible = true
if (isEdit) {
this.dialogName = '编辑分组'
if (data.parentTreeId != '-') {
type = '0'
}
// 调接口
apt.test({ id: data.treeId }).then((res) => {
const { data } = res
this.treeParams.treeName = data.treeName
this.treeParams.treeId = data.treeId
this.treeParams.parentTreeId = data.parentTreeId
this.treeParams.parentTreeName = data.parentTreeName
})
} else if (type == 0 && isEdit == false) {
this.treeParams.type = '0'
this.dialogName = '新增子分组'
this.treeParams.parentTreeId = data.treeId
this.treeParams.parentTreeName = data.treeName
this.treeParams.treeLevel = parseInt(data.treeLevel) + 1
} else {
this.treeParams.type = '1'
this.dialogName = '新增主分组'
this.treeParams.parentTreeId = '-'
this.treeParams.parentTreeName = '-'
}
},
// 提交表单
submitGroup() {
this.$refs.groupTreeTable.validate((valid) => {
if (valid) {
let treeParams = {
// 需要的参数
}
let updataTreeParams = {
// 需要的参数
}
// todo:调接口的操作
}
})
},
// 关闭当前弹窗
closeGroupDialog() {
this.clearTreeDialog()
this.dialogVisible = false
},
clearTreeDialog() {
this.addDialogVisible = false
this.dialogName = ''
this.treeParams.treeName = ''
},
},
}
</script>
<style scoped>
.pull-right {
float: right;
}
</style>