From 5d0e4bcaf5d44a9ce2ff196e38c77676aa8ea880 Mon Sep 17 00:00:00 2001
From: zhouwx <1175765986@qq.com>
Date: Fri, 12 Jun 2026 16:37:15 +0800
Subject: [PATCH] 中科大支线—添加菜单、角色

---
 src/layout/components/Sidebar/SidebarItem.vue |  181 ++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 152 insertions(+), 29 deletions(-)

diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue
index c423fb1..cf69f54 100644
--- a/src/layout/components/Sidebar/SidebarItem.vue
+++ b/src/layout/components/Sidebar/SidebarItem.vue
@@ -1,33 +1,147 @@
 <template>
+<!--  <div v-if="!item.hidden">-->
+<!--    <template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">-->
+<!--      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">-->
+<!--        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">-->
+<!--          <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"/>-->
+<!--          <template #title><span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span></template>-->
+<!--        </el-menu-item>-->
+<!--      </app-link>-->
+<!--    </template>-->
+
+<!--    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>-->
+<!--      <template v-if="item.meta" #title>-->
+<!--        <svg-icon :icon-class="item.meta && item.meta.icon" />-->
+<!--        <span class="menu-title" :title="hasTitle(item.meta.title)">{{ item.meta.title }}</span>-->
+<!--      </template>-->
+
+<!--      <sidebar-item-->
+<!--        v-for="child in item.children"-->
+<!--        :key="child.path"-->
+<!--        :is-nest="true"-->
+<!--        :item="child"-->
+<!--        :base-path="resolvePath(child.path)"-->
+<!--        class="nest-menu"-->
+<!--      />-->
+<!--    </el-sub-menu>-->
+<!--  </div>-->
   <div v-if="!item.hidden">
-    <template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
-      <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
-        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{ 'submenu-title-noDropdown': !isNest }">
-          <svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)"/>
-          <template #title><span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span></template>
+    <!-- 优化条件:优先判定【仅有1个可见子菜单】,直接走一级菜单渲染 -->
+    <template v-if="calcSingleChild(item) && item.path != '/system'">
+      <app-link v-if="onlyOneChild?.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)">
+        <el-menu-item
+            :index="resolvePath(onlyOneChild.path)"
+            :class="{ 'submenu-title-noDropdown': !isNest }"
+        >
+          <svg-icon :icon-class="item.meta?.icon || onlyOneChild.meta?.icon"/>
+          <template #title>
+            <span class="menu-title" :title="hasTitle(item.meta?.title || onlyOneChild.meta?.title)">
+              {{ item.meta?.title || onlyOneChild.meta?.title }}
+            </span>
+          </template>
         </el-menu-item>
       </app-link>
     </template>
 
-    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
+    <!-- 多个子菜单 / 强制目录:正常展开二级菜单 -->
+    <el-sub-menu
+        v-else
+        ref="subMenu"
+        :index="resolvePath(item.path)"
+        popper-append-to-body
+    >
       <template v-if="item.meta" #title>
         <svg-icon :icon-class="item.meta && item.meta.icon" />
         <span class="menu-title" :title="hasTitle(item.meta.title)">{{ item.meta.title }}</span>
       </template>
 
       <sidebar-item
-        v-for="child in item.children"
-        :key="child.path"
-        :is-nest="true"
-        :item="child"
-        :base-path="resolvePath(child.path)"
-        class="nest-menu"
+          v-for="child in item.children"
+          :key="child.path"
+          :is-nest="true"
+          :item="child"
+          :base-path="resolvePath(child.path)"
+          class="nest-menu"
       />
     </el-sub-menu>
   </div>
 </template>
 
