fix: 菜单排序 app 分组优先于 admin,sort_order 按 menuType 作用域解析
Build Backend JAR / build (push) Has been cancelled
Build Backend JAR / build (push) Has been cancelled
- menuComparator 增加 menuType 排序维度(app → admin → 其他) - resolveSortOrder 查询限定同 menuType,避免跨类型尾部误判 - 抽出 loadRawMenus 保持原始 SQL 与比较器语义一致
This commit is contained in:
+44
-10
@@ -85,7 +85,7 @@ public class PermissionMenuService {
|
|||||||
entity.setParentId(parentId);
|
entity.setParentId(parentId);
|
||||||
entity.setMenuType(menuType);
|
entity.setMenuType(menuType);
|
||||||
entity.setRoutePath(routePath);
|
entity.setRoutePath(routePath);
|
||||||
entity.setSortOrder(resolveSortOrder(request.getSortOrder(), null));
|
entity.setSortOrder(resolveSortOrder(menuType, request.getSortOrder(), null));
|
||||||
permissionMenuMapper.insert(entity);
|
permissionMenuMapper.insert(entity);
|
||||||
return toItemVo(getMenuById(entity.getId()));
|
return toItemVo(getMenuById(entity.getId()));
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ public class PermissionMenuService {
|
|||||||
entity.setParentId(parentId);
|
entity.setParentId(parentId);
|
||||||
entity.setMenuType(menuType);
|
entity.setMenuType(menuType);
|
||||||
entity.setRoutePath(routePath);
|
entity.setRoutePath(routePath);
|
||||||
entity.setSortOrder(resolveSortOrder(request.getSortOrder(), id));
|
entity.setSortOrder(resolveSortOrder(menuType, request.getSortOrder(), id));
|
||||||
permissionMenuMapper.updateById(entity);
|
permissionMenuMapper.updateById(entity);
|
||||||
return toItemVo(getMenuById(id));
|
return toItemVo(getMenuById(id));
|
||||||
}
|
}
|
||||||
@@ -410,12 +410,7 @@ public class PermissionMenuService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<PermissionMenuEntity> loadMenus(String menuType) {
|
private List<PermissionMenuEntity> loadMenus(String menuType) {
|
||||||
String normalizedType = normalizeMenuType(menuType);
|
List<PermissionMenuEntity> rows = loadRawMenus(menuType);
|
||||||
LambdaQueryWrapper<PermissionMenuEntity> query = new LambdaQueryWrapper<PermissionMenuEntity>()
|
|
||||||
.eq(normalizedType != null, PermissionMenuEntity::getMenuType, normalizedType)
|
|
||||||
.orderByAsc(PermissionMenuEntity::getSortOrder)
|
|
||||||
.orderByAsc(PermissionMenuEntity::getId);
|
|
||||||
List<PermissionMenuEntity> rows = permissionMenuMapper.selectList(query);
|
|
||||||
if (rows == null || rows.isEmpty()) {
|
if (rows == null || rows.isEmpty()) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
@@ -425,6 +420,20 @@ public class PermissionMenuService {
|
|||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches every menu (optionally scoped to one type) in insertion order.
|
||||||
|
* Sorting happens in {@link #loadMenus(String)} and only for hierarchies
|
||||||
|
* that actually need one, keeping raw SQL and comparator semantics in sync.
|
||||||
|
*/
|
||||||
|
private List<PermissionMenuEntity> loadRawMenus(String menuType) {
|
||||||
|
String normalizedType = normalizeMenuType(menuType);
|
||||||
|
LambdaQueryWrapper<PermissionMenuEntity> query = new LambdaQueryWrapper<PermissionMenuEntity>()
|
||||||
|
.eq(normalizedType != null, PermissionMenuEntity::getMenuType, normalizedType)
|
||||||
|
.orderByAsc(PermissionMenuEntity::getSortOrder)
|
||||||
|
.orderByAsc(PermissionMenuEntity::getId);
|
||||||
|
return permissionMenuMapper.selectList(query);
|
||||||
|
}
|
||||||
|
|
||||||
private List<Long> loadDirectColumnIds(Long userId) {
|
private List<Long> loadDirectColumnIds(Long userId) {
|
||||||
List<UserColumnPermissionEntity> rows = userColumnPermissionMapper.selectByUserId(userId);
|
List<UserColumnPermissionEntity> rows = userColumnPermissionMapper.selectByUserId(userId);
|
||||||
if (rows == null || rows.isEmpty()) {
|
if (rows == null || rows.isEmpty()) {
|
||||||
@@ -751,12 +760,30 @@ public class PermissionMenuService {
|
|||||||
return new ArrayList<>(uniqueIds);
|
return new ArrayList<>(uniqueIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** app 分组排在 admin 分组之前;组内按 sort_order, id 排。 */
|
||||||
private Comparator<PermissionMenuEntity> menuComparator() {
|
private Comparator<PermissionMenuEntity> menuComparator() {
|
||||||
return Comparator
|
return Comparator
|
||||||
.comparing(PermissionMenuEntity::getSortOrder, Comparator.nullsLast(Integer::compareTo))
|
.comparing(PermissionMenuEntity::getMenuType, Comparator.nullsLast(menuTypeRank()))
|
||||||
|
.thenComparing(PermissionMenuEntity::getSortOrder, Comparator.nullsLast(Integer::compareTo))
|
||||||
.thenComparing(PermissionMenuEntity::getId, Comparator.nullsLast(Long::compareTo));
|
.thenComparing(PermissionMenuEntity::getId, Comparator.nullsLast(Long::compareTo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Comparator<String> menuTypeRank() {
|
||||||
|
return Comparator.comparing(this::menuTypePriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** App 菜单优先展示在 admin 菜单之前。 */
|
||||||
|
private int menuTypePriority(String menuType) {
|
||||||
|
if (MENU_TYPE_APP.equals(menuType)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (MENU_TYPE_ADMIN.equals(menuType)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Internal/legacy rows stay out of the way of both user-facing groups.
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
private List<PermissionMenuItemVo> toItemVos(List<PermissionMenuEntity> visibleMenus,
|
private List<PermissionMenuItemVo> toItemVos(List<PermissionMenuEntity> visibleMenus,
|
||||||
List<PermissionMenuEntity> hierarchyMenus) {
|
List<PermissionMenuEntity> hierarchyMenus) {
|
||||||
Map<Long, PermissionMenuEntity> menuMap = hierarchyMenus.stream()
|
Map<Long, PermissionMenuEntity> menuMap = hierarchyMenus.stream()
|
||||||
@@ -800,11 +827,18 @@ public class PermissionMenuService {
|
|||||||
return root.getColumnKey();
|
return root.getColumnKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer resolveSortOrder(Integer sortOrder, Long excludeId) {
|
/**
|
||||||
|
* Resolves the default sort order when none is supplied, scoped to the
|
||||||
|
* menu's own type (parent takes precedence, then hierarchy ancestors).
|
||||||
|
* The DB query mirrors {@link #loadMenus(String)} ordering so the last row
|
||||||
|
* is the true tail of the type's ordering.
|
||||||
|
*/
|
||||||
|
private Integer resolveSortOrder(String menuType, Integer sortOrder, Long excludeId) {
|
||||||
if (sortOrder != null) {
|
if (sortOrder != null) {
|
||||||
return sortOrder;
|
return sortOrder;
|
||||||
}
|
}
|
||||||
PermissionMenuEntity tail = permissionMenuMapper.selectOne(new LambdaQueryWrapper<PermissionMenuEntity>()
|
PermissionMenuEntity tail = permissionMenuMapper.selectOne(new LambdaQueryWrapper<PermissionMenuEntity>()
|
||||||
|
.eq(PermissionMenuEntity::getMenuType, normalizeMenuType(menuType))
|
||||||
.ne(excludeId != null, PermissionMenuEntity::getId, excludeId)
|
.ne(excludeId != null, PermissionMenuEntity::getId, excludeId)
|
||||||
.orderByDesc(PermissionMenuEntity::getSortOrder)
|
.orderByDesc(PermissionMenuEntity::getSortOrder)
|
||||||
.orderByDesc(PermissionMenuEntity::getId)
|
.orderByDesc(PermissionMenuEntity::getId)
|
||||||
|
|||||||
Reference in New Issue
Block a user