diff --git a/pc/src/components/CommonAside.vue b/pc/src/components/CommonAside.vue
index d4e474e..dab7ea6 100644
--- a/pc/src/components/CommonAside.vue
+++ b/pc/src/components/CommonAside.vue
@@ -103,23 +103,62 @@ const activeBgColor = computed(() => {
// 将后端数据转换为前端需要的格式
const transformMenuData = (menus) => {
- // 功能页面路径关键词,这些菜单不应该显示在侧边栏
- const functionPageKeywords = ['/detail', '/add', '/edit', '/delete', '/create', '/update', '/category', '/tag'];
+ if (!menus || menus.length === 0) {
+ console.warn('菜单数据为空');
+ return [];
+ }
- // 判断是否是功能页面
+ console.log('原始菜单数据:', menus);
+
+ // 功能页面路径关键词,这些菜单不应该显示在侧边栏
+ // 注意:只过滤真正的功能页面,不过滤包含这些关键词的父菜单
+ const functionPageKeywords = ['/detail', '/add', '/edit', '/delete', '/create', '/update'];
+
+ // 需要隐藏的子菜单路径(这些子菜单不应该显示在侧边栏)
+ const hiddenSubMenuPaths = ['/apps/knowledge/category', '/apps/knowledge/tag'];
+
+ // 判断是否是功能页面(更精确的判断)
const isFunctionPage = (path) => {
if (!path) return false;
const lowerPath = path.toLowerCase();
- return functionPageKeywords.some(keyword => lowerPath.includes(keyword));
+ // 检查路径是否以这些关键词结尾,或者是这些关键词的组合
+ // 例如:/apps/knowledge/detail 是功能页面
+ // 但 /apps/knowledge 不是功能页面
+ return functionPageKeywords.some(keyword => {
+ // 检查路径是否以关键词结尾,或者路径中包含 /keyword/ 或 /keyword
+ return lowerPath.endsWith(keyword) ||
+ lowerPath.includes(`/${keyword}/`) ||
+ lowerPath.endsWith(`/${keyword}`);
+ });
+ };
+
+ // 判断是否是需要隐藏的子菜单
+ const isHiddenSubMenu = (path) => {
+ if (!path) return false;
+ const lowerPath = path.toLowerCase();
+ return hiddenSubMenuPaths.some(hiddenPath => {
+ return lowerPath === hiddenPath || lowerPath.startsWith(hiddenPath + '/');
+ });
};
- // 首先映射字段格式,只保留页面菜单(menu_type=1),并过滤掉功能页面
+ // 首先映射字段格式,只保留页面菜单(menu_type=1),并过滤掉功能页面和需要隐藏的子菜单
const allMenus = menus
.filter(menu => {
// 只显示页面菜单,不显示API权限菜单
- if (menu.menuType !== 1) return false;
- // 过滤掉功能页面(详情、新增、编辑、删除、分类、标签等)
- if (isFunctionPage(menu.path)) return false;
+ if (menu.menuType !== 1 && menu.menuType !== undefined) {
+ console.log('过滤掉非页面菜单:', menu);
+ return false;
+ }
+ // 过滤掉功能页面(详情、新增、编辑、删除等)
+ if (isFunctionPage(menu.path)) {
+ console.log('过滤掉功能页面:', menu.path);
+ return false;
+ }
+ // 过滤掉需要隐藏的子菜单(如分类管理、标签管理)
+ if (isHiddenSubMenu(menu.path)) {
+ console.log('过滤掉隐藏的子菜单:', menu.path);
+ return false;
+ }
return true;
})
.map(menu => ({
@@ -133,16 +172,19 @@ const transformMenuData = (menus) => {
children: []
}));
+ console.log('过滤后的菜单数据:', allMenus);
+
// 构建菜单映射表(只包含有效的页面菜单)
const menuMap = new Map();
allMenus.forEach(menu => {
menuMap.set(menu.id, menu);
});
- // 构建树形结构,只保留那些父菜单也存在的菜单项
+ // 构建树形结构
+ // 如果父菜单不在当前数据中,将菜单项作为根菜单显示
const rootMenus = [];
allMenus.forEach(menu => {
- if (menu.parentId === 0) {
+ if (menu.parentId === 0 || !menu.parentId) {
// 顶级菜单直接加入
rootMenus.push(menu);
} else {
@@ -154,10 +196,16 @@ const transformMenuData = (menus) => {
parent.children = [];
}
parent.children.push(menu);
+ } else {
+ // 如果父菜单不存在,可能是父菜单被过滤掉了,或者父菜单不在当前返回的数据中
+ // 这种情况下,将该菜单作为根菜单显示(避免菜单丢失)
+ console.warn('菜单的父菜单不存在,将作为根菜单显示。菜单ID:', menu.id, '父菜单ID:', menu.parentId, '菜单路径:', menu.path);
+ rootMenus.push(menu);
}
- // 如果父菜单不存在(被过滤掉了或者是menu_type=2),则忽略该菜单项,不添加到任何地方
}
});
+
+ console.log('构建后的菜单树:', rootMenus);
// 按 order 排序(确保排序正确)
const sortMenus = (menus) => {
diff --git a/pc/src/components/CommonHeader.vue b/pc/src/components/CommonHeader.vue
index 6a2abd2..7be6a5e 100644
--- a/pc/src/components/CommonHeader.vue
+++ b/pc/src/components/CommonHeader.vue
@@ -193,6 +193,33 @@ const handleCommand = async (command) => {
// 清除菜单缓存
menuStore.resetMenus();
+ // 清除所有以 menu_cache_ 开头的本地存储项
+ const menuCacheKeys: string[] = [];
+ // 遍历 localStorage
+ for (let i = 0; i < localStorage.length; i++) {
+ const key = localStorage.key(i);
+ if (key && key.startsWith('menu_cache_')) {
+ menuCacheKeys.push(key);
+ }
+ }
+ // 删除 localStorage 中的 menu_cache_ 项
+ menuCacheKeys.forEach(key => {
+ localStorage.removeItem(key);
+ });
+
+ // 遍历 sessionStorage
+ const sessionMenuCacheKeys: string[] = [];
+ for (let i = 0; i < sessionStorage.length; i++) {
+ const key = sessionStorage.key(i);
+ if (key && key.startsWith('menu_cache_')) {
+ sessionMenuCacheKeys.push(key);
+ }
+ }
+ // 删除 sessionStorage 中的 menu_cache_ 项
+ sessionMenuCacheKeys.forEach(key => {
+ sessionStorage.removeItem(key);
+ });
+
// 重置 tabs store 状态
const { useTabsStore } = await import('@/stores');
const tabsStore = useTabsStore();
diff --git a/pc/src/views/system/files/FileCategory.vue b/pc/src/views/system/files/FileCategory.vue
index 07d71a2..25d82e6 100644
--- a/pc/src/views/system/files/FileCategory.vue
+++ b/pc/src/views/system/files/FileCategory.vue
@@ -26,21 +26,17 @@
-
+
-
-
- {{ row.file_count || 0 }} 个文件
-
-
+ {{ row.file_count || 0 }}
-
+
{{ row.sort_order || 0 }}
-
+
-
+
编辑
diff --git a/pc/src/views/system/roles/index.vue b/pc/src/views/system/roles/index.vue
index fb7d1e4..7be1089 100644
--- a/pc/src/views/system/roles/index.vue
+++ b/pc/src/views/system/roles/index.vue
@@ -51,7 +51,7 @@
详情
0 {
+ // 继续查找父菜单的父菜单
+ if parentMenu.ParentId > 0 {
+ findParents(parentMenu.ParentId)
+ }
+ }
+ }
+
+ // 为每个菜单查找其父菜单
+ for _, m := range menus {
+ if m.ParentId > 0 {
+ findParents(m.ParentId)
+ }
+ }
+
+ // 5. 如果存在父菜单,查询所有父菜单
+ if len(parentIds) > 0 {
+ parentIdList := make([]int, 0, len(parentIds))
+ for pid := range parentIds {
+ parentIdList = append(parentIdList, pid)
+ }
+
+ // 构建父菜单查询
+ parentPlaceholders := make([]string, len(parentIdList))
+ parentArgs := make([]interface{}, len(parentIdList)+1)
+ for i, id := range parentIdList {
+ parentPlaceholders[i] = "?"
+ parentArgs[i] = id
+ }
+ parentArgs[len(parentIdList)] = 1 // menu_type=1
+
+ parentQuery := "SELECT id, name, path, parent_id, icon, `order`, status, component_path, is_external, external_url, menu_type, permission " +
+ "FROM yz_menus " +
+ "WHERE id IN (" + strings.Join(parentPlaceholders, ",") + ") " +
+ "AND delete_time IS NULL " +
+ "AND menu_type = ? " +
+ "ORDER BY `order`, id"
+
+ var parentMenus []*Menu
+ _, err = o.Raw(parentQuery, parentArgs...).QueryRows(&parentMenus)
+ if err == nil && len(parentMenus) > 0 {
+ // 将父菜单添加到结果中(去重)
+ menuMap := make(map[int]*Menu)
+ for _, m := range menus {
+ menuMap[m.Id] = m
+ }
+ for _, pm := range parentMenus {
+ if _, exists := menuMap[pm.Id]; !exists {
+ menus = append(menus, pm)
+ menuMap[pm.Id] = pm
+ }
+ }
+ }
+ }
+
+ // 6. 转换为map格式
result := make([]map[string]interface{}, 0, len(menus))
for _, m := range menus {
item := map[string]interface{}{