mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 16:00:51 +00:00
fix: avoid sidebar menu flicker when loading and sorting (#12066)
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -82,6 +83,15 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
for _, set := range setting {
|
||||
settingMap[set.Key] = set.Value
|
||||
}
|
||||
if hideMenu, ok := settingMap["HideMenu"]; ok && len(hideMenu) > 0 {
|
||||
var menus []dto.ShowMenu
|
||||
if err := json.Unmarshal([]byte(hideMenu), &menus); err == nil {
|
||||
sortShowMenus(menus)
|
||||
if sortedBytes, err := json.Marshal(menus); err == nil {
|
||||
settingMap["HideMenu"] = string(sortedBytes)
|
||||
}
|
||||
}
|
||||
}
|
||||
var info dto.SettingInfo
|
||||
arr, err := json.Marshal(settingMap)
|
||||
if err != nil {
|
||||
@@ -103,6 +113,20 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
|
||||
return &info, err
|
||||
}
|
||||
|
||||
func sortShowMenus(menus []dto.ShowMenu) {
|
||||
for i := range menus {
|
||||
if len(menus[i].Children) > 0 {
|
||||
sortShowMenus(menus[i].Children)
|
||||
}
|
||||
}
|
||||
sort.SliceStable(menus, func(i, j int) bool {
|
||||
if menus[i].Sort == menus[j].Sort {
|
||||
return menus[i].ID < menus[j].ID
|
||||
}
|
||||
return menus[i].Sort < menus[j].Sort
|
||||
})
|
||||
}
|
||||
|
||||
func (u *SettingService) Update(key, value string) error {
|
||||
oldVal, err := settingRepo.Get(repo.WithByKey(key))
|
||||
if err != nil {
|
||||
|
||||
@@ -39,7 +39,6 @@ import { GlobalStore, MenuStore } from '@/store';
|
||||
import { isString } from '@vueuse/core';
|
||||
import { getSettingInfo } from '@/api/modules/setting';
|
||||
import PrimaryMenu from '@/assets/images/menu-bg.svg?component';
|
||||
import { sortMenu } from '@/utils/util';
|
||||
|
||||
const route = useRoute();
|
||||
const menuStore = MenuStore();
|
||||
@@ -72,13 +71,13 @@ const handleMenuClick = (path) => {
|
||||
emit('menuClick', path);
|
||||
};
|
||||
|
||||
function getCheckedLabels(menu: any, showMap: any) {
|
||||
function getCheckedLabels(menu: any, showSet: Set<string>) {
|
||||
for (const item of menu) {
|
||||
if (item.isShow) {
|
||||
showMap[item.label] = true;
|
||||
showSet.add(item.label);
|
||||
}
|
||||
if (item.children) {
|
||||
getCheckedLabels(item.children, showMap);
|
||||
getCheckedLabels(item.children, showSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,73 +87,50 @@ const openTask = () => {
|
||||
};
|
||||
|
||||
const search = async () => {
|
||||
const res = await getSettingInfo();
|
||||
version.value = res.data.systemVersion;
|
||||
let hideMenu = JSON.parse(res.data.hideMenu);
|
||||
sortMenu(hideMenu);
|
||||
const showMap = new Map();
|
||||
getCheckedLabels(hideMenu, showMap);
|
||||
const rootMap = new Map();
|
||||
hideMenu.forEach((m, index) => {
|
||||
rootMap.set(m.label, index);
|
||||
});
|
||||
let rstMenuList: RouteRecordRaw[] = [];
|
||||
let resMenuList: RouteRecordRaw[] = [];
|
||||
resMenuList = adjustAndCleanMenu(hideMenu, menuStore.menuList);
|
||||
for (const menu of resMenuList) {
|
||||
let menuItem = JSON.parse(JSON.stringify(menu));
|
||||
if (!showMap[menuItem.name]) {
|
||||
continue;
|
||||
} else if (menuItem.name === 'Xpack-Menu') {
|
||||
menuItem.meta.hideInSidebar = false;
|
||||
}
|
||||
const childMenu = hideMenu.find((item) => item.label == menu.name);
|
||||
const childMap = buildIndexMap(childMenu?.children || []);
|
||||
const itemChildren =
|
||||
(menuItem.children ?? [])
|
||||
.filter(
|
||||
try {
|
||||
const res = await getSettingInfo();
|
||||
version.value = res.data.systemVersion;
|
||||
let hideMenu = JSON.parse(res.data.hideMenu);
|
||||
const showSet = new Set<string>();
|
||||
getCheckedLabels(hideMenu, showSet);
|
||||
const rstMenuList: RouteRecordRaw[] = [];
|
||||
const resMenuList = adjustAndCleanMenu(hideMenu, menuList);
|
||||
for (const menu of resMenuList) {
|
||||
let menuItem = JSON.parse(JSON.stringify(menu));
|
||||
if (!showSet.has(menuItem.name as string)) {
|
||||
continue;
|
||||
} else if (menuItem.name === 'Xpack-Menu') {
|
||||
menuItem.meta.hideInSidebar = false;
|
||||
}
|
||||
const itemChildren =
|
||||
(menuItem.children ?? []).filter(
|
||||
(item) =>
|
||||
item.name && showMap[item.name as string] && !(item.name === 'Upage' && globalStore.isIntl),
|
||||
)
|
||||
.sort(sortByMap(childMap)) || [];
|
||||
item.name && showSet.has(item.name as string) && !(item.name === 'Upage' && globalStore.isIntl),
|
||||
) || [];
|
||||
|
||||
if (itemChildren.length === 1) {
|
||||
menuItem.meta.icon = itemChildren[0].meta.icon;
|
||||
menuItem.meta.title = itemChildren[0].meta.title;
|
||||
if (itemChildren.length === 1) {
|
||||
menuItem.meta.icon = itemChildren[0].meta.icon;
|
||||
menuItem.meta.title = itemChildren[0].meta.title;
|
||||
}
|
||||
menuItem.children = itemChildren;
|
||||
rstMenuList.push(menuItem);
|
||||
}
|
||||
if (!isSameMenuList(menuStore.menuList as RouteRecordRaw[], rstMenuList)) {
|
||||
menuStore.setMenuList(rstMenuList);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!menuStore.menuList || menuStore.menuList.length === 0) {
|
||||
menuStore.setMenuList(menuList);
|
||||
}
|
||||
menuItem.children = itemChildren;
|
||||
rstMenuList.push(menuItem);
|
||||
}
|
||||
rstMenuList.sort((a, b) => {
|
||||
const labelA = a.name;
|
||||
const labelB = b.name;
|
||||
const indexA = rootMap.get(labelA) ?? Infinity;
|
||||
const indexB = rootMap.get(labelB) ?? Infinity;
|
||||
return indexA - indexB;
|
||||
});
|
||||
menuStore.menuList = rstMenuList;
|
||||
};
|
||||
|
||||
function buildIndexMap(list: any[]): Map<string, number> {
|
||||
const map = new Map<string, number>();
|
||||
list.forEach((m, i) => map.set(m.label, i));
|
||||
return map;
|
||||
}
|
||||
|
||||
function sortByMap(map: Map<string, number>) {
|
||||
return (a: { name: string }, b: { name: string }) => {
|
||||
const indexA = map.get(a.name) ?? Infinity;
|
||||
const indexB = map.get(b.name) ?? Infinity;
|
||||
return indexA - indexB;
|
||||
};
|
||||
function isSameMenuList(source: RouteRecordRaw[], target: RouteRecordRaw[]) {
|
||||
return JSON.stringify(source) === JSON.stringify(target);
|
||||
}
|
||||
|
||||
function adjustAndCleanMenu(menuItem, list) {
|
||||
const menuList = JSON.parse(JSON.stringify(list));
|
||||
const orderMap = new Map();
|
||||
menuItem.forEach((item, index) => {
|
||||
orderMap.set(item.label, index);
|
||||
});
|
||||
const itemMap = new Map();
|
||||
for (const parent of menuList) {
|
||||
itemMap.set(parent.name, parent);
|
||||
@@ -175,15 +151,7 @@ function adjustAndCleanMenu(menuItem, list) {
|
||||
if (!matched) continue;
|
||||
|
||||
if (Array.isArray(ref.children) && ref.children.length > 0) {
|
||||
const childMap = buildIndexMap(ref.children || []);
|
||||
matched.children = buildTree(ref.children);
|
||||
matched.children.sort((a, b) => {
|
||||
const labelA = a.name;
|
||||
const labelB = b.name;
|
||||
const indexA = childMap.get(labelA) ?? Infinity;
|
||||
const indexB = childMap.get(labelB) ?? Infinity;
|
||||
return indexA - indexB;
|
||||
});
|
||||
} else {
|
||||
delete matched.children;
|
||||
}
|
||||
@@ -195,11 +163,6 @@ function adjustAndCleanMenu(menuItem, list) {
|
||||
}
|
||||
|
||||
const newMenu = buildTree(menuItem);
|
||||
newMenu.sort((a, b) => {
|
||||
const indexA = orderMap.get(a.name) ?? Infinity;
|
||||
const indexB = orderMap.get(b.name) ?? Infinity;
|
||||
return indexA - indexB;
|
||||
});
|
||||
for (const menu of newMenu) {
|
||||
if (menu.children?.length === 1) {
|
||||
menu.meta.icon = menu.children[0].meta.icon;
|
||||
@@ -211,7 +174,9 @@ function adjustAndCleanMenu(menuItem, list) {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
menuStore.setMenuList(menuList);
|
||||
if (!menuStore.menuList || menuStore.menuList.length === 0) {
|
||||
menuStore.setMenuList(menuList);
|
||||
}
|
||||
search();
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user