+<!--<script setup>-->
+<!--import { isExternal } from '@/utils/validate'-->
+<!--import AppLink from './Link'-->
+<!--import { getNormalPath } from '@/utils/ruoyi'-->
+
+<!--const props = defineProps({-->
+<!--  // route object-->
+<!--  item: {-->
+<!--    type: Object,-->
+<!--    required: true-->
+<!--  },-->
+<!--  isNest: {-->
+<!--    type: Boolean,-->
+<!--    default: false-->
+<!--  },-->
+<!--  basePath: {-->
+<!--    type: String,-->
+<!--    default: ''-->
+<!--  }-->
+<!--})-->
+
+<!--const onlyOneChild = ref({});-->
+
+<!--function hasOneShowingChild(children = [], parent) {-->
+<!--  if (!children) {-->
+<!--    children = [];-->
+<!--  }-->
+<!--  const showingChildren = children.filter(item => {-->
+<!--    if (item.hidden) {-->
+<!--      return false-->
+<!--    } else {-->
+<!--      // Temp set(will be used if only has one showing child)-->
+<!--      onlyOneChild.value = item-->
+<!--      return true-->
+<!--    }-->
+<!--  })-->
+
+<!--  // When there is only one child router, the child router is displayed by default-->
+<!--  if (showingChildren.length === 1) {-->
+<!--    return true-->
+<!--  }-->
+
+<!--  // Show parent if there are no child router to display-->
+<!--  if (showingChildren.length === 0) {-->
+<!--    onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }-->
+<!--    return true-->
+<!--  }-->
+
+<!--  return false-->
+<!--};-->
+
+<!--function resolvePath(routePath, routeQuery) {-->
+<!--  if (isExternal(routePath)) {-->
+<!--    return routePath-->
+<!--  }-->
+<!--  if (isExternal(props.basePath)) {-->
+<!--    return props.basePath-->
+<!--  }-->
+<!--  if (routeQuery) {-->
+<!--    let query = JSON.parse(routeQuery);-->
+<!--    return { path: getNormalPath(props.basePath + '/' + routePath), query: query }-->
+<!--  }-->
+<!--  return getNormalPath(props.basePath + '/' + routePath)-->
+<!--}-->
+
+<!--function hasTitle(title){-->
+<!--  if (title.length > 5) {-->
+<!--    return title;-->
+<!--  } else {-->
+<!--    return "";-->
+<!--  }-->
+<!--}-->
+<!--</script>-->
 <script setup>
+import { ref } from 'vue'
 import { isExternal } from '@/utils/validate'
 import AppLink from './Link'
 import { getNormalPath } from '@/utils/ruoyi'
@@ -48,35 +162,44 @@
   }
 })
 
-const onlyOneChild = ref({});
+// 修复:初始化为 null,而非空对象
+const onlyOneChild = ref(null);
 
+/**
+ * 修复版:判断是否只有一个可见子菜单(核心改动)
+ */
 function hasOneShowingChild(children = [], parent) {
-  if (!children) {
-    children = [];
-  }
-  const showingChildren = children.filter(item => {
-    if (item.hidden) {
-      return false
-    } else {
-      // Temp set(will be used if only has one showing child)
-      onlyOneChild.value = item
-      return true
-    }
-  })
+  if (!children) children = []
 
-  // When there is only one child router, the child router is displayed by default
+  // 1. 先统一过滤出【未隐藏】的子菜单
+  const showingChildren = children.filter(item => !item.hidden)
+
+  // 2. 仅有 1 个可见子菜单:赋值 + 标记无下级,适配原有判断
   if (showingChildren.length === 1) {
+    const child = showingChildren[0]
+    // 标记:当前子菜单没有可展示的下级(关键,适配原模板逻辑)
+    onlyOneChild.value = { ...child, noShowingChildren: true }
     return true
   }
 
-  // Show parent if there are no child router to display
+  // 3. 没有可见子菜单
   if (showingChildren.length === 0) {
     onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
     return true
   }
 
+  // 4. 多个子菜单
+  onlyOneChild.value = null
   return false
-};
+}
+
+/**
+ * 新增统一判断方法:简化模板条件,命中「单菜单合并逻辑」
+ */
+function calcSingleChild(item) {
+// 存在子菜单 且 仅有一个可见子菜单
+  return hasOneShowingChild(item.children, item)
+}
 
 function resolvePath(routePath, routeQuery) {
   if (isExternal(routePath)) {
@@ -93,7 +216,7 @@
 }
 
 function hasTitle(title){
-  if (title.length > 5) {
+  if (title && title.length > 5) {
     return title;
   } else {
     return "";

--
Gitblit v1.9.2