How to add permissions to vxetable right-click menu options and render based on row data
Business scenario:
? The page has button permissions, and the right-click menu function is also implemented on the form. It is also necessary to control the permission function of the right-click menu.
Solution ideas:
-
By viewing the document, right-click the configuration
menu-config
and select the attributevisibleMethod
(Document description: The return value of this function is used to determine whether to allow the right-click menu to be displayed (for menus that need to be It may be used for permission control)), which can obtain these data({<!-- --> type, options, columns, row?, rowIndex?, column?, columnIndex? }) => boolean // options is our configuration data // row is the currently clicked row
-
When configuring the right-click options, add an attribute
auth: ["Permission Encoding"]
-
You need to use the usePermission method in hooks to verify permissions
-
In
visibleMethod
, traverse the auth attribute in options to verify whether you have permission.
Code reference
vxeTable configuration
... menuConfig: {<!-- --> // Right click configuration body: {<!-- --> options: [Options()], }, visibleMethod: visibleMethod, }, ... //options configuration const orderClassTableMenuConfigOptions = () => {<!-- --> return [ {<!-- --> code: 'refresh', name: 'Refresh', prefixIcon: 'vxe-icon-refresh', visible: true, disabled: false, }, {<!-- --> code: 'add', name: 'New', prefixIcon: 'vxe-icon-feedback', visible: true, disabled: false, auth: ["yanjun202.com_add"], }, {<!-- --> code: 'copy', name: 'Copy', prefixIcon: 'vxe-icon-paste', visible: true, disabled: true, auth: ["yanjun202.com_copy"], },] ; //visibleMethod function visibleMethod(Opt) {<!-- --> const {<!-- --> options, row, rowIndex, columns } = Opt; //Permission processing const {<!-- --> isPermission } = usePermission(); options[0].forEach((item) => {<!-- --> if (item.auth) {<!-- --> //Can be set to hide or disable, controlled according to business scenarios item.visible = isPermission(item.auth); } }); // Or you can determine whether to disable the button based on the row data if (row.orderClass == 'A' & amp; & amp; row.orderStatus !== '8') {<!-- --> // Enable or disable copying const index = options[0].findIndex((item) => item.code === 'copy'); options[0][index].disabled = false; } return true; }
Reference for writing usePermission: Source: Front-end Junge
/** * Whether maxList contains minList * * @param maxList large array * @param minList small array */ function containsAll(maxList: string[], minList: string[]) {<!-- --> return intersection(maxList, minList).length == minList.length; } /** * Determine whether there is permission * * @param permissionsOwns The permissions owned by the user (the set of permissions queried by the background/anyone/visible/resource interface) * @param toBeVerified Permission to be verified (the resource code written on the button, such as <a-button v-hasPermission="['system:menu:delete']">) */ function isPermitted(permissionsOwns: WildcardPermission[], toBeVerified: WildcardPermission) {<!-- --> if (permissionsOwns == null || permissionsOwns.length === 0) {<!-- --> return false; } // Traverse the permissions owned by the user and determine whether each one contains permissions to be verified. for (const owned of permissionsOwns) {<!-- --> if (owned.implies(toBeVerified)) {<!-- --> return true; } } return false; } const WILDCARD_TOKEN = '*'; // wildcard const PART_DIVIDER_TOKEN = ':'; // module separator const SUBPART_DIVIDER_TOKEN = ','; // Function separator /** * Wildcard permission parsing object */ class WildcardPermission {<!-- --> //The parsed permission set contains only : parts: string[][]; /** * Parse and store wildcardString into parts * * @param wildcardString original wildcard string * @param caseSensitive whether it is case-sensitive true: distinguish; false: ignore case */ constructor(wildcardString: string, caseSensitive: boolean) {<!-- --> this.parts = []; this._init_(wildcardString, caseSensitive); } // Parse wildcards _init_(wildcardString: string, caseSensitive: boolean) {<!-- --> if (wildcardString == null || wildcardString.trim().length === 0) {<!-- --> throw new Error('The permission encoding wildcard string cannot be null or empty. Make sure the permission string is in the correct format.'); } 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( 'The permission encoding wildcard string cannot contain parts with only delimiters. Ensure that the permission encoding string is in the correct format. ', ); } this.parts.push(subParts); } if (this.parts.length <= 0) {<!-- --> throw new Error('The permission encoding wildcard string cannot only contain delimiters, make sure the format of the permission encoding string is correct.'); } } //The real judgment logic implies(toBeVerified: WildcardPermission) {<!-- --> const toBeVerifiedParts = toBeVerified.parts; let i = 0; for (const toBeVerifiedPart of toBeVerifiedParts) {<!-- --> // If this permission has fewer parts than other permissions, everything after the number of parts contained in this permission will automatically be implicit, so return true if (this.parts.length - 1 < i) {<!-- --> return false; } else {<!-- --> const part = this.parts[i]; if (!part.includes(WILDCARD_TOKEN) & amp; & amp; !containsAll(part, toBeVerifiedPart)) {<!-- --> return false; } i + + ; } } // If this permission has more parts than others, it will only be implied if all other parts are wildcards 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(); } /** * Must contain all permissions listed for the element to be displayed */ function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean {<!-- --> return isPermission(value, def, PermModeEnum.Has); } /** * Renders this element when all permissions listed are not included */ function withoutPermission( value?: RoleEnum | RoleEnum[] | string | string[], def = true, ): boolean {<!-- --> return isPermission(value, def, PermModeEnum.Without); } /** * Renders this element when none of the listed permissions are included */ function withoutAnyPermission( value?: RoleEnum | RoleEnum[] | string | string[], def = true, ): boolean {<!-- --> return isPermission(value, def, PermModeEnum.WithoutAny); } /** * As long as any of the listed permissions are included, the element will be displayed */ function hasAnyPermission( value?: RoleEnum | RoleEnum[] | string | string[], def = true, ): boolean {<!-- --> return isPermission(value, def, PermModeEnum.HasAny); } /** * Judgment authority * * @param value needs to determine whether the current user owns the resource code * @param def value When it is empty, whether it is owned by default * @param mode mode optional values: have all have any none */ 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; // The permissions to be verified must be an array let permissions = value; if (!isArray(value)) {<!-- --> permissions = [value]; } if (permissions != null & amp; & amp; permissions.length > 0) {<!-- --> //Convert the permissions you have const permissionsOwns: WildcardPermission[] = []; // Bug: After exiting from the developer system, logging in to the basic platform will prompt that there is no permission. // if (map.permissionsOwns & amp; & amp; 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); } // Different modes have different verification rules. if (mode === PermModeEnum.Has) {<!-- --> //Have all permissions if (!isPermitted(permissionsOwns, toBeVerified)) {<!-- --> flag = false; } } else if (mode === PermModeEnum.Without) {<!-- --> // Without all permissions `Insert image description here ` if (isPermitted(permissionsOwns, toBeVerified)) {<!-- --> flag = false; } } else if (mode === PermModeEnum.HasAny) {<!-- --> //Have any permission if (isPermitted(permissionsOwns, toBeVerified)) {<!-- --> flag = true; } } else if (mode === PermModeEnum.WithoutAny) {<!-- --> // Does not have any permissions 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, }; }