vxetable右键菜单选项如何添加权限及根据行的数据渲染
vxetable右键菜单选项如何添加权限及根据行的数据渲染
业务场景:
页面做了按钮权限,表格上也做了右键菜单的功能,也需要给右键菜单做权限功能控制
解决思路:
-
通过查看文档,右键配置
menu-config
选择有个属性visibleMethod
(文档说明:该函数的返回值用来决定是否允许显示右键菜单(对于需要对菜单进行权限控制时可能会用到)),它可以获取到这些数据({ type, options, columns, row?, rowIndex?, column?, columnIndex? }) => boolean // options 就是我们的配置数据 // row 是当前点击的行
-
配置右键的选项的时候增加一个属性
auth: ["权限编码"]
-
需要用到 hooks 中的 usePermission 方法,来验证权限
-
在
visibleMethod
中 去遍历 options 中的auth属性,去验证 是否有权限
代码参考
vxeTable 配置
...
menuConfig: {
// 右键配置
body: {
options: [Options()],
},
visibleMethod: visibleMethod,
},
...
//options 配置
const orderClassTableMenuConfigOptions = () => {
return [
{
code: 'refresh',
name: '刷新',
prefixIcon: 'vxe-icon-refresh',
visible: true,
disabled: false,
},
{
code: 'add',
name: '新增',
prefixIcon: 'vxe-icon-feedback',
visible: true,
disabled: false,
auth: ["yanjun202.com_add"],
},
{
code: 'copy',
name: '复制',
prefixIcon: 'vxe-icon-paste',
visible: true,
disabled: true,
auth: ["yanjun202.com_copy"],
},] ;
//visibleMethod
function visibleMethod(Opt) {
const { options, row, rowIndex, columns } = Opt;
// 权限处理
const { isPermission } = usePermission();
options[0].forEach((item) => {
if (item.auth) {
//可以设置 隐藏或者禁用, 根据业务场景控制
item.visible = isPermission(item.auth);
}
});
// 或者可以根据行的数据,来判断是否禁用按钮
if (row.orderClass == 'A' && row.orderStatus !== '8') {
// 复制的可用 或者禁用
const index = options[0].findIndex((item) => item.code === 'copy');
options[0][index].disabled = false;
}
return true;
}
usePermission 写法的参考: 来源:前端君哥
/**
* maxList是否包含minList
*
* @param maxList 大数组
* @param minList 小数组
*/
function containsAll(maxList: string[], minList: string[]) {
return intersection(maxList, minList).length == minList.length;
}
/**
* 判断是否有权限
*
* @param permissionsOwns 用户拥有的权限(后台/anyone/visible/resource接口查询出的权限集合)
* @param toBeVerified 待验证的权限(按钮上面写死的资源编码,如<a-button v-hasPermission="['system:menu:delete']">)
*/
function isPermitted(permissionsOwns: WildcardPermission[], toBeVerified: WildcardPermission) {
if (permissionsOwns == null || permissionsOwns.length === 0) {
return false;
}
// 遍历用户拥有的权限,按个判断是否”包含“待验证的权限
for (const owned of permissionsOwns) {
if (owned.implies(toBeVerified)) {
return true;
}
}
return false;
}
const WILDCARD_TOKEN = '*'; // 通配符
const PART_DIVIDER_TOKEN = ':'; // 模块分隔符
const SUBPART_DIVIDER_TOKEN = ','; // 功能分隔符
/**
* 通配符权限解析对象
*/
class WildcardPermission {
// 解析后的只包含 : 的权限集合
parts: string[][];
/**
* 将 wildcardString 解析存储到 parts
*
* @param wildcardString 原始通配符字符串
* @param caseSensitive 是否区分大小写 true:区分;false:忽略大小写
*/
constructor(wildcardString: string, caseSensitive: boolean) {
this.parts = [];
this._init_(wildcardString, caseSensitive);
}
// 解析通配符
_init_(wildcardString: string, caseSensitive: boolean) {
if (wildcardString == null || wildcardString.trim().length === 0) {
throw new Error('权限编码通配符字符串不能为null或空。确保权限字符串的格式正确。');
}
wildcardString = wildcardString.trim();
const parts: string[] = wildcardString.split(PART_DIVIDER_TOKEN);
this.parts = [];
for (const part of parts) {
let subParts: string[] = part.split(SUBPART_DIVIDER_TOKEN);
if (!caseSensitive) {
const lowerSubParts: string[] = [];
for (const subPart of subParts) {
lowerSubParts.push(subPart.toLocaleLowerCase());
}
subParts = lowerSubParts;
}
if (subParts.length <= 0) {
throw new Error(
'权限编码通配符字符串不能包含只有分隔符的部分,确保权限编码字符串的格式正确。',
);
}
this.parts.push(subParts);
}
if (this.parts.length <= 0) {
throw new Error('权限编码通配符字符串不能只包含分隔符,确保权限编码字符串的格式正确。');
}
}
// 真正的判断逻辑
implies(toBeVerified: WildcardPermission) {
const toBeVerifiedParts = toBeVerified.parts;
let i = 0;
for (const toBeVerifiedPart of toBeVerifiedParts) {
// 如果此权限的部分数少于其他权限,则此权限中包含的部分数之后的所有内容都将自动隐含,因此返回true
if (this.parts.length - 1 < i) {
return false;
} else {
const part = this.parts[i];
if (!part.includes(WILDCARD_TOKEN) && !containsAll(part, toBeVerifiedPart)) {
return false;
}
i++;
}
}
// 如果此权限的部分多于其他部分,则仅当所有其他部分都是通配符时才暗示它
for (; i < this.parts.length; i++) {
const part = this.parts[i];
if (!part.includes(WILDCARD_TOKEN)) {
return false;
}
}
return true;
}
}
const permMap = {};
// User permissions related operations
export function usePermission() {
const userStore = useUserStore();
const appStore = useAppStore();
const permissionStore = usePermissionStore();
const { closeAll } = useTabs(router);
/**
* Change permission mode
*/
async function togglePermissionMode() {
appStore.setProjectConfig({
permissionMode:
projectSetting.permissionMode === PermissionModeEnum.BACK
? PermissionModeEnum.ROUTE_MAPPING
: PermissionModeEnum.BACK,
});
location.reload();
}
/**
* Reset and regain authority resource information
* @param id
*/
async function resume() {
const tabStore = useMultipleTabStore();
tabStore.clearCacheTabs();
resetRouter();
const routes = await permissionStore.buildRoutesAction();
routes.forEach((route) => {
router.addRoute(route as unknown as RouteRecordRaw);
});
permissionStore.setLastBuildMenuTime();
closeAll();
}
/**
* 必须包含列出的所有权限,元素才显示
*/
function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean {
return isPermission(value, def, PermModeEnum.Has);
}
/**
* 当不包含列出的所有权限时,渲染该元素
*/
function withoutPermission(
value?: RoleEnum | RoleEnum[] | string | string[],
def = true,
): boolean {
return isPermission(value, def, PermModeEnum.Without);
}
/**
* 当不包含列出的任意权限时,渲染该元素
*/
function withoutAnyPermission(
value?: RoleEnum | RoleEnum[] | string | string[],
def = true,
): boolean {
return isPermission(value, def, PermModeEnum.WithoutAny);
}
/**
* 只要包含列出的任意一个权限,元素就会显示
*/
function hasAnyPermission(
value?: RoleEnum | RoleEnum[] | string | string[],
def = true,
): boolean {
return isPermission(value, def, PermModeEnum.HasAny);
}
/**
* 判断权限
*
* @param value 需要判断当前用户是否拥有的资源编码
* @param def value 为空时,默认是否拥有
* @param mode 模式 可选值: 拥有所有 拥有任意 没有
*/
function isPermission(
value?: RoleEnum | RoleEnum[] | string | string[],
def = true,
mode = PermModeEnum.Has,
): boolean {
// Visible by default
if (!value) {
return def;
}
const permMode = projectSetting.permissionMode;
if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) {
if (!isArray(value)) {
return userStore.getRoleList?.includes(value as RoleEnum);
}
return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0;
}
if (PermissionModeEnum.BACK === permMode) {
const visibleResource = permissionStore.getVisibleResource;
const enabled = visibleResource?.enabled;
if (!enabled) {
return true;
}
let flag = true;
if (mode === PermModeEnum.HasAny || mode === PermModeEnum.WithoutAny) {
flag = false;
}
const resourceList = visibleResource.resourceList;
const caseSensitive = visibleResource.caseSensitive;
// 待校验权限 一定要是数组
let permissions = value;
if (!isArray(value)) {
permissions = [value];
}
if (permissions != null && permissions.length > 0) {
// 转换拥有的权限
const permissionsOwns: WildcardPermission[] = [];
// bug:从开发者系统退出后,登录基础平台都会提示无权限
// if (map.permissionsOwns && map.permissionsOwns.length > 0) {
// permissionsOwns = map.permissionsOwns;
// } else {
for (const resource of resourceList) {
// let wp: WildcardPermission;
// if (permMap[resource]) {
// wp = permMap[resource];
// } else {
// wp = new WildcardPermission(resource, caseSensitive);
// }
permissionsOwns.push(new WildcardPermission(resource, caseSensitive));
}
// map.permissionsOwns = permissionsOwns;
// }
for (const strPerm of permissions) {
let toBeVerified;
if (permMap[strPerm]) {
toBeVerified = permMap[strPerm];
} else {
toBeVerified = new WildcardPermission(strPerm, caseSensitive);
}
// 不同的模式,校验规则不一样
if (mode === PermModeEnum.Has) {
// 拥有所有权限
if (!isPermitted(permissionsOwns, toBeVerified)) {
flag = false;
}
} else if (mode === PermModeEnum.Without) {
// 没有所有权限`在这里插入图片描述
`
if (isPermitted(permissionsOwns, toBeVerified)) {
flag = false;
}
} else if (mode === PermModeEnum.HasAny) {
// 拥有任意一个权限
if (isPermitted(permissionsOwns, toBeVerified)) {
flag = true;
}
} else if (mode === PermModeEnum.WithoutAny) {
// 没有任意一个权限
if (!isPermitted(permissionsOwns, toBeVerified)) {
flag = true;
}
}
}
}
return flag;
}
return true;
}
/**
* Change roles
* @param roles
*/
async function changeRole(roles: RoleEnum | RoleEnum[]): Promise<void> {
if (projectSetting.permissionMode !== PermissionModeEnum.ROUTE_MAPPING) {
throw new Error(
'Please switch PermissionModeEnum to ROUTE_MAPPING mode in the configuration to operate!',
);
}
if (!isArray(roles)) {
roles = [roles];
}
userStore.setRoleList(roles);
await resume();
}
/**
* refresh menu data
*/
async function refreshMenu() {
resume();
}
return {
changeRole,
isPermission,
hasPermission,
withoutPermission,
withoutAnyPermission,
hasAnyPermission,
togglePermissionMode,
refreshMenu,
};
}