效果:
默认选择“全部范围”,不展示组织结构tree
选择“组织结构”显示组织结构tree,搜索自动展开相应tree节点,并标红显示
组件代码:
<template>
<div>
<a-modal
:title="title"
:visible="visible"
:confirm-loading="confirmLoading"
@ok="handleSubmit"
@cancel="handleCancel"
>
<b>{{ tip }}</b><br/><br/>
<a-radio-group v-model="value" @change="onChangeRadio">
<a-radio :style="radioStyle" :value="1">
全部范围
</a-radio>
<a-radio :style="radioStyle" :value="2">
选择组织结构
</a-radio>
</a-radio-group>
<div v-if="value === 2" class="tree-box">
<a-input-search v-model="searchStr" placeholder="输入搜索项" style="width:200px;" @change="onSearch"></a-input-search>
<a-tree
v-model="checkedKeys"
checkable
:auto-expand-parent="autoExpandParent"
:defaultExpandAll="defaultExpandAll"
:expanded-keys="expandedKeys"
:tree-data="treeData"
:selected-keys="selectedKeys"
:replaceFields="replaceFields"
@expand="onExpand"
@select="onSelect"
>
<template slot='title' slot-scope="{name}">
<span v-html="name.replace(new RegExp(searchValue, 'g'),'<span style=color:#f50>' + searchValue + '</span>')"></span>
</template>
</a-tree>
</div>
</a-modal>
</div>
</template>
<script>
import { getTree } from '@/api/tree';
export default {
name: 'TreeComponent',
// 由于是单独抽取的组件,所以加了props
props: {
visible: {
type: Boolean,
default: false,
},
confirmLoading: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '共享'
},
tip: {
type: String,
default: '请选择:'
},
},
data() {
return {
value: 1,
radioStyle: {
display: 'block',
height: '30px',
lineHeight: '30px',
},
backupsExpandedKeys: [],
autoExpandParent: true,
defaultExpandAll: true,
expandedKeys: [],
selectedKeys: [],
searchStr: '',
searchValue: '',
checkedKeys: [],
treeData: [],
replaceFields: {
title: 'name',
key: 'id'
},
};
},
watch: {
checkedKeys(val) {
// this.expandedKeys = val
},
visible() {
this.value = 1
this.checkedKeys = []
}
},
methods: {
// 调用接口获取组织结构tree
async getAllTree() {
let res = await getTree()
this.treeData = res?.data || []
},
// 确定
handleSubmit() {
this.$emit('complete', this.checkedKeys)
},
// 取消-关闭弹框
handleCancel() {
this.$emit('cancle')
},
// 切换单选框触发
onChangeRadio(e) {
this.checkedKeys = []
this.expandedKeys = [];
},
// 展开/收起节点时触发
onExpand(expandedKeys) {
this.expandedKeys = expandedKeys;
this.autoExpandParent = false;
},
// 点击复选框触发
onCheck(checkedKeys) {
this.checkedKeys = checkedKeys;
},
// 点击树节点触发
onSelect(selectedKeys, info) {
this.selectedKeys = selectedKeys;
},
// 点击搜索进行模糊筛选
onSearch() {
const _this = this;
_this.searchValue = _this.searchStr;
if (_this.searchValue === '') {
_this.expandedKeys = [];
} else {
_this.expandedKeys = [];
_this.backupsExpandedKeys = [];
let candidateKeysList = _this.getkeyList(_this.searchValue, _this.treeData, []);
candidateKeysList.map(
item => {
let key = _this.getParentKey(item, this.treeData);
if (key && !_this.backupsExpandedKeys.some(item => item === key)) {
_this.backupsExpandedKeys.push(key);
}
}
)
let length = this.backupsExpandedKeys.length;
for (let i = 0; i < length; i++) {
_this.getAllParentKey(_this.backupsExpandedKeys[i], _this.treeData)
}
_this.expandedKeys = _this.backupsExpandedKeys.slice();
_this.autoExpandParent = true
}
},
// 获取节点中含有value的所有key集合
getkeyList(value, tree, keyList) {
for (let i = 0; i < tree.length; i++) {
let node = tree[i];
node.scopedSlots = { title: 'title' }
if (node.name.indexOf(value) > -1) {
keyList.push(node.id);
}
if (node.children) {
this.getkeyList(value, node.children, keyList);
}
}
return keyList;
},
// 该递归主要用于获取key的父亲节点的key值
getParentKey(key, tree) {
let parentKey;
for (let i = 0; i < tree.length; i++) {
const node = tree[i];
if (node.children) {
if (node.children.some(item => item.id === key)) {
parentKey = node.id;
} else if (this.getParentKey(key, node.children)) {
parentKey = this.getParentKey(key, node.children);
}
}
}
return parentKey;
},
// 获取该节点的所有祖先节点
getAllParentKey(key, tree) {
let parentKey
if (key) {
parentKey = this.getParentKey(key, tree);
if (parentKey) {
if (!this.backupsExpandedKeys.some(item => item === parentKey)) {
this.backupsExpandedKeys.push(parentKey)
}
this.getAllParentKey(parentKey, tree)
}
}
},
},
created() {
this.getAllTree()
},
};
</script>
<style>
.tree-box{
height: 50%;
}
</style>
在其他页面中使用组件
<template>
<a-button
title="共享"
@click="showModal(id)"
/>
<TreeComponent
:visible="visible"
:confirmLoading="confirmLoading"
@complete="handleSubmit"
@cancle="visible = false"
/>
</template>
<script>
import TreeComponent from './TreeComponent'
export default {
name: ' PageComponent',
data() {
return {
id: '',
visible: false, // 控制弹框modal隐藏|显示
confirmLoading: false, // 确定按钮的loading
checkedKeys: [], // 选中的组织机构的id,这里为平铺
}
},
methods:{
// 打开弹框
async showModal(id) {
this.confirmLoading = false
this.visible = true
this.id = id
},
// 确定共享
handleSubmit(checkedKeys) {
this.confirmLoading = true
this.checkedKeys = checkedKeys
const params = {
id: this.id,
checkedTreeList: checkedKeys,
}
// 调用共享接口
share(params).then(res => {
if (res.statusCode === 200) {
res.message.success('成功')
this.handleGetList() // 重新渲染列表
}
}).catch(err => {
err.message.error('失败:' + err.message)
}).finally(() => {
this.confirmLoading = false
this.visible = false
})
},
}