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