|
|
@@ -54,6 +54,9 @@ import java.util.stream.Collectors;
|
|
|
@Slf4j
|
|
|
@Service
|
|
|
public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantInfo> implements TenantInfoService {
|
|
|
+
|
|
|
+ /** 菜单 upsert 单批上限,避免 SQL 过长 */
|
|
|
+ private static final int MENU_UPSERT_BATCH_SIZE = 200;
|
|
|
private static final String REDIS_SYSTEM_KEY_PREFIX = "tenantid:system:";
|
|
|
private static final String TENANT_INFO_CODE_CACHE_KEY_PREFIX = "tenant:info:code:";
|
|
|
private static final int TENANT_INFO_CODE_CACHE_HOURS = 24;
|
|
|
@@ -278,16 +281,57 @@ public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantI
|
|
|
if ("sys".equals(flag)) {
|
|
|
List<SysMenu> menuList = baseMapper.selectTenantMenu();
|
|
|
List<SysMenu> result = mergeSysMenu(sysMenus, menuList);
|
|
|
- // 返回与模板维护页一致的扁平列表,由前端 handleTree(menuId) 建树
|
|
|
- return R.ok().put("menus", result);
|
|
|
+ List<Long> tenantMenuIds = menuList.stream()
|
|
|
+ .map(SysMenu::getMenuId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ List<Long> checkedKeys = expandSysMenuIdsWithAncestors(tenantMenuIds, sysMenus);
|
|
|
+ return R.ok().put("menus", result).put("checkedKeys", checkedKeys);
|
|
|
}
|
|
|
List<TenantCompanyMenu> menuList = baseMapper.selectTenantComMenu();
|
|
|
List<TenantCompanyMenu> result = mergeComMenu(companyMenus, menuList);
|
|
|
- return R.ok().put("menus", result);
|
|
|
+ List<Long> tenantMenuIds = menuList.stream()
|
|
|
+ .map(TenantCompanyMenu::getMenuId)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ List<Long> checkedKeys = expandComMenuIdsWithAncestors(tenantMenuIds, companyMenus);
|
|
|
+ return R.ok().put("menus", result).put("checkedKeys", checkedKeys);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Long> expandSysMenuIdsWithAncestors(List<Long> menuIds, List<SysMenu> allMenus) {
|
|
|
+ if (CollectionUtils.isEmpty(menuIds) || CollectionUtils.isEmpty(allMenus)) {
|
|
|
+ return new ArrayList<>(emptyIfNull(menuIds));
|
|
|
+ }
|
|
|
+ Map<Long, Long> parentById = allMenus.stream()
|
|
|
+ .collect(Collectors.toMap(SysMenu::getMenuId, SysMenu::getParentId, (a, b) -> a));
|
|
|
+ return expandMenuIdsWithAncestors(menuIds, parentById);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Long> expandComMenuIdsWithAncestors(List<Long> menuIds, List<TenantCompanyMenu> allMenus) {
|
|
|
+ if (CollectionUtils.isEmpty(menuIds) || CollectionUtils.isEmpty(allMenus)) {
|
|
|
+ return new ArrayList<>(emptyIfNull(menuIds));
|
|
|
+ }
|
|
|
+ Map<Long, Long> parentById = allMenus.stream()
|
|
|
+ .collect(Collectors.toMap(TenantCompanyMenu::getMenuId, TenantCompanyMenu::getParentId, (a, b) -> a));
|
|
|
+ return expandMenuIdsWithAncestors(menuIds, parentById);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Long> expandMenuIdsWithAncestors(List<Long> menuIds, Map<Long, Long> parentById) {
|
|
|
+ Set<Long> expanded = new LinkedHashSet<>();
|
|
|
+ for (Long menuId : menuIds) {
|
|
|
+ Long current = menuId;
|
|
|
+ while (current != null && current != 0L) {
|
|
|
+ if (!expanded.add(current)) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ current = parentById.get(current);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return new ArrayList<>(expanded);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 合并模板菜单与租户库菜单:结构以模板(tenant_sys_menu)为准,visible 以租户库为准
|
|
|
+ * 合并模板菜单与租户库菜单:结构以模板(tenant_sys_menu)为准,visible 以租户库是否存在为准
|
|
|
*/
|
|
|
private List<SysMenu> mergeSysMenu(List<SysMenu> standardList, List<SysMenu> tenantList) {
|
|
|
Map<Long, SysMenu> tenantMap = tenantList.stream()
|
|
|
@@ -302,6 +346,8 @@ public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantI
|
|
|
private SysMenu mergeOneSysMenu(SysMenu standard, Map<Long, SysMenu> tenantMap) {
|
|
|
SysMenu tenant = tenantMap.get(standard.getMenuId());
|
|
|
if (tenant != null) {
|
|
|
+ // 租户库存在即已分配,统一 visible=0 便于前端回显
|
|
|
+ tenant.setVisible("0");
|
|
|
return tenant;
|
|
|
}
|
|
|
SysMenu unassigned = new SysMenu();
|
|
|
@@ -326,6 +372,7 @@ public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantI
|
|
|
private TenantCompanyMenu mergeOneComMenu(TenantCompanyMenu standard, Map<Long, TenantCompanyMenu> tenantMap) {
|
|
|
TenantCompanyMenu tenant = tenantMap.get(standard.getMenuId());
|
|
|
if (tenant != null) {
|
|
|
+ tenant.setVisible("0");
|
|
|
return tenant;
|
|
|
}
|
|
|
TenantCompanyMenu unassigned = new TenantCompanyMenu();
|
|
|
@@ -362,84 +409,103 @@ public class TenantInfoServiceImpl extends ServiceImpl<TenantInfoMapper, TenantI
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 租户库菜单全量替换:existIds 查租户库 sys_menu,删/插均在租户库执行。
|
|
|
+ * 租户库菜单差量同步:仅删除取消项,对其余项批量 upsert(不先删后插)。
|
|
|
*/
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public R menuAssignReplace(List<Long> selected, String flag, List<SysMenu> assignSysMenu, List<TenantCompanyMenu> assignCompanyMenu) {
|
|
|
- List<Long> allSelected = emptyIfNull(selected);
|
|
|
- Set<Long> selectedSet = new HashSet<>(allSelected);
|
|
|
+ Set<Long> selectedSet = new HashSet<>(emptyIfNull(selected));
|
|
|
|
|
|
if ("sys".equals(flag)) {
|
|
|
- replaceSysMenu(allSelected, selectedSet, assignSysMenu);
|
|
|
+ syncSysMenuAssign(selectedSet, emptyListIfNull(assignSysMenu));
|
|
|
return R.ok();
|
|
|
}
|
|
|
- replaceComMenu(allSelected, selectedSet, assignCompanyMenu);
|
|
|
+ syncComMenuAssign(selectedSet, emptyListIfNull(assignCompanyMenu));
|
|
|
return R.ok();
|
|
|
}
|
|
|
|
|
|
- private void replaceSysMenu(List<Long> allSelected, Set<Long> selectedSet, List<SysMenu> assignSysMenu) {
|
|
|
- List<Long> existIds = emptyIfNull(baseMapper.selectTenantDbSysMenuIds());
|
|
|
+ private void syncSysMenuAssign(Set<Long> selectedSet, List<SysMenu> assignSysMenu) {
|
|
|
+ Set<Long> existSet = new HashSet<>(emptyIfNull(baseMapper.selectTenantDbSysMenuIds()));
|
|
|
|
|
|
- List<Long> toRemove = existIds.stream()
|
|
|
+ List<Long> toRemove = existSet.stream()
|
|
|
.filter(id -> !selectedSet.contains(id))
|
|
|
.collect(Collectors.toList());
|
|
|
removeTenantSysMenus(toRemove);
|
|
|
|
|
|
- List<Long> toRefresh = existIds.stream()
|
|
|
- .filter(selectedSet::contains)
|
|
|
- .collect(Collectors.toList());
|
|
|
- removeTenantSysMenus(toRefresh);
|
|
|
-
|
|
|
- if (!CollectionUtils.isEmpty(assignSysMenu)) {
|
|
|
- baseMapper.addSysMenu(assignSysMenu);
|
|
|
- }
|
|
|
- if (!CollectionUtils.isEmpty(allSelected)) {
|
|
|
- baseMapper.updatePitchMenu(allSelected);
|
|
|
- }
|
|
|
+ batchUpsertSysMenu(assignSysMenu);
|
|
|
}
|
|
|
|
|
|
- private void replaceComMenu(List<Long> allSelected, Set<Long> selectedSet, List<TenantCompanyMenu> assignCompanyMenu) {
|
|
|
- List<Long> existIds = emptyIfNull(baseMapper.selectTenantDbComMenuIds());
|
|
|
+ private void syncComMenuAssign(Set<Long> selectedSet, List<TenantCompanyMenu> assignCompanyMenu) {
|
|
|
+ Set<Long> existSet = new HashSet<>(emptyIfNull(baseMapper.selectTenantDbComMenuIds()));
|
|
|
|
|
|
- List<Long> toRemove = existIds.stream()
|
|
|
+ List<Long> toRemove = existSet.stream()
|
|
|
.filter(id -> !selectedSet.contains(id))
|
|
|
.collect(Collectors.toList());
|
|
|
removeTenantComMenus(toRemove);
|
|
|
|
|
|
- List<Long> toRefresh = existIds.stream()
|
|
|
- .filter(selectedSet::contains)
|
|
|
- .collect(Collectors.toList());
|
|
|
- removeTenantComMenus(toRefresh);
|
|
|
+ batchUpsertComMenu(assignCompanyMenu);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void batchUpsertSysMenu(List<SysMenu> menus) {
|
|
|
+ if (CollectionUtils.isEmpty(menus)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (int i = 0; i < menus.size(); i += MENU_UPSERT_BATCH_SIZE) {
|
|
|
+ int end = Math.min(i + MENU_UPSERT_BATCH_SIZE, menus.size());
|
|
|
+ baseMapper.upsertSysMenu(new ArrayList<>(menus.subList(i, end)));
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (!CollectionUtils.isEmpty(assignCompanyMenu)) {
|
|
|
- baseMapper.addComMenu(assignCompanyMenu);
|
|
|
+ private void batchUpsertComMenu(List<TenantCompanyMenu> menus) {
|
|
|
+ if (CollectionUtils.isEmpty(menus)) {
|
|
|
+ return;
|
|
|
}
|
|
|
- if (!CollectionUtils.isEmpty(allSelected)) {
|
|
|
- baseMapper.updatePitchComMenu(allSelected);
|
|
|
+ for (int i = 0; i < menus.size(); i += MENU_UPSERT_BATCH_SIZE) {
|
|
|
+ int end = Math.min(i + MENU_UPSERT_BATCH_SIZE, menus.size());
|
|
|
+ baseMapper.upsertComMenu(new ArrayList<>(menus.subList(i, end)));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void removeTenantSysMenus(List<Long> menuIds) {
|
|
|
+ batchRemoveTenantSysMenus(menuIds);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void removeTenantComMenus(List<Long> menuIds) {
|
|
|
+ batchRemoveTenantComMenus(menuIds);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void batchRemoveTenantSysMenus(List<Long> menuIds) {
|
|
|
if (CollectionUtils.isEmpty(menuIds)) {
|
|
|
return;
|
|
|
}
|
|
|
- baseMapper.deleteSysRoleMenuByMenuIds(menuIds);
|
|
|
- baseMapper.deleteTenantSysMenuByIds(menuIds);
|
|
|
+ for (int i = 0; i < menuIds.size(); i += MENU_UPSERT_BATCH_SIZE) {
|
|
|
+ int end = Math.min(i + MENU_UPSERT_BATCH_SIZE, menuIds.size());
|
|
|
+ List<Long> batch = menuIds.subList(i, end);
|
|
|
+ baseMapper.deleteSysRoleMenuByMenuIds(batch);
|
|
|
+ baseMapper.deleteTenantSysMenuByIds(batch);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void removeTenantComMenus(List<Long> menuIds) {
|
|
|
+ private void batchRemoveTenantComMenus(List<Long> menuIds) {
|
|
|
if (CollectionUtils.isEmpty(menuIds)) {
|
|
|
return;
|
|
|
}
|
|
|
- baseMapper.deleteComRoleMenuByMenuIds(menuIds);
|
|
|
- baseMapper.deleteTenantComMenuByIds(menuIds);
|
|
|
+ for (int i = 0; i < menuIds.size(); i += MENU_UPSERT_BATCH_SIZE) {
|
|
|
+ int end = Math.min(i + MENU_UPSERT_BATCH_SIZE, menuIds.size());
|
|
|
+ List<Long> batch = menuIds.subList(i, end);
|
|
|
+ baseMapper.deleteComRoleMenuByMenuIds(batch);
|
|
|
+ baseMapper.deleteTenantComMenuByIds(batch);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private static List<Long> emptyIfNull(List<Long> list) {
|
|
|
return list == null ? Collections.emptyList() : list;
|
|
|
}
|
|
|
|
|
|
+ private static <T> List<T> emptyListIfNull(List<T> list) {
|
|
|
+ return list == null ? Collections.emptyList() : list;
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public TenantInfo getTenByCorpId(String corpId) {
|
|
|
return baseMapper.getTenByCorpId(corpId);
|