Vue 菜单管理,全选 半选 el-checkbox-group el-checkbox indeterminate
注意:indeterminate = false ,表示没被选中,提交的时候没有值
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>权限管理系统</title>
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
<script src="https://unpkg.com/vue@3"></script>
<script src="https://unpkg.com/element-plus"></script>
<style>
.menu-container {
max-width: 800px;
margin: 20px auto;
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.menu-row {
margin-bottom: 20px;
border-bottom: 1px solid #eee;
padding-bottom: 15px;
}
.menu-row:last-child {
border-bottom: none;
}
.menu-col {
/*display: flex;*/
/*flex-direction: column;*/
}
.menu-sub {
margin: 10px 0;
padding: 10px;
background: #f9f9f9;
border-radius: 4px;
}
.menu-func-group {
margin: 10px 0 0 25px;
padding: 10px;
background: #f5f5f5;
border-radius: 4px;
}
.hint {
font-size: 12px;
color: #888;
margin: 0 0 8px 0;
}
.menu-level3 {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.header {
text-align: center;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="menu-container">
<div class="header">
<h2>角色权限管理</h2>
<p>请为角色分配菜单和功能权限</p>
</div>
<el-form :model="form" :rules="rules" label-width="120px">
<el-form-item label="角色名称" prop="RoleName">
<el-input v-model="form.RoleName" placeholder="请输入角色名称"></el-input>
</el-form-item>
<el-form-item label="角色描述" prop="RoleDescription">
<el-input v-model="form.RoleDescription" type="textarea" placeholder="请输入角色描述"></el-input>
</el-form-item>
<h3>菜单权限</h3>
<div v-for="menu in menuOptions" :key="menu.Id" class="menu-row">
<!-- 一级菜单 -->
<el-form-item :label="menu.Name">
<!-- 二级菜单 -->
<el-checkbox-group v-model="checkedMenuIds" class="menu-col menu-level2">
<div v-for="sub in menu.Children" :key="sub.Id" class="menu-sub">
<el-checkbox
:label="sub.Id"
:key="sub.Id"
:indeterminate="sub.indeterminate"
@change="(val) => handleSubMenuChange(val, sub)"
>
{{ sub.Name }}
</el-checkbox>
<!-- 三级菜单(功能权限) -->
<div class="menu-func-group">
<p class="hint">功能权限:</p>
<el-checkbox-group
v-model="checkedFunctionIds"
class="menu-col menu-level3"
@change="(value) => handleFunctionChange(value, sub)"
>
<el-checkbox
v-for="subFunc in sub.Functions"
:key="subFunc.Id"
:label="subFunc.Id"
:value="subFunc.Id"
>
{{ subFunc.Name }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</el-checkbox-group>
</el-form-item>
</div>
<el-form-item>
<el-button type="primary" @click="submitForm">提交</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
<script>
const { createApp, ref, reactive, onMounted } = Vue;
createApp({
setup() {
// 为每个二级菜单添加 indeterminate 状态
const menuOptions = ref([
{
Id: '1',
Name: '系统管理',
Children: [
{
Id: '1-1',
Name: '用户管理',
indeterminate: false,
Functions: [
{ Id: '1-1-1', Name: '新增用户' },
{ Id: '1-1-2', Name: '编辑用户' },
{ Id: '1-1-3', Name: '删除用户' }
]
},
{
Id: '1-2',
Name: '角色管理',
indeterminate: false,
Functions: [
{ Id: '1-2-1', Name: '新增角色' },
{ Id: '1-2-2', Name: '编辑角色' },
{ Id: '1-2-3', Name: '删除角色' }
]
}
]
},
{
Id: '2',
Name: '业务管理',
Children: [
{
Id: '2-1',
Name: '订单管理',
indeterminate: false,
Functions: [
{ Id: '2-1-1', Name: '创建订单' },
{ Id: '2-1-2', Name: '审核订单' },
{ Id: '2-1-3', Name: '取消订单' }
]
},
{
Id: '2-2',
Name: '客户管理',
indeterminate: false,
Functions: [
{ Id: '2-2-1', Name: '新增客户' },
{ Id: '2-2-2', Name: '编辑客户' },
{ Id: '2-2-3', Name: '删除客户' }
]
}
]
}
]);
const functionOptions = ref([]);
const checkedMenuIds = ref([]);
const checkedFunctionIds = ref([]);
const detailInfo = ref({});
const form = reactive({
RoleName: '',
RoleDescription: ''
});
const rules = reactive({
RoleName: [{ required: true, message: "角色名称不能为空", trigger: "blur" }],
RoleDescription: [{ required: true, message: "角色描述不能为空", trigger: "blur" }],
});
// 处理二级菜单勾选变化
const handleSubMenuChange = (checked, subMenu) => {
if (checked) {
// 选中二级菜单时,添加所有功能权限
subMenu.Functions.forEach(func => {
if (!checkedFunctionIds.value.includes(func.Id)) {
checkedFunctionIds.value.push(func.Id);
}
});
subMenu.indeterminate = false;
} else {
// 取消二级菜单时,移除所有功能权限
subMenu.Functions.forEach(func => {
const index = checkedFunctionIds.value.indexOf(func.Id);
if (index > -1) {
checkedFunctionIds.value.splice(index, 1);
}
});
subMenu.indeterminate = false;
}
// 更新所有二级菜单的不确定状态
updateAllIndeterminateStates();
};
// 处理功能权限勾选变化
const handleFunctionChange = (value, subMenu) => {
const allFunctions = subMenu.Functions.map(f => f.Id);
const allChecked = allFunctions.every(id => checkedFunctionIds.value.includes(id));
const anyChecked = allFunctions.some(id => checkedFunctionIds.value.includes(id));
// 更新当前二级菜单的选中状态
if (allChecked) {
// 如果所有功能都被选中,确保二级菜单被选中
if (!checkedMenuIds.value.includes(subMenu.Id)) {
checkedMenuIds.value.push(subMenu.Id);
}
subMenu.indeterminate = false;
} else if (anyChecked) {
// 如果部分功能被选中,设置不确定状态
subMenu.indeterminate = true;
// 确保二级菜单不被选中(因为是不确定状态)
const index = checkedMenuIds.value.indexOf(subMenu.Id);
if (index > -1) {
checkedMenuIds.value.splice(index, 1);
}
} else {
// 如果没有功能被选中,确保二级菜单不被选中
subMenu.indeterminate = false;
const index = checkedMenuIds.value.indexOf(subMenu.Id);
if (index > -1) {
checkedMenuIds.value.splice(index, 1);
}
}
};
// 更新所有二级菜单的不确定状态
const updateAllIndeterminateStates = () => {
menuOptions.value.forEach(menu => {
menu.Children.forEach(subMenu => {
const allFunctions = subMenu.Functions.map(f => f.Id);
const anyChecked = allFunctions.some(id => checkedFunctionIds.value.includes(id));
const allChecked = allFunctions.every(id => checkedFunctionIds.value.includes(id));
if (anyChecked && !allChecked) {
subMenu.indeterminate = true;
} else {
subMenu.indeterminate = false;
}
});
});
};
// 初始化时设置一些默认选中项,方便演示
onMounted(() => {
checkedMenuIds.value = ['1-1'];
checkedFunctionIds.value = ['1-1-1', '1-1-2', '2-1-1'];
updateAllIndeterminateStates();
});
const submitForm = () => {
console.log('选中的菜单ID:', checkedMenuIds.value);
console.log('选中的功能ID:', checkedFunctionIds.value);
ElMessage.success('提交成功!');
};
const resetForm = () => {
checkedMenuIds.value = [];
checkedFunctionIds.value = [];
form.RoleName = '';
form.RoleDescription = '';
// 重置所有不确定状态
menuOptions.value.forEach(menu => {
menu.Children.forEach(subMenu => {
subMenu.indeterminate = false;
});
});
};
return {
menuOptions,
functionOptions,
checkedMenuIds,
checkedFunctionIds,
detailInfo,
form,
rules,
handleSubMenuChange,
handleFunctionChange,
submitForm,
resetForm
};
}
}).use(ElementPlus).mount('#app');
</script>
</body>
</html>

本文来自博客园,作者:VipSoft 转载请注明原文链接:https://www.cnblogs.com/vipsoft/p/19073386
浙公网安备 33010602011771号