说明:这个菜单授权的代码目前只实现了一、二级菜单授权。
实现效果
代码分成两部分:1.vue页面
<template>
<div class="container">
<a-card :bordered="false">
<span class="back-box" @click="backPage"><a-icon type="left" />返回</span>
<p class="left-top-title">角色</p>
<a-form
layout="horizontal"
:form="form"
:label-col="{ span: 7 }"
:wrapper-col="{ span: 12 }"
>
<a-row type="flex" justify="center">
<a-col :span="20">
<a-form-item label="角色">
<a-input
placeholder="请输入名称"
v-decorator="[
'name',
{ rules: [{ required: true, message: '请输入角色名称' }] },
]"
></a-input>
</a-form-item>
</a-col>
<a-col :span="20">
<a-form-item label="角色描述">
<a-textarea
placeholder="请输入角色描述"
v-decorator="['remark']"
/>
</a-form-item>
</a-col>
</a-row>
</a-form>
<p class="left-top-title">授权</p>
<div class="all-item">
<div
v-for="(item, index) in menuAll"
:key="index"
:class="
item.children.length == 0 || item.close
? 'clear-margin'
: 'check-item'
"
>
<div class="header-box-style">
<a-checkbox
:indeterminate="item.indeterminate"
:checked="item.checkAll"
@change="onCheckAllChange(index, $event)"
>
{{ item.name }}
</a-checkbox>
<p
class="open-or-close"
v-if="item.children.length"
@click="closeShow(index)"
>
{{ item.close ? "展开" : "关闭" }}
</p>
</div>
<br />
<a-checkbox-group
v-if="item.children.length && !item.close"
v-model="item.checklist"
:options="item.children | backArr"
@change="onChange(item.checklist, item.children.length, index)"
/>
</div>
</div>
<div class="bottom-btn-box">
<a-button type="default" @click="backPage">取消</a-button>
<a-button type="primary" @click="submit">确认</a-button>
</div>
</a-card>
</div>
</template>
<script>
import store from "@/store";
import { initData, handleOriginal } from "@/common/permissions/handleCheck.js";
export default {
name: "",
data() {
return {
form: this.$form.createForm(this),
indeterminate: true,
checkAll: false,
permissions: [],
checkedList: [],
menuAll: [],
};
},
filters: {
backArr(value) {
let temp = [];
value.forEach((item) => {
let obj = {
label: item.name,
value: item.id,
};
temp.push(obj);
});
return temp;
},
},
mounted() {
this.getItemRole();
},
methods: {
// 获得角色数据
getItemRole() {
this.$http.get("/role/" + this.$route.query.id).then((res) => {
if (res.code == 1) {
this.form.setFieldsValue({
name: res.data.name,
remark: res.data.remark,
});
this.permissions = res.data.permissions;
this.editId = res.data.id;
this.menuAll = initData(store.state.Menu.routes[0].children.slice());
this.menuAll =
this.permissions.length > 0
? handleOriginal(this.menuAll, this.permissions)
: this.menuAll;
}
});
},
// 提交
submit() {
// 获取选中id集合
this.checkedList = this.backChecked(this.menuAll);
this.form.validateFields((err, fieldsValue) => {
if (err) {
return;
}
let permis = this.checkedList;
this.$set(fieldsValue, "permissions", permis);
this.$set(fieldsValue, "id", this.editId);
this.$http.put("/role", fieldsValue).then((res) => {
if (res.code == 1) {
this.$message.success(res.msg);
this.$router.push("/user/permission");
} else {
this.$message.error(res.msg);
}
});
});
},
// 返回选中id数组
backChecked(list) {
let checkArr = [];
list.forEach((item) => {
if (item.children.length == 0 && item.checkAll) {
checkArr.push(item.id);
}
checkArr.push(...item.checklist);
});
return checkArr;
},
closeShow(index) {
this.menuAll[index].close = !this.menuAll[index].close;
},
// 跳转到列表页
backPage() {
this.$router.push("/user/permission");
},
onChange(list, maxlength, index) {
// 当前选中内容的内容长度
if (list.length == maxlength) {
// 选中父级
this.menuAll[index].checkAll = true;
this.menuAll[index].indeterminate = false;
} else {
if (list.length > 0) {
this.menuAll[index].indeterminate = true;
} else {
this.menuAll[index].checkAll = false;
this.menuAll[index].indeterminate = false;
}
}
},
onCheckAllChange(index) {
// 父控制自己选中显示样式
this.menuAll[index].checkAll = !this.menuAll[index].checkAll;
this.menuAll[index].indeterminate = false;
// 子都选中样式
if (this.menuAll[index].checkAll) {
this.menuAll[index].checklist = this.menuAll[index].children.map(
(item) => {
return item.id;
}
);
} else {
this.menuAll[index].checklist = [];
}
},
},
};
</script>
<style scoped lang="less">
// 返回功能位置修饰
/deep/.ant-card-body {
padding-top: 10px;
}
.back-box {
display: inline-block;
margin-bottom: 15px;
}
.left-top-title {
font-weight: 600;
color: rgb(150, 150, 150);
line-height: 30px;
font-size: 16px;
}
.left-top-title::before {
content: "";
display: inline-block;
width: 4px;
height: 14px;
background: rgb(0, 164, 230);
margin-right: 8px;
margin-bottom: 0px;
}
.clear-margin {
}
.all-item {
height: 480px;
overflow-y: auto;
padding-top: 20px;
}
.check-item {
margin-bottom: 20px;
}
.header-box-style {
width: 100%;
height: 36px;
line-height: 36px;
background: #f5f5f5;
padding-left: 10px;
position: relative;
.open-or-close {
position: absolute;
right: 10px;
top: 0;
color: rgb(0, 164, 230);
cursor: pointer;
}
}
.ant-checkbox-group {
padding-left: 20px;
}
.bottom-btn-box {
display: flex;
justify-content: center;
padding-top: 20px;
.ant-btn-primary {
margin-left: 16px;
}
}
</style>
js.传参处理。
/*
给菜单数据里面添加新的参数
*/
export function initData(arr) {
let menuAll = arr.concat();
let menu = [];
menuAll.forEach((item) => {
let obj = {
...item,
close: false,
indeterminate: false,
checklist: [],
checkAll: false,
};
menu.push(obj);
});
return menu;
}
/*
params:list 是完整菜单
params:arr 后端返回权限数组
*/
export function handleOriginal(arr0, arr) {
let list = arr0.concat();
let menu = arr0.concat();
list.forEach((element, index) => {
if (element.children.length > 0) {
let children = element.children.map((item) => item.id);
menu[index] = { ...element, ...findChecked(children, arr) };
} else {
arr.forEach((item) => {
if (item == element.id) {
menu[index].checkAll = true;
}
});
}
});
return menu;
}
/*
params:child 子id集合
params:permis 子id集合
*/
export function findChecked(child, permis) {
let checklist = [];
let checkAll = false;
let indeterminate = false;
child.forEach((item) => {
permis.forEach((pe) => {
if (item == pe) {
checklist.push(pe);
}
});
});
if (checklist.length == child.length) {
// 子集群都包含
checkAll = true;
indeterminate = false;
} else {
checkAll = false;
indeterminate = true;
if (checklist.length == 0) {
indeterminate = false;
}
}
return {
checklist: checklist,
checkAll: checkAll,
indeterminate: indeterminate,
};
}
最开始项目设计授权的时候,只考虑了二级菜单授权问题。后来研究了一下,项目其实是包含三级菜单的。授权就要落到三级上面,可惜,这个上面手写的授权组件不好用了,实现三级会很麻烦。果断换成了树状。呼呼。
如果用大家知道这个checkbox点击时候,只点击选框才选中点击文字不选中,希望留言一下。现在实现三级主要是卡在这地方了。