element+plus级联表格父级子级选择
存在的问题(使用的是"element-plus": “^2.2.28”,“vue”: “^3.2.45”,)
使用this.$refs.selectTable.toggleRowSelection(j, true);去勾选父级时,会将子级即子级以下的全部勾选;
但是我想要的只是勾选父级,但是又不想去除勾选父级时,勾选子级的功能!
解决思路,勾选父级时先将父级以下的全部子级取消勾选,再将原本勾选了的一个一个勾选!
最终效果
废话不多说,上代码
<template>
<el-dialog
:title="titleShow"
destroy-on-close
:model-value="roleDialogVisible"
:close-on-click-modal="false"
@close="roleDialogToClose(false)"
width="40%"
top="10vh"
>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="角色信息" name="first">
<el-form ref="formRef" label-width="120px" :model="formModelRole" :rules="formRules">
<input type="text" name="account" style="display: none" />
<input type="password" name="password" style="display: none" />
<el-form-item label="角色标识" prop="roleCode">
<el-input
v-model.trim="formModelRole.roleCode"
placeholder="请输入角色标识"
clearable
maxlength="20"
:show-word-limit="true"
></el-input>
</el-form-item>
<el-form-item label="角色名称" prop="roleName">
<el-input
v-model.trim="formModelRole.roleName"
placeholder="请输入角色名称"
clearable
maxlength="20"
:show-word-limit="true"
></el-input>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formModelRole.status">
<el-radio-button label="0">禁用</el-radio-button>
<el-radio-button label="1">启用</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="描述" prop="roleDesc">
<el-input
type="textarea"
rows="2"
placeholder="请输入描述信息"
resize="none"
maxlength="100"
:show-word-limit="true"
v-model.trim="formModelRole.roleDesc"
></el-input>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="分配权限" name="second" :disabled="type === 'add'">
<el-form ref="formRefJurisdiction" label-width="120px" :model="formModelJurisdiction">
<el-form-item label="过期时间" prop="timeOut">
<el-badge :value="messageTell" class="item">
<el-date-picker
v-model="formModelJurisdiction.timeOut"
format="YYYY-MM-DD HH:mm:ss"
type="datetime"
placeholder="请选择过期时间!"
>
</el-date-picker>
</el-badge>
</el-form-item>
<el-form-item label="功能菜单" prop="roleCode">
<el-table
ref="selectTable"
:data="tableData"
style="width: 100%; max-height: 500px; margin-bottom: 20px; overflow: auto"
@select="selectbox"
@select-all="select_All"
row-key="id"
border
default-expand-all
height="345px"
size="small"
@selection-change="selectChange"
>
<el-table-column type="selection" width="50" />
<el-table-column prop="menuName" label="菜单" width="200"></el-table-column>
<el-table-column prop="actionList" width="500" label="操作">
<template #default="scope">
<el-checkbox-group v-model="formModelJurisdiction.grantActions">
<el-checkbox
v-for="(item, index) in scope.row.actionList"
@change="(checked) => log(checked, scope.row)"
:key="index"
:label="item.authorityId"
name="type"
>
<span :title="item.actionDesc">{{ item.actionName }}</span>
</el-checkbox>
</el-checkbox-group>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="角色成员" name="third" :disabled="type === 'add'">
<el-transfer
v-model="selectRole"
:titles="['选择用户', '已选择用户']"
filterable
:props="{
key: 'userId'
}"
:filter-method="filterMethod"
:render-content="transferRender"
:data="data"
></el-transfer>
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="roleDialogToClose(false)">取 消</el-button>
<el-button type="primary" @click="save()">保 存</el-button>
</template>
</el-dialog>
</template>
<script lang="ts">
import dayjs from 'dayjs';
import _ from 'lodash-es';
import { defineComponent } from 'vue';
import {
addRole,
updateRole,
GetUserToRole,
allUserInfo,
addRoleToUser,
getJurisdictionRole,
getJurisdiction,
addJurisdictionRole
} from '../service/index';
export default defineComponent({
name: 'editorRoleDialog',
props: {
type: {
type: String,
default: 'add'
},
roleDialogVisible: {
type: Boolean
},
formModel: {
type: Object
}
},
emits: ['roleDialogClose', 'save'],
watch: {
formModel(val) {
this.formModelRole = val;
},
formModelJurisdiction(val) {
if (val.timeOut && new Date(val.timeOut) < new Date()) {
this.messageTell = '授权已过期';
} else {
this.messageTell = '授权已过期';
}
}
},
data() {
return {
activeName: 'first',
titleShow: '角色信息',
formModelRole: {
roleCode: '',
roleName: '',
status: '1',
roleDesc: ''
},
selectRole: [],
showRight: [],
data: [],
formModelJurisdiction: {
timeOut: '',
grantActions: []
},
tableData: [],
selectJurisdiction: [],
clickSelects: [],
formRules: {
roleCode: [
{ required: true, message: '角色标识不能为空', trigger: 'blur' },
{
required: true,
validator: (rule: any, value: any, callback: any) => {
const reg = /[^a-zA-Z]/g;
if (reg.test(value) && value.indexOf('_') != -1) {
let reg1 = /[0-9]/g;
value.split().map((v) => {
if (reg1.test(v)) {
return callback(new Error('角色标识为字母下划线的组合'));
}
});
return callback();
} else {
return callback(new Error('角色标识为字母下划线的组合'));
}
},
trigger: 'blur'
}
],
roleName: [
{ required: true, message: '角色名称不能为空', trigger: 'blur' },
{
required: true,
validator: (rule: any, value: any, callback: any) => {
const reg = /[^u4e00-u9fa5\w]/g;
if (!reg.test(value)) {
callback(new Error('角色名称必须为中文'));
} else {
return callback();
}
},
trigger: 'blur'
}
]
},
checkedJson: [],
messageTell: '',
status_checked: true,
fatherSelectArray: []
};
},
mounted() {},
methods: {
roleDialogToClose(refresh: boolean) {
this.$refs.formRef.resetFields();
this.$emit('roleDialogClose', refresh);
this.selectJurisdiction = [];
this.formModelJurisdiction = {};
this.activeName = 'first';
this.titleShow = '角色信息';
// this.$refs.selectTable.clearAll()
this.$refs.selectTable.clearSelection();
this.formModelJurisdiction.grantActions = [];
this.selectJurisdiction = [];
this.checkedJson = [];
},
transferRender(h, option) {
return option.userName + '(' + option.nickName + ')';
},
selectChange(selection) {
// console.log();
this.clickSelects = _.cloneDeep(selection);
},
toggleRowSelection() {},
log(item, value) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
// let that = this
if (item) {
this.checkedJson = [];
this.$refs.selectTable.toggleRowSelection(value, true);
let json = _.cloneDeep(this.clickSelects);
let array = json.map((v) => {
return v.authorityId;
});
this.tableData.map((v) => {
if (v.children && v.children.length > 0) {
this.pdDeep(v, value, array);
if (this.checkedJson.length > 0) {
this.checkedJson = this.Deduplication(this.checkedJson, 'id');
this.checkedJson.map((j) => {
this.$refs.selectTable.toggleRowSelection(j, true);
this.soloveProblem(j, array);
});
}
return;
}
});
} else {
//表格内部选择框,行内全部取消,取消右侧选中
// if (!this.pdInArray(value, this.formModelJurisdiction.grantActions)) {
// this.$refs.selectTable.toggleRowSelection(value, false)
// // 如果右侧只有当前行选中,取消父级选中
// this.status_checked = true
// this.tableData.map((v) => {
// if (v.children && v.children.length > 0) {
// v.children.map((j) => {
// if (j.menuName === value.menuName) {
// let array = []
// this.clickSelects.map((v) => {
// array.push(v.authorityId)
// })
// for (let n = 0; n < v.children.length; n++) {
// if (array.includes(v.children[n].authorityId)) {
// this.status_checked = false
// }
// }
// if (this.status_checked) {
// this.$refs.selectTable.toggleRowSelection(v, false)
// }
// }
// })
// }
// })
// }
}
},
//用来判断需要选中的父级元素,
/*array是用来判断的数组,里面包含了需要选中的父级
*value1时选中的子级元素
*array1是已经选中的元素的key的数组
* */
pdDeep(array, value1, array1) {
if (array.children && array.children.length > 0) {
for (let i = 0; i < array.children.length; i++) {
if (array.children[i].id === value1.parentId) { //找到所选子级的父级
if (array1 && array1.length > 0) {
if (!array1.includes(array.children[i].authorityId)) { //如果当前父级被选中就不放入this.checkedJson中
this.checkedJson.unshift(array.children[i]);
this.tableData.map((v) => { //这里是再去向上找到该父级的父级,逐层向上
this.pdDeep(v, array.children[i], array1);
});
}
} else { //如果已经选中的数组为空,则直接推入父级,然后逐层向上
this.checkedJson.unshift(array.children[i]);
this.tableData.map((v) => {
this.pdDeep(v, array.children[i], array1);
});
}
} else if (array.id === value1.parentId) { //直接判断array是否为所选子级的父级
if (array1 && array1.length > 0) {
if (!array1.includes(array.authorityId)) {
this.checkedJson.unshift(array);
}
} else {
this.checkedJson.unshift(array);
}
} else if (array.children[i]) { //这里是逐层向下,找到直接父级
this.pdDeep(array.children[i], value1, array1);
}
}
}
},
//递归的全部选择与全部取消,逐级向下操作
selectAll(array, status) {
try {
if (array.children && array.children.length > 0) {
array.children.map((v) => {
setTimeout(() => {
this.$refs.selectTable.toggleRowSelection(v, status);
v.actionList.map((j) => {
if (status) {
if (this.formModelJurisdiction.grantActions.indexOf(j.authorityId) === -1) {
this.formModelJurisdiction.grantActions.push(j.authorityId);
}
} else {
if (this.formModelJurisdiction.grantActions.indexOf(j.authorityId) !== -1)
this.formModelJurisdiction.grantActions.splice(
this.formModelJurisdiction.grantActions.indexOf(j.authorityId),
1
);
}
});
this.selectAll(v, status);
}, 10);
});
} else if (array.actionList && array.actionList.length) {
array.actionList.map((m) => {
if (status) {
if (this.formModelJurisdiction.grantActions.indexOf(m.authorityId) === -1) {
this.formModelJurisdiction.grantActions.push(m.authorityId);
}
} else {
if (this.formModelJurisdiction.grantActions.indexOf(m.authorityId) !== -1)
this.formModelJurisdiction.grantActions.splice(
this.formModelJurisdiction.grantActions.indexOf(m.authorityId),
1
);
}
});
}
} catch (e) {
console.log(e);
}
},
//表格头的全选与取消
select_All(selection) {
if (selection && selection.length > this.tableData.length) {
this.tableData.map((v) => {
this.selectAll(v, true);
});
} else {
this.formModelJurisdiction.grantActions = [];
this.tableData.map((v) => {
this.selectAll(v, false);
});
}
},
pdChildren() {},
selectbox(selection, row) {
setTimeout(() => {
this.checkedJson = [];
if (selection.includes(row)) {
this.$refs.selectTable.toggleRowSelection(row, true);
let json = _.cloneDeep(this.clickSelects);
let array = json.map((v) => {
return v.authorityId;
});
console.log(array, 'array');
this.tableData.map((v) => {
if (v.children && v.children.length > 0) {
this.pdDeep(v, row, array);
if (this.checkedJson.length > 0) {
this.checkedJson = this.Deduplication(this.checkedJson, 'id');
this.checkedJson.map((j) => {
this.$refs.selectTable.toggleRowSelection(j, true);
this.soloveProblem(j, array);
});
}
}
});
if (row.actionList && row.actionList.length > 0) {
row.actionList.map((v) => {
if (this.formModelJurisdiction.grantActions.indexOf(v.authorityId + '') === -1) {
this.formModelJurisdiction.grantActions.push(v.authorityId);
}
});
}
if (row.children && row.children.length > 0) {
this.selectAll(row, true);
} else {
if (row.actionList && row.actionList.length > 0) {
row.actionList.map((v) => {
if (this.formModelJurisdiction.grantActions.indexOf(v.authorityId + '') === -1) {
this.formModelJurisdiction.grantActions.push(v.authorityId);
}
});
}
}
} else {
if (row.actionList && row.actionList.length > 0) {
row.actionList.map((v) => {
if (this.formModelJurisdiction.grantActions.indexOf(v.authorityId + '') !== -1) {
this.formModelJurisdiction.grantActions.splice(
this.formModelJurisdiction.grantActions.indexOf(v.authorityId + ''),
1
);
}
});
}
if (row.children && row.children.length > 0) {
this.selectAll(row, false);
} else {
if (row.actionList && row.actionList.length > 0) {
row.actionList.map((v) => {
if (this.formModelJurisdiction.grantActions.indexOf(v.authorityId + '') !== -1) {
this.formModelJurisdiction.grantActions.splice(
this.formModelJurisdiction.grantActions.indexOf(v.authorityId + ''),
1
);
}
});
}
}
//表格取消选择子级时,全部取消,取消父级
if (row) {
setTimeout(() => {
let Array = this.clickSelects.map((v) => {
return v.authorityId;
});
console.log(Array, 'Array');
this.fatherSelectArray = [];
this.closeSelect(row, this.tableData);
if (this.fatherSelectArray && this.fatherSelectArray.length > 0) {
this.fatherSelectArray = this.Deduplication(this.fatherSelectArray, 'id');
this.fatherSelectArray.map((q) => {
let status = false;
q.children.map((m) => {
if (Array.includes(m.authorityId)) {
status = true;
}
});
if (!status) {
this.$refs.selectTable.toggleRowSelection(q, false);
}
});
}
}, 100);
}
}
}, 200);
},
async save() {
switch (this.activeName) {
case 'first':
if (this.type == 'add') {
this.$refs.formRef.validate(async (valid) => {
if (!valid) return;
try {
await addRole({
roleCode: this.formModelRole.roleCode,
roleName: this.formModelRole.roleName,
status: this.formModelRole.status,
roleDesc: this.formModelRole.roleDesc
});
this.$message({
type: 'success',
message: '添加角色成功'
});
this.roleDialogToClose(true);
} catch (error) {
console.log(error);
}
});
} else {
this.$refs.formRef.validate(async (valid) => {
if (!valid) return;
try {
await updateRole({
roleId: this.formModelRole.roleId,
roleCode: this.formModelRole.roleCode,
roleName: this.formModelRole.roleName,
status: this.formModelRole.status,
roleDesc: this.formModelRole.roleDesc
});
this.$message({
type: 'success',
message: '修改角色成功'
});
this.roleDialogToClose(true);
} catch (error) {
console.log(error);
}
});
}
break;
case 'second': {
let array = [];
this.clickSelects.map((v) => {
array.push(v.authorityId);
});
array.push(...this.formModelJurisdiction.grantActions);
let string = array.join(',');
console.log(string, 'string');
try {
await addJurisdictionRole({
roleId: this.formModelRole.roleId,
expireTime: this.formModelJurisdiction.timeOut
? dayjs(this.formModelJurisdiction.timeOut).format('YYYY-MM-DD HH:mm:ss')
: '',
authorityIds: string
});
this.$message({
type: 'success',
message: '授权成功'
});
this.roleDialogToClose(true);
} catch (error) {
console.log(error);
}
break;
}
case 'third':
try {
await addRoleToUser({
roleId: this.formModelRole.roleId,
userIds: this.selectRole.join(',')
});
this.$message({
type: 'success',
message: '修改成功'
});
this.selectRole = [];
this.roleDialogToClose(true);
} catch (error) {
console.log(error);
}
break;
default:
break;
}
// this.$refs.selectTable.clearSelection();
this.formModelJurisdiction.grantActions = [];
this.selectJurisdiction = [];
this.checkedJson = [];
},
//切换tab时
async handleClick(tab) {
this.titleShow = tab.props.label;
this.$nextTick(async () => {
switch (this.activeName) {
//权限组装树以及选中该选中的
case 'second':
try {
let data1 = await getJurisdiction();
let { data } = await getJurisdictionRole({
roleId: this.formModelRole.roleId
});
this.formModelJurisdiction.grantActions = [];
this.selectJurisdiction = [];
this.formModelJurisdiction.timeOut = data[0] ? data[0].expireTime : '';
if (new Date(this.formModelJurisdiction.timeOut) < new Date()) {
this.messageTell = '授权已过期';
} else {
this.messageTell = '';
}
let array = [];
let array2 = [];
let array3 = [];
data1.data.map((v) => {
array3.push(v.authorityId);
v.id = v.menuId;
array.push(v.menuId);
});
//组装数据
data1.data.map((v) => {
if (array.includes(v.parentId) && v.parentId != '0') {
array2.push(v);
if (data1.data[array.indexOf(v.parentId)].children) {
console.log(1);
} else {
data1.data[array.indexOf(v.parentId)].children = [];
}
data1.data[array.indexOf(v.parentId)].children.push(v);
}
});
array2.map((v) => {
data1.data.splice(data1.data.indexOf(v), 1);
});
this.tableData = data1.data;
data.map((v) => {
v.id = v.authorityId;
if (!array3.includes(v.authorityId)) this.formModelJurisdiction.grantActions.push(v.authorityId);
this.selectJurisdiction.push(v.authorityId);
});
this.checkedJson = [];
this.BackShow(this.selectJurisdiction, this.tableData);
this.Deduplication(this.checkedJson, 'id');
this.$nextTick(function () {
this.checkedJson.map((j) => {
this.$refs.selectTable.toggleRowSelection(j, true);
this.soloveProblem(j, this.checkedJson);
});
});
} catch (error) {
console.log(error);
}
break;
case 'third':
try {
let userinfo = await allUserInfo();
let userall = userinfo.data;
let { data } = await GetUserToRole({
roleId: this.formModelRole.roleId
});
data.map((v) => {
this.selectRole.push(v.userId);
});
this.data = userall;
} catch (error) {
console.log(error);
}
break;
default:
break;
}
});
this.checkedJson = [];
},
filterMethod(query, item) {
return item.userName.includes(query);
},
//取消时判断id是否在数组中,不在返回false
pdInArray(idarray, array) {
let status = false;
if (idarray && array && array.length > 0) {
for (let i = 0; i < idarray.actionList.length; i++) {
if (array.includes(idarray.actionList[i].authorityId)) {
status = true;
}
}
return status;
} else {
return status;
}
},
// 取消选中,解决选中父级其子级也被选中的问题
/*
* parent为传入的父级元素
* array已经选中的key组成的数组
* */
soloveProblem(parent, array) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
let that = this;
function dgselect(parent, array) {
//如果本身是选中的就继续选中
if (parent.children && parent.children.length > 0) {
if (array && array.length > 0) {
parent.children.map((j) => {
if (array.indexOf(j.authorityId) != -1) {
that.$refs.selectTable.toggleRowSelection(j, true);
} else if (j.children && j.children.length > 0) {
dgselect(j, array); //逐级向下去判断选择与否
}
});
}
}
}
//先全部取消子级,及子子级的选中
if (parent.children && parent.children.length > 0) {
parent.children.map((v) => {
this.$refs.selectTable.toggleRowSelection(v, false);
});
}
dgselect(parent, array);
},
// 去重
Deduplication(array, byWhat) {
if (array.length > 0) {
for (let i = array.length - 1; i >= 1; i--) {
for (let j = i - 1; j >= 0; j--) {
if (array[i][byWhat] === array[j][byWhat]) {
array.splice(i, 1);
i = i - 1;
}
}
}
return array;
}
},
// 回显问题
/* array需要选中的key组成的数组
* array1为树形表格的全部数据
* */
BackShow(array, array1) {
if (array && array.length > 0) {
array.map((id) => {
array1.map((v) => {
if (id === v.authorityId) {
this.checkedJson.push(v);
} else if (v.children && v.children.length > 0) {
v.children.map((j) => {
this.BackShow([id], v.children);
});
}
});
});
}
},
// 级联取消
closeSelect(row, table, father = null) {
if (table && table.length > 0) {
table.map((v) => {
if (v.id === row.parentId) {
this.fatherSelectArray.push(v);
if (father) {
this.fatherSelectArray.push(father);
}
} else if (v.children && v.children.length > 0) {
this.closeSelect(row, v.children, v);
}
});
}
}
}
});
</script>
<style lang="scss" scoped>
:deep(.el-divider) {
margin: 0 !important;
}
:deep(.el-transfer) {
width: 100% !important;
--el-transfer-panel-width: 38%;
}
.item {
margin-top: 6px;
margin-right: 40px;
}
</style>
功能尚未完善,勿喷!