2025-07-16 14:27:17 +08:00

304 lines
7.9 KiB
Vue

<template>
<div id="" class="myTree">
<el-tree ref="tree" class="filter-tree" :data="treeData" @node-click="treeUpdate" :props="defaultProps" :node-key="nodeKey" :default-expanded-keys="treeExpandId" :filter-node-method="filterNode" :default-expand-all="defaultExpandAll" :show-checkbox="showCheckbox">
<span slot-scope="{ node, data }" class="custom-tree-node">
<span class="nameVal">{{ node.label }}</span>
<span class="btnGroup" style="height: 26px;">
<el-tooltip v-if="node.level == 1 && isAddDel" class="item" effect="dark" content="添加同级节点" placement="bottom">
<i class="el-icon-circle-plus-outline" @click.stop="() => append(node, data,'addbrother')" />
</el-tooltip>
<el-tooltip v-if="isAddDel" class="item" effect="dark" content="添加子级节点" placement="bottom">
<i class="el-icon-circle-plus-outline" @click.stop="() => append(node, data,'addson')" />
</el-tooltip>
<el-tooltip class="item" effect="dark" content="编辑" placement="bottom">
<i v-if="isEdit" class="el-icon-edit" @click.stop="() => update(node, data)" />
</el-tooltip>
<el-tooltip v-if="isAddDel" class="item" effect="dark" content="删除" placement="bottom">
<el-popover :ref="`popover-${data.id}`" v-model="data.delConfirmVisible" placement="top" width="160">
<p>确认删除该节点吗?</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="popoverCancel(node,data)">取消</el-button>
<el-button type="primary" size="mini" @click="opoverSubmit(node,data)">确定</el-button>
</div>
<i slot="reference" class="el-icon-delete" @click.stop="() => remove(node, data)" />
</el-popover>
</el-tooltip>
</span>
</span>
</el-tree>
<el-dialog :append-to-body="true" :title="editIndex == 1 ? '创建' : '编辑'" :visible.sync="dialogFormVisible" custom-class="commonDialog">
<el-form ref="addForm" :model="addForm" :rules="formRules" :label-width="labelWidth + 'px'">
<div v-for="(item,index) in addFormArr" :key="index">
<el-form-item :label="item.label" :prop="item.prop">
<el-input v-model="addForm[item.prop]" />
</el-form-item>
</div>
</el-form>
<div slot="footer" class="btnGroup">
<el-button @click="resetForm('addForm')">取消</el-button>
<el-button type="primary" @click="submitForm('addForm')">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'Organization',
props: {
// 唯一id,这个是树状结构的id就是唯一的,没啥作用其实,区分用
id: {
type: String,
default: 'Mytree',
required: true
},
// 这是每一个树状节点的唯一的key,element 原有属性
nodeKey: {
type: String,
default: 'id',
required: true
},
// 是否显示复选框,element 原有属性
showCheckbox: {
type: Boolean,
default: false
},
// 是否默认显示全部,element 原有属性
defaultExpandAll: {
type: Boolean,
default: false
},
// tree的数组,element 原有属性
treeData: {
type: Array,
default: () => {
return new Array()
}
},
// tree的数据解析方式,element 原有属性
defaultProps: {
type: Object
},
// 是否有添加,删除等按钮
isAddDel: {
type: Boolean,
default: false
},
isEdit: {
type: Boolean,
default: false
},
// 添加,编辑的弹框里的表单-for循用
addFormArr: {
type: Array,
default: () => {
return new Array()
}
},
// 添加,编辑的弹框里的表单绑定的v-model绑定
addForm: {
type: Object,
default: () => {
return {}
}
},
labelWidth: {
type: Number,
default: 100
},
// 正则校验
formRules: {
type: Object,
default: () => {
return {}
}
}
},
data() {
return {
popoverVisible: false,
dialogFormVisible: false,
treeExpandId: [], // 自己定义的用于接收tree树id的数组
editIndex: 1, // 模态框editIndex = 1为新增 editIndex != 1为修改
editForm: null,
// treeData: [{
// label: '根节点',
// value: 100
// }]
}
},
watch: {},
mounted() {
},
methods: {
filterNode(value, data) {
if (!value) return true
// 调用tree 里面的filter方法的时候的过滤条件方法,传到父组件,父组件掉接口
this.$emit('filterNodeChange', {
value: value,
data: data
})
},
// 新增或修改数据
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
if (this.editIndex) {
// var msg = '添加'
// 添加确定事件,父组件掉接口
this.$emit('treeSubmitChange', this.addForm)
} else {
// var msg = '编辑'
// 编辑确定事件,父组件掉接口
this.editForm = this.addForm;
this.$emit('treeEditChange', this.editForm)
}
} else {
return false
}
})
},
resetForm(formName) {
this.$refs[formName].resetFields()
this.dialogFormVisible = false
},
append(node, data, type) {
if (type == 'addson') {
this.addForm.parentid = data.id
}
this.editIndex = 1
this.dialogFormVisible = true
},
update(node, data) {
if (type == 'addbrother') {
delete this.addForm.parentid
}
Object.keys(data).forEach((key) => {
this.addForm[key] = data[key]
})
this.editIndex = 0
this.dialogFormVisible = true
},
treeUpdate(node, data) {
this.$emit('treeUpdateChange', {
node: node,
data: data
})
},
remove(node, data) {
},
tabHandleClick() {
},
popoverCancel(node, data) {
data.delConfirmVisible = false
},
opoverSubmit(node, data) {
data.delConfirmVisible = false
// 树删除方法,父组件掉接口
this.$emit('treeDelChange', {
node: node,
data: data
})
},
getCheckedKeys() {
return this.$refs.tree.getCheckedKeys()
},
setCheckedNodes(nodes) {
this.$refs.tree.setCheckedNodes(nodes)
}
}
}
</script>
<style lang="scss" scoped>
.myTree {
padding: 12px;
.el-tree {
.custom-tree-node {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.el-icon-delete {
height: 26px !important;
display: flex;
justify-content: center;
align-items: center;
}
.el-tree-node__content {
line-height: 30px;
height: 30px;
.nameVal {
font-family: PingFangSC-Regular;
font-size: 14px;
color: #333333;
letter-spacing: 0;
font-weight: 400;
}
.custom-tree-node {
.btnGroup {
display: none;
.el-icon-delete {
font-size: 14px;
}
.el-icon-edit {
font-size: 14px;
}
.el-icon-circle-plus-outline {
font-size: 14px;
}
.item {
margin-left: 5px;
}
.item:hover {
color: #409eff;
}
}
}
}
::v-deep .el-tree-node__content:hover {
background-color: rgba(38, 122, 248, 0.1) !important;
.custom-tree-node {
.btnGroup {
display: flex;
justify-content: center;
align-items: center;
}
}
}
}
}
</style>
<style>
@media screen and (max-width: 760px) {
.commonDialog {
width: 80vw !important;
z-index: 99999999;
}
}
</style>