代码
- 子组件
// 封装组件
<template>
<div class="treeTransfer">
<!-- 左边 -->
<div class="leftTree">
<div class="list">
<div class="left_lowline">
<p class="left_title">用户列表</p>
</div>
<!-- 搜索 -->
<div class="left_input">
<el-input
v-model="leftSearch"
class="w-50 m-2"
placeholder="搜索"
clearable
:prefix-icon="Search"
/>
</div>
<el-tree
ref="treeRef"
:data="props.fromData"
show-checkbox
:node-key="props.nodeKey"
highlight-current
:props="props.defaultProps"
v-slot="{ node, data }"
>
<div>
{{ data.corgName }} // 父节点
</div>
<div>
{{ data.userName }} // 子节点
</div>
</el-tree>
</div>
</div>
<!-- 中间按钮 -->
<div class="btnDiv">
<div class="mg10" @click="toRight()">
<el-button :icon="Right" circle />
</div>
<div class="mg10" @click="toLeft()">
<el-button :icon="Back" circle />
</div>
</div>
<!-- 右边 -->
<div class="rightTree">
<div class="list">
<div class="left_lowline">
<p class="left_title">已选列表</p>
</div>
<!-- 搜索 -->
<div class="left_input">
<el-input
v-model="rightSearch"
class="w-50 m-2"
placeholder="搜索"
clearable
:prefix-icon="Search"
/>
</div>
<div
class="right_item"
:class="['item', { active: item.active }]"
v-for="(item, index) in toData"
:key="index"
@click="checkNode(item)"
>
{{ item[props.defaultProps.label] }}
<!-- 下拉框 -->
<div>
<el-select
v-model="item.priority"
class="m-2"
placeholder="请选择"
style="width: 100px"
>
<el-option
v-for="item2 in options"
:key="item2.value"
:label="item2.label"
:value="item2.value"
/>
</el-select>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
//@ts-nocheck 解决ts类型报红
import { ref, onMounted } from 'vue';
import { Search } from '@element-plus/icons-vue';
import { useMainStore } from '@/store/index';
import { Right, Back } from '@element-plus/icons-vue';
const mainStore = useMainStore();
const props = defineProps(['nodeKey', 'fromData', 'toData', 'defaultProps']);
const leftSearch = ref('');
const rightSearch = ref('');
const options = [
{
value: '3',
label: '高',
},
{
value: '2',
label: '中',
},
{
value: '1',
label: '低',
},
];
// 定义emit
const emit = defineEmits(['checkVal']);
const treeRef = ref();
// 右侧数据
const toData = ref([]);
onMounted(() => {
if (props.toData.length > 0) {
toData.value = treeRef.value.getCheckedNodes(false, false);
treeRef.value.setCheckedKeys([], false);
}
});
// 去右边
const toRight = () => {
const checkNodes = treeRef.value.getCheckedNodes(false, false);
const newArr = toData.value.concat(checkNodes);
let obj = {};
let peon = newArr.reduce((cur, next) => {
obj[next[props.nodeKey]]
? ''
: (obj[next[props.nodeKey]] = true && cur.push(next));
return cur;
}, []); // 设置cur默认类型为数组,并且初始值为空的数组
toData.value = peon;
treeRef.value.setCheckedKeys([], false);
checkVal();
props.fromData.forEach((item: any) => {
item.children.forEach((left: any) => {
toData.value.forEach((right) => {
if (left.userId == right.userId) { // 已选的不可重复勾选
left.disabled = true;
}
});
});
});
};
// 去左边
const toLeft = () => {
for (var i = 0; i < toData.value.length; i++) {
if (toData.value[i].active) {
toData.value[i].active = false;
toData.value.splice(i, 1);
i -= 1;
}
}
checkVal();
props.fromData.forEach((item: any) => {
item.children.forEach((left: any) => {
left.disabled = false;
toData.value.forEach((right) => {
if (left.userId == right.userId) {
left.disabled = true;
}
});
});
});
};
// 右侧item点击
const checkNode = (item: any) => {
item.active = !item.active;
};
// 返回父组件
const checkVal = () => {
emit('checkVal', toData.value);
};
</script>
- 父组件
<div>
<p class="select_meb">选择固定成员:</p>
<div class="shuttle_frame">
<tree-transfer
ref="treeTransferRef"
node-key="userId"
:fromData="fromData"
:toData="toData"
:defaultProps="transferProps"
@checkVal="checkVal"
>
</tree-transfer>
</div>
<!-- 底部按钮 -->
<div class="modfiy_but">
<el-button @click="saveModfiyManageMeb" type="primary"
>确认</el-button
>
<el-button @click="cancelModfiyManage">取消</el-button>
</div>
</div>
import { ref, onMounted } from 'vue';
let treeTransferRef = ref(); // 树形穿梭框
let fromData = ref([]); // 树形数据
let toData = ref([]); // 选中的ids数据
const transferProps = ref({
label: 'userName',
children: 'children',
disabled: 'disabled',
});
// 子组件树形穿梭框返回
const checkVal = (val: any) => {
toData.value = val;
};
// 获取左侧用户列表
async function getUserList() {
let params = {
userId: '',
};
const res = await getCompanyListById(params);
if (res.code == 200) {
if (res.data.result == 1) {
fromData.value = res.data.returnMsg;
// 根据返回数据处理.....
} else {
ElMessage.error(res.message);
}
}
}
********************************************************************
// 后端要求传参格式
[{"userId":"28586","priority":"2"},{"userId":"28588","priority":"3"}]
// 确认
function saveModfiyManageMeb() {
let rightList: any[] = [];
toData.value.forEach((element) => {
let param = { userId: '', priority: '' };
param.userId = element.userId;
param.priority = element.priority;
rightList.push(param);
});
var existUserStr = JSON.stringify(rightList);
let params = {
groupId: '',
userDataStr: existUserStr,
};
saveAndModifyUserOfGroup(params).then((res) => {
if (res.code == 200) {
ElMessage.success('修改成功');
} else {
ElMessage.error(res.message);
}
});
}
参考了一位大佬的,当时忘记复制链接了。