网站首页 全球最实用的IT互联网站!

人工智能P2P分享Wind搜索发布信息网站地图标签大全

当前位置:诺佳网 > 人工智能 > 大模型 >

【Dv3Admin】Vue3一键配置权限规则

时间:2026-03-17 16:31

人气:

作者:admin

标签:

导读:文章浏览阅读534次,点赞13次,收藏11次。本文探讨后台权限配置系统的实现方案,针对传统权限管理中配置分散、状态不一致等问题,提出基于Vue和Element Plus的一体化解决方案。系统通...

在后台权限体系中,角色、菜单、接口按钮与数据范围往往被拆散在多个配置入口中维护,实际落地时极易出现按钮越权、数据范围错配、前端状态与后端存储不一致等问题。这类风险通常不源于单一逻辑错误,而是配置路径过长、默认策略缺失以及批量操作能力不足共同叠加后的结果。

本文围绕“角色权限配置”这一真实模块展开,聚焦权限配置抽屉 RoleDrawer 与接口权限面板 RoleMenuBtn 的协作方式,完整拆解从部门切换、菜单选择、按钮勾选到数据范围持久化的实现链路,重点关注参数传递、状态同步与接口封装方式。

需求解析

该功能位于后台系统的角色管理模块中,运行在前端基于 Vue 与 Element Plus 的管理界面,后端通过统一的权限接口提供数据支撑,主要服务于角色创建或调整后的权限配置场景。使用过程中需要在一个统一界面内完成部门切换、菜单定位、接口按钮授权以及数据范围控制,且所有操作要求即时生效并持久化。
在这里插入图片描述
在这里插入图片描述
从操作链路上看,权限配置从角色列表页触发,打开权限配置抽屉后,通过部门筛选驱动菜单树刷新,菜单节点变化进一步触发接口权限面板的数据加载,按钮勾选与数据范围设置最终通过接口写入后端。

结果落库

接口
持久化

权限配置

选择
菜单

加载
接口按钮

勾选按钮
设置数据范围

上下文切换

切换
部门

加载
菜单树

入口触发

角色列表页

打开
RoleDrawer

功能实现

权限配置抽屉由 RoleDrawer.vue 承载,负责统一容纳部门切换、菜单树以及不同权限面板,通过抽屉形式避免页面跳转带来的上下文丢失。

<template>
	<el-drawer v-model="RoleDrawer.drawerVisible" title="权限配置" direction="rtl" size="80%" :close-on-click-modal="false"
		:before-close="RoleDrawer.handleDrawerClose" :destroy-on-close="true">
		<template #header>

			<div style="display: flex;align-items: center;">
				<el-form-item label="部门" prop="company" style="margin-top: 16px;margin-right: 12px;">
					<el-select v-model="RoleDrawer.company" placeholder="请选择部门" @change="handleDeptChange"
						style="width: 200px;">
						<el-option v-for="item in deptAllList" :key="item.key" :label="item.name" :value="item.name" />
					</el-select>
				</el-form-item>
				<div>当前授权角色:
					<el-tag style="margin-right: 20px">{{ RoleDrawer.roleName }}</el-tag>
					授权人员:
					<el-button size="small" :icon="UserFilled" @click="handleUsers">{{ RoleDrawer.users.length
					}}</el-button>
				</div>
			</div>
		</template>
		<splitpanes class="default-theme" style="height: 100%">
			<pane min-size="20" size="22">
				<div class="pane-box">
					<MenuTreeCom ref="refMenuTreeCom" />
				</div>
			</pane>
			<pane min-size="20">
				<div class="pane-box">
					<el-tabs v-model="activeName" class="demo-tabs">
						<el-tab-pane label="接口权限" name="first">
							<MenuBtnCom />
						</el-tab-pane>
						<el-tab-pane label="列字段权限" name="second">
							<MenuFieldCom />
						</el-tab-pane>
					</el-tabs>
				</div>
			</pane>
		</splitpanes>
	</el-drawer>

	<el-dialog v-model="dialogVisible" title="授权用户" width="700px" :close-on-click-modal="false">
		<RoleUsersCom />
	</el-dialog>
</template>

该组件的关键在于将部门、菜单与权限面板解耦,抽屉关闭时销毁实例,避免历史状态残留。

接口权限面板由 RoleMenuBtn.vue 实现,承担默认接口权限、按钮勾选与快捷配置能力。

