老产品前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

537 lines
14 KiB

<template>
<div class="el-tree-node">
<div class="filter-input">
<el-input placeholder="输入关键字进行过滤"
v-model="filterText"
clearable>
</el-input>
</div>
<el-tree v-if="lazy === true"
ref="tree"
lazy
node-key="id"
v-loading="loading"
:default-expanded-keys="defaultExpandKeys"
:expand-on-click-node="defaultExpandOnClickNode"
:render-content="renderContent"
:show-checkbox="showCheckbox"
:default-checked-keys="defaultCheckedKeys"
:default-expand-all="defaultExpandAll"
:current-node-key="currentNodeKey"
:filter-node-method="filterNode"
:check-on-click-node="checkOnClickNode"
highlight-current
:props="props"
:load="loadNode"
@node-click="handleNodeClick"
@node-expand="handleNodeExpand"></el-tree>
<el-tree v-else
node-key="id"
ref="tree"
:data="nodeData"
v-loading="loading"
:default-expand-all="defaultExpandAll"
:default-expanded-keys="defaultExpandKeys"
:filter-node-method="filterNode"
:expand-on-click-node="defaultExpandOnClickNode"
:render-content="renderContent"
:show-checkbox="showCheckbox"
:current-node-key="currentNodeKey"
:check-on-click-node="checkOnClickNode"
highlight-current
:props="props"
@node-click="handleNodeClick"
@check="handleCheckBox"
@current-change="handleCurrentChange"></el-tree>
</div>
</template>
<script>
export default {
data () {
return {
nodeData: [],
currentNodeKey: this.defaultNodeKey,
checkedKeys: this.defaultCheckedKeys,
firstData: null,
props: {
children: 'children',
label: 'label',
isLeaf: 'leaf'
},
filterText: '',
defaultExpandKeys: ['0'],
loading: false, // 加载中
selNode: '',// 后台数据选中的节点
expandKeys: []
}
},
watch: {
filterText (val) {
this.$refs.tree.filter(val)
}
},
props: {
url: {
type: String,
required: true
},
params: {
type: Object,
default () {
return {}
}
},
// 默认全展开
defaultExpandAll: {
type: Boolean,
default: true
},
lazy: {
type: Boolean,
default: false
},
autoLoad: {
type: Boolean,
default: true
},
showCheckbox: {
type: Boolean,
default: false
},
defaultOnlyLeaf: {
// 点击所有节点都能选中,为true时表示:只能选择叶节点
type: Boolean,
default: false
},
defaultExpandOnClickNode: {
// 默认点击节点时展开节点
type: Boolean,
default: false
},
defaultCheckedKeys: {
// 默认勾选节点
type: Array,
default () {
return []
}
},
defaultNodeKey: {
// 默认选中节点(节点id)
type: [Number, String]
},
isDialogTree: {
// 是否是从选择树弹出框打开的树
type: Boolean,
default: false
},
// 能够选择的节点类型,默认为空
nodeType: {
type: String,
default: ''
},
// 是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点
checkOnClickNode: {
type: Boolean,
default: true
},
tenantCode: {
type: String,
default: ''
}
},
methods: {
setExpandKeys (expandKeys) {
this.expandKeys = expandKeys
},
filterNode (value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
loadData (callback, currentKey, checkedKeys, expandKeys) {
this.expandKeys = expandKeys
var headers = {}
if (this.tenantCode !== '') {
headers = {
tenantCode: this.tenantCode
}
}
this.selNode = ''
this.currentNodeKey = currentKey
this.checkedKeys = checkedKeys
this.resetFilterText()
window.app.ajax.post(
this.url,
this.params,
(data, rspMsg) => {
let arrayData = data
if (!Array.isArray(data)) {
arrayData = []
arrayData.push(data)
}
// alert(JSON.stringify(data))
this.nodeData = data
// console.log(this.nodeData)
this.processData(this.nodeData, null)
this.initCheckNodes()
this.loading = false
},
(rspMsg, data) => {
this.$message.error(rspMsg)
this.loading = false
}, headers
)
if (typeof callback === 'function') callback()
},
loadDataByUrl (url, callback, currentKey) {
this.selNode = ''
this.currentNodeKey = currentKey
this.loading = true
this.resetFilterText()
window.app.ajax.get(
url,
this.params,
(data, rspMsg) => {
this.nodeData = data
console.log(this.nodeData)
this.firstData = null
this.processData(this.nodeData, null)
this.initCheckNodes()
this.loading = false
},
(rspMsg, data) => {
this.$message.error(rspMsg)
this.loading = false
}
)
if (typeof callback === 'function') callback()
},
processData (data, parentData) {
// 处理节点数据
data.forEach(_data => {
_data.parent = parentData
if (_data.selectNode === '1') {
this.selNode = _data.id
}
if (_data.children && _data.children.length > 0) {
this.processData(_data.children, _data)
} else {
_data.isLeaf = true // 叶子节点
if (!this.firstData) { // 保存第一层节点数据
this.firstData = _data
}
}
})
},
initCheckNodes () {
// 默认展开的节点
if (this.expandKeys.length > 0) {
this.expandKeys.forEach((oneKey, index) => { // 组织数据
this.defaultExpandKeys.push(oneKey + '')
})
}
// 设置节点状态
if (this.showCheckbox) { // 多选节点
// if (this.defaultCheckedKeys.length > 0) {
// 设置勾选节点
if (this.checkedKeys === undefined) {
this.$nextTick(() => {
this.$refs['tree'].setCheckedKeys(this.defaultCheckedKeys)
})
} else {
this.$nextTick(() => {
this.$refs['tree'].setCheckedKeys(this.checkedKeys)
})
}
// }
} else { // 单选节点
// 如果没有设置默认勾选和展开节点,设置第一层级的第一个叶子节点为勾选状态
if (this.currentNodeKey === undefined || this.currentNodeKey === null) {
if (this.selNode !== '') {
this.currentNodeKey = this.selNode
} else {
this.currentNodeKey = this.firstData.id
}
// if (this.showCheckbox) {
// this.defaultCheckedKeys.push(this.currentNodeKey)
// }
// 要在数据更新视图之后,设置高亮, 设置勾选
this.$nextTick(() => {
this.setCurrentKey(this.currentNodeKey)
// if (this.showCheckbox)
// this.$refs['tree'].setCheckedKeys(this.defaultCheckedKeys)
})
} else {
this.$nextTick(() => {
this.setCurrentKey(this.currentNodeKey)
})
}
}
// if (this.defaultCheckedKeys.length > 0) { // 多选节点
// // 设置勾选节点
// this.$nextTick(() => {
// this.$refs['tree'].setCheckedKeys(this.defaultCheckedKeys)
// })
// } else { // 单选节点
// }
this.$emit('dataFinish')
},
setCurrentKey (key) {
this.$refs['tree'].setCurrentKey(key)
if (!this.isDialogTree) {
// 获取当前被选中节点的 data,主动触发点击事件
this.handleNodeClick(this.$refs['tree'].getCurrentNode(), '', '')
}
},
renderContent (h, { node, data, store }) {
// 渲染tree
return h(
'span',
{
class: 'custom-tree-node'
},
[
data.icon
? h('svg-icon', {
class: 'blue', // 图标颜色
props: {
iconClass: data.icon
}
})
: '',
h('span', {
class: 'mLeft'// 节点名称span新增左边距属性
}, node.label)
]
)
},
addDefaultExpandedKeys (data) {
if (data.parent && data.parent.length > 0) {
this.addDefaultExpandedKeys(data.parent)
} else {
this.defaultExpandKeys.push(data)
}
},
handleNodeClick (data, node, store) {
let checkedArr = this.$refs['tree'].getCheckedNodes()
if (this.defaultOnlyLeaf) { // 只能选择叶子节点
if (data.children && data.children.length > 0) { // 如果没有子节点
} else {
this.$emit('nodeClick', data, node)
}
} else {
this.$emit('nodeClick', data, node, checkedArr)
}
},
handleCheckBox (data, status) {
let checkedArr = this.$refs['tree'].getCheckedNodes()
this.$emit('chechBoxClick', data, checkedArr)
},
handleCurrentChange (data, node, store) {
// console.logconsole.log(data, node)
},
handleNodeExpand (data, node, store) {
// console.log(data, node, store)
},
loadNode (node, resolve) {
if (node.level === 0) {
this.loadData(() => {
resolve(this.nodeData[0])
this.$refs['tree'].setCurrentKey(this.nodeData[0].id)
})
} else {
resolve([])
}
},
// 获取多选节点的id数组(全部)
getCheckedKeysAll () {
return this.$refs['tree'].getCheckedKeys()
},
// 获取多选节点的id字符串(只有叶子节点)
getCheckedKeys () {
var checkedNodes = this.getCheckedNodes()
var p = /[a-z]/i
var selIds = ''
if (this.nodeType === '') { // 没有指定的节点类型
checkedNodes.forEach(element => {
var id = element.id
// if (p.test(element.id)) { // 判断第一位是否是字母,是的话截掉
if (p.test(element.id.substring(0, 1))) { // 判断第一位是否是字母,是的话截掉
id = element.id.substring(1)
}
selIds = selIds + id + ','
})
} else { // 指定了节点类型
checkedNodes.forEach(element => {
if (element.role === this.nodeType) {
var id = element.id
selIds = selIds + id + ','
}
})
}
if (selIds !== '') {
selIds = selIds.substring(0, selIds.length - 1)
}
return selIds
},
setCheckedKeys (key) {
this.$refs['tree'].setCheckedKeys(key)
// 获取当前被选中节点的 data,主动触发点击事件
// this.handleNodeClick(this.$refs['tree'].getCurrentNode())
},
// 获取多选节点的对象数组(全部)
getCheckedNodesAll () {
return this.$refs['tree'].getCheckedNodes()
},
// 获取多选节点的对象数组(只有叶子节点)
getCheckedNodes () {
var checkedNodesAll = this.$refs['tree'].getCheckedNodes()// 所有选中的节点,包括父节点
var checkedNodes = []
// 剔除父节点
checkedNodesAll.forEach(oneNodes => {
if (oneNodes.children && oneNodes.children.length > 0) {
} else {
checkedNodes.push(oneNodes)
}
})
// console.log(checkedNodes)
return checkedNodes
},
// 重置查询条件
resetFilterText () {
this.filterText = ''
}
},
mounted () {
if (!this.lazy) {
if (this.autoLoad) {
this.loading = true
this.loadData(null, this.currentNodeKey, this.checkedKeys, this.expandKeys)
}
}
}
}
</script>
<style>
.mLeft {
margin-left: 6px;
}
.blue {
color: #003585;
}
</style>
<style scoped>
.el-tree-node {
outline: 0;
font-size: 14px;
word-wrap: break-word !important;
line-height: 14px !important;
}
.el-tree-node:focus > .el-tree-node__content {
background-color: #f5f7fa;
}
.el-tree-node.is-drop-inner > .el-tree-node__content .el-tree-node__label {
background-color: #00d1b2;
color: #fff;
}
.el-tree-node__content {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
height: 26px;
cursor: pointer;
}
.el-tree-node__content > .el-tree-node__expand-icon {
padding: 6px;
}
.el-tree-node__content > .el-checkbox {
margin-right: 8px;
}
.el-tree-node__content:hover {
background-color: #f5f7fa;
}
.el-tree.is-dragging .el-tree-node__content {
cursor: move;
}
.el-tree.is-dragging.is-drop-not-allow .el-tree-node__content {
cursor: not-allowed;
}
.el-tree-node__expand-icon {
cursor: pointer;
color: #c0c4cc;
font-size: 12px;
-webkit-transform: rotate(0);
transform: rotate(0);
-webkit-transition: -webkit-transform 0.3s ease-in-out;
transition: -webkit-transform 0.3s ease-in-out;
transition: transform 0.3s ease-in-out;
transition: transform 0.3s ease-in-out, -webkit-transform 0.3s ease-in-out;
}
.el-tree-node__expand-icon.expanded {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.el-tree-node__expand-icon.is-leaf {
color: transparent;
cursor: default;
}
.el-tree-node__label {
font-size: 14px;
}
.el-tree-node__loading-icon {
margin-right: 8px;
font-size: 14px;
color: #c0c4cc;
}
.el-tree-node > .el-tree-node__children {
overflow: hidden;
background-color: transparent;
}
.el-tree-node.is-expanded > .el-tree-node__children {
display: block;
}
.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
background-color: #f0f7ff;
}
.filter-input {
margin-bottom: 10px;
}
</style>