304 lines
7.9 KiB
Vue
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>
|