<template>
	<div class="pccm-item" v-if="RoleMenuBtn.$state.length > 0">
		<div class="menu-form-alert">
			<div style="display: flex; align-items: center; white-space: nowrap; margin-bottom: 10px">
				<span>默认接口权限:</span>
				<el-select v-model="default_selectBtn.data_range" @change="defaulthandlePermissionRangeChange"
					placeholder="请选择" style="margin-left: 5px; width: 250px; min-width: 250px">
					<el-option v-for="item in dataPermissionRange" :key="item.value" :label="item.label"
						:value="item.value" />
				</el-select>
				<el-tree-select v-show="default_selectBtn.data_range === 4" node-key="id"
					v-model="default_selectBtn.dept" :props="defaultTreeProps" :data="deptData"
					@change="customhandlePermissionRangeChange(default_selectBtn.dept)" placeholder="请选择自定义部门" multiple
					check-strictly :render-after-expand="false" show-checkbox class="dialog-tree"
					style="margin-left: 15px; width: AUTO; min-width: 250px; margin-top: 0" />
			</div>
			<span>配置操作功能接口权限,配置数据权限点击小齿轮</span>
		</div>
		<div style="margin-bottom: 20px;">
			<el-button type="primary" @click="handleQuickQuery('快速查询')">快速查询</el-button>
			<el-button type="primary" @click="handleQuickQuery('标准业务')">标准业务</el-button>
		</div>
		<el-checkbox v-for="btn in RoleMenuBtn.$state" :key="btn.id" v-model="btn.isCheck"
			@change="handleCheckChange(btn)">
			<div class="btn-item">
				{{ btn.data_range !== null ? `${btn.name}(${formatDataRange(btn.data_range, btn.dept)})` : btn.name }}
				<span v-show="btn.isCheck" @click.stop.prevent="handleSettingClick(btn)">
					<el-icon>
						<Setting />
					</el-icon>
				</span>
				<span>【{{ btn.api }}】</span>
			</div>
		</el-checkbox>
	</div>

默认接口权限在此作为批量勾选的基准,避免为每个按钮重复配置数据范围。

按钮勾选与快速配置通过统一接口完成写入,并同步更新本地状态。

const handleCheckChange = async (btn: RoleMenuBtnType) => {
	selectBtn.value = default_selectBtn.value;
	const put_data = {
		isCheck: btn.isCheck,
		roleId: RoleDrawer.roleId,
		menuId: RoleMenuTree.id,
		btnId: btn.id,
		data_range: default_selectBtn.value.data_range,
		dept: default_selectBtn.value.dept,
	};
	const { data, msg } = await setRoleMenuBtn(put_data);
	RoleMenuBtn.updateState(data);
	ElMessage({ message: msg, type: 'success' });
};

该逻辑保证勾选行为与后端状态保持同步,否则会导致前端显示与实际权限不一致。

快捷配置基于后端预设返回按钮集合,再批量写入权限。

const handleQuickQuery = async (type: string) => {
	const { data } = await getRoleMenuBtnField({
		roleId: RoleDrawer.roleId,
		menuId: RoleMenuTree.id,
		select: type,
	});
	const names = data.menu_btn.map((item: any) => item.name);
	const updatedButtons = RoleMenuBtn.$state.map((btn: RoleMenuBtnType) => ({
		...btn,
		isCheck: names.includes(btn.name)
	}));
	RoleMenuBtn.updateBatchState(updatedButtons);
	const promises = updatedButtons
		.filter(btn => names.includes(btn.name))
		.map(async (btn) => {
			const put_data = {
				isCheck: btn.isCheck,
				roleId: RoleDrawer.roleId,
				menuId: RoleMenuTree.id,
				btnId: btn.id,
				data_range: default_selectBtn.value.data_range,
				dept: default_selectBtn.value.dept,
			};
			return await setRoleMenuBtn(put_data);
		});
	try {
		await Promise.all(promises);
		ElMessage({ message: '快速配置成功', type: 'success' });
	} catch (error) {
		ElMessage({ message: '快速配置失败', type: 'error' });
	}
}

单按钮的数据范围通过弹窗单独配置,确认后立即持久化。

const handleDialogConfirm = async () => {
	const { data, msg } = await setRoleMenuBtnDataRange(selectBtn.value);
	selectBtn.value = data;
	dialogVisible.value = false;
	ElMessage({ message: msg, type: 'success' });
};

接口统一封装在组件内的 api.ts,确保权限相关读写路径集中维护。

export function getRoleMenu(query: object) {
	return request({
		url: '/api/system/role_menu_button_permission/get_role_menu/',
		method: 'get',
		params: query,
	}).then((res: any) => {
		return XEUtils.toArrayTree(res.data, { key: 'id', parentKey: 'parent', children: 'children', strict: false });
	});
}
/**
 * 设置 角色-菜单
 */
export function setRoleMenu(data: object) {
	return request({
		url: '/api/system/role_menu_button_permission/set_role_menu/',
		method: 'put',
		data,
	});
}

角色列表页通过权限控制暴露入口,避免无权限访问配置能力。

permission: {
	type: 'primary',
	text: '权限配置',
	show: auth('role:Permission'),
	click: (clickContext: any): void => {
		const { row } = clickContext;
		context.RoleDrawer.handleDrawerOpen(row);
		context.RoleMenuBtn.setState([]);
		context.RoleMenuField.setState([]);
	},
},

总结

该模块通过权限配置抽屉将部门、菜单与接口权限聚合在单一操作空间内,避免多页面切换造成的状态割裂,同时以默认接口权限作为批量授权的核心锚点。在实现层面,勾选即存与弹窗即存降低了配置遗漏风险,但接口调用频繁,对后端幂等性与性能提出更高要求,若重新设计可引入批量提交或事务化策略以减少请求数量。

整体链路在权限渲染、数据一致性与维护成本之间取得平衡,为复杂业务场景下的角色权限管理提供了一套可复用的实现范式。

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信