Files
admin-govern/src/views/govern/device/planData/components/treeTransfers.vue
2024-12-25 10:53:07 +08:00

292 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="transferTreeBox" v-if="fromData.length != 0 || toData.length != 0">
<!-- 左侧待选内容 -->
<div class="SelectBox">
<div class="boxTitle" @click="clickAllSelect">未绑定数据</div>
<div class="boxCenter">
<el-input maxlength="32" show-word-limit v-model.trim="filterText" :suffix-icon="Search"
style="width: 100%" placeholder="请输入搜索内容" clearable></el-input>
<el-tree ref="leftTree" default-expand-all :data="leftData" :props="defaultProps" show-checkbox
node-key="id" :filter-node-method="filterNode">
<template #default="{ node, data }">
<span class="custom-tree-node">
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }"
v-if="data.icon" />
<span style="margin-left: 4px">{{ node.label }}</span>
</span>
</template>
</el-tree>
</div>
</div>
<!-- 中间穿梭按钮 -->
<div class="transferBtn">
<el-button type="primary" @click="towardsRight">
绑定
<el-icon>
<ArrowRight />
</el-icon>
</el-button>
<el-button type="primary" @click="towardsLeft">
<el-icon>
<ArrowLeft />
</el-icon>
解绑</el-button>
</div>
<!-- 右侧已选内容 -->
<div class="SelectBox">
<div class="boxTitle" @click="clickCancelAllSelect">已绑定数据</div>
<div class="boxCenter">
<el-input maxlength="32" show-word-limit v-model.trim="filterText1" :suffix-icon="Search"
style="width: 100%" placeholder="请输入搜索内容" clearable></el-input>
<el-tree ref="rightTree" default-expand-all :data="rightData" :props="defaultProps" show-checkbox
node-key="id" :filter-node-method="filterNode">
<template #default="{ node, data }">
<span class="custom-tree-node">
<Icon :name="data.icon" style="font-size: 16px" :style="{ color: data.color }"
v-if="data.icon" />
<span style="margin-left: 4px">{{ node.label }}</span>
</span>
</template>
</el-tree>
</div>
</div>
</div>
</template>
<script setup>
import { Search, ArrowRight, ArrowLeft } from '@element-plus/icons-vue'
</script>
<script>
import { useConfig } from '@/stores/config'
export default {
layout: 'login',
props: ['fromData', 'toData'],
data() {
return {
defaultProps: {
children: 'children',
label: 'name'
},
leftData: [],
rightData: [],
filterText: '',
filterText1: ''
}
},
watch: {
fromData(val, oldVal) {
if (val) {
this.leftData = val
const config = useConfig()
this.leftData.forEach(item => {
item.icon = 'el-icon-HomeFilled'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach(item2 => {
item2.icon = 'el-icon-List'
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach(item3 => {
item3.icon = 'el-icon-Platform'
item3.color = config.getColorVal('elementUiPrimary')
if (item3.comFlag === 1) {
item3.color = '#e26257 !important'
}
})
})
})
}
},
toData(val, oldVal) {
if (val) {
this.rightData = val
const config = useConfig()
this.$emit('getData', this.rightData)
this.rightData.forEach(item => {
item.icon = 'el-icon-HomeFilled'
item.color = config.getColorVal('elementUiPrimary')
item.children.forEach(item2 => {
item2.icon = 'el-icon-List'
item2.color = config.getColorVal('elementUiPrimary')
item2.children.forEach(item3 => {
item3.icon = 'el-icon-Platform'
item3.color = config.getColorVal('elementUiPrimary')
if (item3.comFlag === 1) {
item3.color = '#e26257 !important'
}
})
})
})
}
},
filterText(val) {
this.$refs.leftTree.filter(val)
},
filterText1(val) {
this.$refs.rightTree.filter(val)
}
},
mounted() {
this.$forceUpdate()
this.$emit('getData', this.rightData)
},
methods: {
// 点击向右穿梭
towardsRight() {
// (leafOnly, includeHalfChecked) 接收两个 boolean 类型的参数,
// 1. 是否只是叶子节点,默认值为 false 2. 是否包含半选节点,默认值为 false
this.$nextTick(() => {
const checkedNodes = this.$refs.leftTree.getCheckedNodes(false, true) // 包含半选
const checkedKeys = this.$refs.leftTree.getCheckedKeys(false)
const copyNodes = JSON.parse(JSON.stringify(checkedNodes))
copyNodes.forEach(x => {
x.children = []
if (!this.$refs.rightTree.getNode(x.id)) {
this.$refs.rightTree.append(x, x.pid)
}
})
checkedKeys.forEach(x => {
this.$refs.leftTree.remove(x)
})
this.afterToward()
this.$forceUpdate()
})
},
// 点击向左穿梭
towardsLeft() {
this.$nextTick(() => {
const checkedNodes = this.$refs.rightTree.getCheckedNodes(false, true) // 包含半选
const checkedKeys = this.$refs.rightTree.getCheckedKeys(false)
const copyNodes = JSON.parse(JSON.stringify(checkedNodes))
copyNodes.forEach(x => {
x.children = []
if (!this.$refs.leftTree.getNode(x.id)) {
this.$refs.leftTree.append(x, x.pid)
}
})
checkedKeys.forEach(x => {
this.$refs.rightTree.remove(x)
})
this.$forceUpdate()
this.afterToward()
})
},
// 点击全选
clickAllSelect() {
return;
this.$refs.leftTree.setCheckedNodes(this.leftData)
this.towardsRight()
},
// 点击取消全选
clickCancelAllSelect() {
return;
this.$refs.rightTree.setCheckedNodes(this.rightData)
this.towardsLeft()
},
// 数据穿梭后
afterToward() {
this.$refs.leftTree.setCheckedKeys([])
this.$refs.rightTree.setCheckedKeys([])
this.$emit('getData', this.rightData)
this.$forceUpdate()
},
//组件搜索
filterNode(value, data, node) {
if (!value) return true
// return data.name.includes(value)
if (data.name) {
return this.chooseNode(value, data, node)
}
},
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配则返回该节点以及其下的所有子节点如果参数是子节点则返回该节点的父节点。name是中文字符enName是英文字符.
chooseNode(value, data, node) {
if (data.name.indexOf(value) !== -1) {
return true
}
const level = node.level
// 如果传入的节点本身就是一级节点就不用校验了
if (level === 1) {
return false
}
// 先取当前节点的父节点
let parentData = node.parent
// 遍历当前节点的父节点
let index = 0
while (index < level - 1) {
// 如果匹配到直接返回此处name值是中文字符enName是英文字符。判断匹配中英文过滤
if (parentData.data.name.indexOf(value) !== -1) {
return true
}
// 否则的话再往上一层做匹配
parentData = parentData.parent
index++
}
// 没匹配到返回false
return false
}
}
}
</script>
<style lang="scss" scoped>
.transferTreeBox {
display: flex;
width: 100%;
justify-content: space-around;
padding: 10px 10px 50px 10px;
.SelectBox {
height: 400px;
width: 40%;
color: #fff;
position: relative;
.boxTitle {
background: var(--el-color-primary);
height: 40px;
line-height: 40px;
text-align: center;
border-bottom: 2px solid #eee;
cursor: pointer;
border: 2px solid var(--el-color-primary);
}
.boxCenter {
height: 100%;
width: 100%;
overflow-y: scroll;
background: #fff;
padding: 0 10px;
border: 1px solid #eee;
.el-input {
margin: 10px 0;
}
}
}
.transferBtn {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100px;
flex: 1;
.pickBtn {
height: 40px;
width: 40px;
background: var(--el-color-primary);
color: #fff;
font-weight: 700;
font-size: 20px;
border-radius: 5px;
margin-top: 10px;
text-align: center;
line-height: 40px;
cursor: pointer;
}
}
}
</style>