From 67d25f3d9eb0124c7aab544bf8f77031d6d8adc3 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期三, 30 九月 2026 10:36:18 +0800
Subject: [PATCH] 增加公司账号权限功能

---
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java |   88 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java
index 2cf1595..e621337 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java
@@ -3,8 +3,10 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 import javax.annotation.Resource;
@@ -71,6 +73,8 @@
 	private static final String SERVICE_PROVIDER_ROLE_KEY = "service_provider";
 	private static final String COMPANY_ROLE_NAME = "公司";
 	private static final String COMPANY_ROLE_KEY = "company";
+	private static final String COMPANY_ADMIN_ROLE_NAME = "公司管理员";
+	private static final String COMPANY_ADMIN_ROLE_KEY = "company_admin";
 	private static final String OWN_SITE_NAME = "自有电站";
 	private static final String SYSTEM_ROLE_REMARK = "系统内置角色";
 
@@ -101,10 +105,15 @@
 		ensureSystemRole(INDEPENDENT_PARTNER_ROLE_NAME, INDEPENDENT_PARTNER_ROLE_KEY, getIndependentPartnerMenuIds());
 		ensureSystemRole(SITE_OWNER_ROLE_NAME, SITE_OWNER_ROLE_KEY, new HashSet<>());
 		ensureSystemRole(SERVICE_PROVIDER_ROLE_NAME, SERVICE_PROVIDER_ROLE_KEY, new HashSet<>());
-		ensureSystemRole(COMPANY_ROLE_NAME, COMPANY_ROLE_KEY, new HashSet<>());
+		// 公司管理员角色:默认拥有车队管理、VIN码管理、卡片管理、白名单用户菜单,权限配置不可修改
+		ensureSystemRole(COMPANY_ADMIN_ROLE_NAME, COMPANY_ADMIN_ROLE_KEY, getCompanyAdminMenuIds(), true);
 	}
 
 	private void ensureSystemRole(String roleName, String roleKey, Set<Long> menuIds) {
+		ensureSystemRole(roleName, roleKey, menuIds, false);
+	}
+
+	private void ensureSystemRole(String roleName, String roleKey, Set<Long> menuIds, boolean repairMenus) {
 		SysRole role = roleService.getOne(new LambdaQueryWrapper<SysRole>()
 				.eq(SysRole::getRoleKey, roleKey)
 				.eq(SysRole::getDelFlag, 0)
@@ -126,6 +135,9 @@
 				role.setUpdateTime(new Date());
 				roleService.updateById(role);
 			}
+			if (repairMenus) {
+				repairRoleMenus(role.getRoleId(), menuIds);
+			}
 			return;
 		}
 
@@ -140,6 +152,32 @@
 		newRole.setCreateTime(new Date());
 		newRole.setMenuIds(menuIds.toArray(new Long[0]));
 		roleService.insertRole(newRole);
+	}
+
+	/**
+	 * 幂等补齐内置角色的菜单绑定(只补不删),保证公司管理员角色的默认菜单随版本补齐
+	 */
+	private void repairRoleMenus(Long roleId, Set<Long> menuIds) {
+		if (roleId == null || menuIds == null || menuIds.isEmpty()) {
+			return;
+		}
+		List<Long> boundMenuIds = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>()
+						.eq(SysRoleMenu::getRoleId, roleId))
+				.stream()
+				.map(SysRoleMenu::getMenuId)
+				.collect(Collectors.toList());
+		List<SysRoleMenu> toInsert = menuIds.stream()
+				.filter(menuId -> !boundMenuIds.contains(menuId))
+				.map(menuId -> {
+					SysRoleMenu roleMenu = new SysRoleMenu();
+					roleMenu.setRoleId(roleId);
+					roleMenu.setMenuId(menuId);
+					return roleMenu;
+				})
+				.collect(Collectors.toList());
+		if (!toInsert.isEmpty()) {
+			sysRoleMenuMapper.batchRoleMenu(toInsert);
+		}
 	}
 
 	private Set<Long> getIndependentPartnerMenuIds() {
@@ -172,6 +210,43 @@
 		}
 	}
 
+	/**
+	 * 公司管理员默认菜单:车队管理、VIN码管理、卡片管理(不含刷卡充电订单/卡片收支明细)、白名单用户及其操作按钮
+	 */
+	private Set<Long> getCompanyAdminMenuIds() {
+		List<SysMenus> menus = menuMapper.getAll();
+		Set<Long> menuIds = new HashSet<>();
+		Map<Long, Long> parentMap = new HashMap<>();
+		for (SysMenus menu : menus) {
+			parentMap.put(menu.getMenuId(), menu.getParentId());
+			String path = normalizeMenuPath(menu.getPath());
+			String perms = menu.getPerms() == null ? "" : menu.getPerms();
+			// 卡片模块排除收支明细子页(/chargingCardBalanceDetail 同以 /chargingCard 开头)
+			if (path.startsWith("fleet") || perms.startsWith("/vinManagement")
+					|| (perms.startsWith("/chargingCard") && !perms.startsWith("/chargingCardBalanceDetail"))
+					|| perms.startsWith("/appUserWhitelist")) {
+				menuIds.add(menu.getMenuId());
+			}
+		}
+		// 白名单用户菜单挂在「用户管理」父级下,补齐祖先节点保证菜单树可以展示
+		Set<Long> ancestorIds = new HashSet<>();
+		for (Long menuId : new HashSet<>(menuIds)) {
+			Long parentId = parentMap.get(menuId);
+			while (parentId != null && parentId != 0L && !menuIds.contains(parentId) && ancestorIds.add(parentId)) {
+				parentId = parentMap.get(parentId);
+			}
+		}
+		menuIds.addAll(ancestorIds);
+		return menuIds;
+	}
+
+	private String normalizeMenuPath(String path) {
+		if (path == null) {
+			return "";
+		}
+		return path.startsWith("/") ? path.substring(1) : path;
+	}
+
 	private boolean isIndependentPartnerRole(SysRole role) {
 		return role != null && (INDEPENDENT_PARTNER_ROLE_KEY.equals(role.getRoleKey())
 				|| INDEPENDENT_PARTNER_ROLE_NAME.equals(role.getRoleName()));
@@ -190,8 +265,14 @@
 				|| COMPANY_ROLE_NAME.equals(role.getRoleName()));
 	}
 
+	private boolean isCompanyAdminBuiltinRole(SysRole role) {
+		return role != null && (COMPANY_ADMIN_ROLE_KEY.equals(role.getRoleKey())
+				|| COMPANY_ADMIN_ROLE_NAME.equals(role.getRoleName()));
+	}
+
 	private boolean isSystemBuiltinRole(SysRole role) {
-		return role != null && (role.isAdmin() || isPartnerBuiltinRole(role) || isCompanyBuiltinRole(role));
+		return role != null && (role.isAdmin() || isPartnerBuiltinRole(role) || isCompanyBuiltinRole(role)
+				|| isCompanyAdminBuiltinRole(role));
 	}
 
 	private void fillRoleV2Info(SysRole role) {
@@ -350,6 +431,9 @@
 		if (oldRole != null && oldRole.isAdmin()) {
 			return AjaxResult.error("超级管理员角色不可编辑");
 		}
+		if (oldRole != null && isCompanyAdminBuiltinRole(oldRole)) {
+			return AjaxResult.error("公司管理员角色不可编辑");
+		}
 		SysRole role = new SysRole();
 		role.setRoleName(dto.getRoleName());
 		SysRole one = roleService.getOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleName, dto.getRoleName()));

--
Gitblit v1.7.1