Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
R
ruoshui-ui
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
etl-ruoshui
ruoshui-ui
Commits
b70d85dc
继续操作前请注册或者登录。
提交
b70d85dc
authored
1月 10, 2026
作者:
吕本才
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
快捷菜单
上级
35b3b12a
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
552 行增加
和
3 行删除
+552
-3
index.js
src/router/index.js
+66
-0
index.vue
src/views/index/admin/index.vue
+486
-3
没有找到文件。
src/router/index.js
浏览文件 @
b70d85dc
...
...
@@ -88,6 +88,72 @@ export const constantRoutes = [
}
]
},
// 快捷菜单路由
{
path
:
'/jcjs'
,
component
:
Layout
,
hidden
:
true
,
children
:
[
{
path
:
'sjy'
,
component
:
()
=>
import
(
'@/views/rule/datasource/index'
),
name
:
'DataSource'
,
meta
:
{
title
:
'数据源管理'
}
}
]
},
{
path
:
'/sjjc'
,
component
:
Layout
,
hidden
:
true
,
children
:
[
{
path
:
'jobInfo'
,
component
:
()
=>
import
(
'@/views/datax/jobInfo/index'
),
name
:
'JobInfo'
,
meta
:
{
title
:
'任务管理'
}
}
]
},
{
path
:
'/flink'
,
component
:
Layout
,
hidden
:
true
,
children
:
[
{
path
:
'FlinkTaskManage'
,
component
:
()
=>
import
(
'@/views/flink/task-manage/index'
),
name
:
'FlinkTaskManage'
,
meta
:
{
title
:
'任务列表'
}
}
]
},
{
path
:
'/market'
,
component
:
Layout
,
hidden
:
true
,
children
:
[
{
path
:
'dataapi'
,
component
:
()
=>
import
(
'@/views/market/dataapi/index'
),
name
:
'DataApi'
,
meta
:
{
title
:
'数据服务'
}
}
]
},
{
path
:
'/quality'
,
component
:
Layout
,
hidden
:
true
,
children
:
[
{
path
:
'checkrule'
,
component
:
()
=>
import
(
'@/views/quality/checkrule/index'
),
name
:
'CheckRule'
,
meta
:
{
title
:
'规则配置'
}
}
]
},
{
path
:
'/flink/task-manage'
,
redirect
:
'noRedirect'
,
...
...
src/views/index/admin/index.vue
浏览文件 @
b70d85dc
<
template
>
<div
class=
"dashboard-container"
>
<div
class=
"dashboard-text"
>
欢迎使用大数据平台
</div>
<div
class=
"dashboard-description"
>
这是一个用于管理大数据任务的平台
</div>
<div
class=
"quick-menu"
>
<div
class=
"menu-header"
>
<h3>
快捷菜单
</h3>
<div>
<el-button
type=
"primary"
size=
"small"
@
click=
"openConfigDialog"
>
<i
class=
"el-icon-setting"
></i>
配置
</el-button>
</div>
</div>
<div
class=
"menu-grid"
>
<router-link
v-for=
"menu in displayMenus"
:key=
"menu.id"
:to=
"menu.path || '#'"
class=
"menu-item"
v-if=
"menu && menu.path"
>
<div
class=
"menu-icon"
>
{{
menu
.
icon
}}
</div>
<div
class=
"menu-label"
>
{{
menu
.
label
}}
</div>
</router-link>
</div>
</div>
<!-- 快捷菜单配置抽屉 -->
<el-drawer
title=
"配置快捷菜单"
:visible
.
sync=
"configDialogVisible"
direction=
"rtl"
size=
"600px"
>
<el-form
:model=
"configForm"
label-width=
"80px"
>
<el-form-item
label=
"选择菜单"
>
<el-checkbox-group
v-model=
"configForm.selectedMenus"
>
<div
v-for=
"(menuNode, index1) in menuTree"
:key=
"menuNode.menuId"
>
<div
style=
"display: flex; align-items: center;"
class=
"menu-level-1"
>
<span
style=
"cursor: pointer; flex: 1;"
@
click
.
stop=
"toggleMenu(menuNode.menuId)"
>
{{
index1
+
1
}}
.
{{
menuNode
.
menuName
}}
</span>
</div>
<div
v-if=
"menuNode.children && menuNode.children.length > 0"
style=
"margin-left: 20px;"
v-show=
"expandedMenus[menuNode.menuId]"
>
<div
v-for=
"(childNode, index2) in menuNode.children"
:key=
"childNode.menuId"
>
<div
v-if=
"!childNode.children || childNode.children.length === 0"
class=
"menu-level-2"
>
<el-checkbox
:label=
"childNode.menuId.toString()"
>
{{
index1
+
1
}}
.
{{
index2
+
1
}}
{{
childNode
.
menuName
}}
</el-checkbox>
</div>
<div
v-else
style=
"display: flex; align-items: center;"
class=
"menu-level-2"
>
<span
style=
"cursor: pointer; flex: 1;"
@
click
.
stop=
"toggleMenu(childNode.menuId)"
>
{{
index1
+
1
}}
.
{{
index2
+
1
}}
{{
childNode
.
menuName
}}
</span>
</div>
<div
v-if=
"childNode.children && childNode.children.length > 0"
style=
"margin-left: 20px;"
v-show=
"expandedMenus[childNode.menuId]"
>
<div
v-for=
"(grandChildNode, index3) in childNode.children"
:key=
"grandChildNode.menuId"
>
<el-checkbox
:label=
"grandChildNode.menuId.toString()"
class=
"menu-level-3"
>
{{
index1
+
1
}}
.
{{
index2
+
1
}}
.
{{
index3
+
1
}}
{{
grandChildNode
.
menuName
}}
</el-checkbox>
</div>
</div>
</div>
</div>
</div>
</el-checkbox-group>
</el-form-item>
</el-form>
<el-button
type=
"success"
size=
"small"
@
click=
"saveMenuConfig"
style=
"margin-left: 10px;"
>
<i
class=
"el-icon-save"
></i>
保存配置
</el-button>
<el-button
size=
"small"
@
click=
"cancelMenuConfig"
style=
"margin-left: 10px;"
>
<i
class=
"el-icon-close"
></i>
取消配置
</el-button>
</el-drawer>
</div>
</
template
>
<
script
>
import
{
listMenu
}
from
'@/api/system/menu'
export
default
{
name
:
'Index'
name
:
'Index'
,
data
()
{
return
{
configDialogVisible
:
false
,
configForm
:
{
selectedMenus
:
[]
},
// 所有可用的菜单
allMenus
:
[],
// 菜单树数据
menuTree
:
[],
// 默认选中的菜单配置
defaultMenuConfig
:
[],
// 加载状态
loading
:
false
,
// 菜单展开状态
expandedMenus
:
{},
// 用于触发菜单更新的时间戳
menuUpdateTime
:
Date
.
now
()
}
},
computed
:
{
// 显示的菜单
displayMenus
()
{
console
.
log
(
'this.displayMenus -000000000000000000'
);
// 通过引用menuUpdateTime,确保当它变化时计算属性会重新计算
this
.
menuUpdateTime
;
let
savedMenuConfig
;
try
{
savedMenuConfig
=
localStorage
.
getItem
(
'quickMenuConfig'
)
?
JSON
.
parse
(
localStorage
.
getItem
(
'quickMenuConfig'
))
:
null
;
}
catch
(
error
)
{
console
.
error
(
'解析菜单配置失败:'
,
error
);
savedMenuConfig
=
null
;
}
// 确保返回有效的菜单配置
let
finalMenuConfig
;
if
(
!
savedMenuConfig
||
!
Array
.
isArray
(
savedMenuConfig
)
||
savedMenuConfig
.
length
===
0
)
{
finalMenuConfig
=
this
.
defaultMenuConfig
;
}
else
{
// 过滤掉无效的菜单项(没有路径或路径无效)
let
filteredMenus
=
savedMenuConfig
.
filter
(
menu
=>
{
return
menu
&&
menu
.
id
&&
menu
.
path
&&
typeof
menu
.
path
===
'string'
&&
menu
.
path
.
trim
()
!==
''
;
});
// 去重处理,确保每个菜单ID唯一
const
menuMap
=
new
Map
();
filteredMenus
.
forEach
(
menu
=>
{
if
(
menu
&&
menu
.
id
)
{
menuMap
.
set
(
menu
.
id
,
menu
);
}
});
// 转换为数组,得到去重后的菜单列表
filteredMenus
=
Array
.
from
(
menuMap
.
values
());
// 如果过滤后没有有效菜单,使用默认配置
finalMenuConfig
=
filteredMenus
.
length
>
0
?
filteredMenus
:
this
.
defaultMenuConfig
;
}
return
finalMenuConfig
;
}
},
created
()
{
console
.
log
(
'ceeated'
,
this
.
defaultMenuConfig
);
this
.
loadMenus
();
},
methods
:
{
// 加载菜单数据
loadMenus
()
{
console
.
log
(
'loadMenus--1111111111111111111'
);
this
.
loading
=
true
;
listMenu
().
then
(
response
=>
{
// 处理菜单数据,转换为前端需要的格式
this
.
processMenuData
(
response
.
data
);
this
.
loading
=
false
;
}).
catch
(
error
=>
{
console
.
error
(
'加载菜单失败:'
,
error
);
this
.
loading
=
false
;
// 如果接口调用失败,使用默认菜单
this
.
useDefaultMenus
();
});
},
// 处理菜单数据
processMenuData
(
menuList
)
{
console
.
log
(
'processMenuData--111'
,
menuList
);
// 检查menuList是否存在且是数组
if
(
!
Array
.
isArray
(
menuList
))
{
this
.
useDefaultMenus
();
return
;
}
// 转换为菜单树结构
this
.
menuTree
=
this
.
buildMenuTree
(
menuList
);
// 提取所有菜单项
const
allMenuItems
=
[];
const
extractMenuItems
=
(
menuNode
,
parentLabel
=
''
)
=>
{
if
(
!
menuNode
)
return
;
const
label
=
parentLabel
?
`
${
parentLabel
}
-
${
menuNode
.
menuName
}
`
:
menuNode
.
menuName
;
const
icon
=
this
.
getMenuIcon
(
menuNode
.
menuName
);
// 只有叶子节点且路径有效才作为可点击的菜单项
if
(
menuNode
.
path
&&
menuNode
.
path
!==
'#'
&&
menuNode
.
path
.
trim
()
!==
''
&&
typeof
menuNode
.
path
===
'string'
&&
menuNode
.
menuType
!==
'F'
&&
(
!
menuNode
.
children
||
menuNode
.
children
.
length
===
0
))
{
// 确保路径以斜杠开头
const
normalizedPath
=
"/"
+
menuNode
.
parentPath
+
(
menuNode
.
path
.
startsWith
(
'/'
)
?
menuNode
.
path
:
`/
${
menuNode
.
path
}
`
);
allMenuItems
.
push
({
id
:
menuNode
.
menuId
.
toString
(),
label
:
label
,
path
:
normalizedPath
,
icon
:
icon
,
parentPath
:
menuNode
.
parentPath
,
parentId
:
menuNode
.
parentId
?
menuNode
.
parentId
.
toString
()
:
null
});
}
if
(
menuNode
.
children
&&
menuNode
.
children
.
length
>
0
)
{
menuNode
.
children
.
forEach
(
childNode
=>
{
extractMenuItems
(
childNode
,
label
);
});
}
};
this
.
menuTree
.
forEach
(
menuNode
=>
{
// 递归提取所有菜单项
extractMenuItems
(
menuNode
);
});
this
.
allMenus
=
allMenuItems
;
// 如果没有从接口获取到菜单,使用默认菜单
if
(
this
.
allMenus
.
length
===
0
)
{
this
.
useDefaultMenus
();
}
},
// 构建菜单树
buildMenuTree
(
menuList
)
{
console
.
log
(
'buildMenuTree--2222222222222222222'
,
menuList
);
// 创建菜单映射
const
menuMap
=
{};
const
rootMenus
=
[];
// 检查menuList是否存在且是数组
if
(
!
Array
.
isArray
(
menuList
))
{
return
rootMenus
;
}
// 首先将所有菜单放入map中,排除menuType为F的菜单
menuList
.
forEach
(
menu
=>
{
if
(
menu
&&
menu
.
menuType
!==
'F'
)
{
menuMap
[
menu
.
menuId
]
=
{
...
menu
,
children
:
[]
};
}
});
// 构建树结构,排除menuType为F的菜单
menuList
.
forEach
(
menu
=>
{
if
(
menu
&&
menu
.
menuType
!==
'F'
)
{
if
(
menu
.
parentId
===
0
)
{
// 根菜单
rootMenus
.
push
(
menuMap
[
menu
.
menuId
]);
}
else
{
// 子菜单
if
(
menuMap
[
menu
.
parentId
])
{
menuMap
[
menu
.
parentId
].
children
.
push
(
{
...
menuMap
[
menu
.
menuId
],
parentPath
:
menuMap
[
menu
.
parentId
].
path
});
}
}
}
});
return
rootMenus
;
},
// 获取菜单图标
getMenuIcon
(
menuName
)
{
const
menuIcons
=
{
'基础建设'
:
'📁'
,
'数据源'
:
'📁'
,
'数据集成'
:
'🔧'
,
'任务管理'
:
'🔧'
,
'数据开发'
:
'⚙️'
,
'任务列表'
:
'⚙️'
,
'数据API'
:
'🔗'
,
'数据api'
:
'🔗'
,
'数据服务'
:
'🔗'
,
'数据质量'
:
'📊'
,
'规则配置'
:
'📊'
};
return
menuIcons
[
menuName
]
||
'📄'
;
},
// 使用默认菜单
useDefaultMenus
()
{
console
.
log
(
'useDefaultMenus:333333333333333333'
);
this
.
allMenus
=
this
.
defaultMenuConfig
;
// 构建默认菜单树
this
.
menuTree
=
[];
},
// 打开配置对话框
openConfigDialog
()
{
const
savedMenuConfig
=
localStorage
.
getItem
(
'quickMenuConfig'
)
?
JSON
.
parse
(
localStorage
.
getItem
(
'quickMenuConfig'
))
:
this
.
defaultMenuConfig
;
console
.
log
(
'openConfigDialog--2222222222222222222'
,
savedMenuConfig
);
// 提取已选中的菜单ID
this
.
configForm
.
selectedMenus
=
savedMenuConfig
.
map
(
menu
=>
menu
.
id
);
console
.
log
(
"选中了菜单ID:"
,
this
.
configForm
.
selectedMenus
);
this
.
configDialogVisible
=
true
;
},
// 保存菜单配置
saveMenuConfig
()
{
// 检查configForm.selectedMenus是否存在且是数组
if
(
!
Array
.
isArray
(
this
.
configForm
.
selectedMenus
))
{
this
.
configForm
.
selectedMenus
=
[];
}
console
.
log
(
'saveMenuConfig--2222222222222222222'
,);
// 随机图标列表
const
randomIcons
=
[
'📁'
,
'🔧'
,
'⚙️'
,
'🔗'
,
'📊'
,
'📄'
,
'📋'
,
'📅'
,
'📈'
,
'📉'
,
'📌'
,
'📍'
,
'🔍'
,
'🔎'
,
'🔏'
,
'🔐'
,
'🔒'
,
'🔓'
,
'🔑'
,
'🔨'
,
'🔩'
,
'🔧'
,
'🔦'
,
'🔅'
,
'🔆'
,
'🔇'
,
'🔈'
,
'🔉'
,
'🔊'
,
'🔔'
,
'🔕'
,
'🔖'
,
'🔗'
,
'🔘'
,
'🔙'
,
'🔚'
,
'🔛'
,
'🔝'
,
'🔞'
,
'🔟'
,
'🔢'
,
'🔣'
,
'🔤'
,
'🔡'
,
'🔠'
,
'🔰'
,
'🔱'
,
'🔲'
,
'🔳'
,
'🔴'
,
'🔵'
,
'🔷'
,
'🔶'
,
'🔸'
,
'🔹'
,
'🔺'
,
'🔻'
,
'🔼'
,
'🔽'
,
'🕐'
,
'🕑'
,
'🕒'
,
'🕓'
,
'🕔'
,
'🕕'
,
'🕖'
,
'🕗'
,
'🕘'
,
'🕙'
,
'🕚'
,
'🕛'
,
'🕜'
,
'🕝'
,
'🕞'
,
'🕟'
,
'🕠'
,
'🕡'
,
'🕢'
,
'🕣'
,
'🕤'
,
'🕥'
,
'🕦'
,
'🕧'
,
'🌑'
,
'🌒'
,
'🌓'
,
'🌔'
,
'🌕'
,
'🌖'
,
'🌗'
,
'🌘'
,
'🌙'
,
'🌚'
,
'🌛'
,
'🌜'
,
'🌞'
,
'🌟'
,
'⭐'
,
'🌠'
,
'🌡️'
,
'🌤️'
,
'🌥️'
,
'🌦️'
,
'🌧️'
,
'🌨️'
,
'🌩️'
,
'🌪️'
,
'🌫️'
,
'🌬️'
,
'🌭'
,
'🍔'
,
'🍟'
,
'🍕'
,
'🍖'
,
'🍗'
,
'🍘'
,
'🍙'
,
'🍚'
,
'🍛'
,
'🍜'
,
'🍝'
,
'🍞'
,
'🍟'
,
'🍡'
,
'🍢'
,
'🍣'
,
'🍤'
,
'🍥'
,
'🍦'
,
'🍧'
,
'🍨'
,
'🍩'
,
'🍪'
,
'🍫'
,
'🍬'
,
'🍭'
,
'🍮'
,
'🍯'
,
'🍰'
,
'🍱'
,
'🍲'
,
'🍳'
,
'🍴'
,
'🍵'
,
'🍶'
,
'🍷'
,
'🍸'
,
'🍹'
,
'🍺'
,
'🍻'
,
'🍼'
,
'🍽️'
,
'🍾'
,
'🍿'
,
'🎀'
,
'🎁'
,
'🎂'
,
'🎃'
,
'🎄'
,
'🎆'
,
'🎇'
,
'🎈'
,
'🎉'
,
'🎊'
,
'🎋'
,
'🎍'
,
'🎎'
,
'🎏'
,
'🎐'
,
'🎑'
,
'🎒'
,
'🎓'
,
'🎠'
,
'🎡'
,
'🎢'
,
'🎣'
,
'🎤'
,
'🎥'
,
'🎦'
,
'🎧'
,
'🎨'
,
'🎩'
,
'🎪'
,
'🎫'
,
'🎬'
,
'🎭'
,
'🎮'
,
'🎯'
,
'🎰'
,
'🎱'
,
'🎲'
,
'🎳'
,
'🎴'
,
'🎵'
,
'🎶'
,
'🎷'
,
'🎸'
,
'🎹'
,
'🎺'
,
'🎻'
,
'🎼'
,
'🎽'
,
'🎾'
,
'🎿'
,
'🏀'
,
'🏁'
,
'🏂'
,
'🏃'
,
'🏄'
,
'🏅'
,
'🏆'
,
'🏇'
,
'🏈'
,
'🏉'
,
'🏊'
,
'🏋️'
,
'🏌️'
,
'🏍️'
,
'🏎️'
,
'🏏'
,
'🏐'
,
'🏑'
,
'🏒'
,
'🏓'
,
'🏔️'
,
'🏕️'
,
'🏖️'
,
'🏗️'
,
'🏘️'
,
'🏙️'
,
'🏚️'
,
'🏛️'
,
'🏜️'
,
'🏝️'
,
'🏞️'
,
'🏟️'
,
'🏠'
,
'🏡'
,
'🏢'
,
'🏣'
,
'🏤'
,
'🏥'
,
'🏦'
,
'🏨'
,
'🏩'
,
'🏪'
,
'🏫'
,
'🏬'
,
'🏭'
,
'🏯'
,
'🏰'
,
'🏳️'
,
'🏴'
,
'🏳️🌈'
,
'🏳️⚧️'
,
'🚀'
,
'🚁'
,
'🚂'
,
'🚃'
,
'🚄'
,
'🚅'
,
'🚆'
,
'🚇'
,
'🚈'
,
'🚉'
,
'🚊'
,
'🚋'
,
'🚌'
,
'🚍'
,
'🚎'
,
'🚐'
,
'🚑'
,
'🚒'
,
'🚓'
,
'🚔'
,
'🚕'
,
'🚖'
,
'🚗'
,
'🚘'
,
'🚙'
,
'🚚'
,
'🚛'
,
'🚜'
,
'🚲'
,
'🛴'
,
'🛵'
,
'🚏'
,
'🛣️'
,
'🛤️'
,
'🛢️'
,
'🛞'
,
'🛟'
,
'🚨'
,
'🚥'
,
'🚦'
,
'🚧'
,
'🛑'
,
'🚪'
,
'🚫'
,
'🚬'
,
'🚭'
,
'🚮'
,
'🚯'
,
'🚰'
,
'🚱'
,
'🚲'
,
'🚳'
,
'🚴'
,
'🚵'
,
'🚶'
,
'🚷'
,
'🚸'
,
'🚹'
,
'🚺'
,
'🚻'
,
'🚼'
,
'🚾'
,
'🛂'
,
'🛃'
,
'🛄'
,
'🛅'
,
'🛆'
,
'🛇'
,
'🛈'
,
'🛉'
,
'🛊'
,
'🛋️'
,
'🛌'
,
'🛍️'
,
'🛎️'
,
'🛏️'
,
'🛐'
,
'🛑'
,
'🛒'
,
'🛓'
,
'🛔'
,
'🛕'
,
'🛖'
,
'🛗'
,
''
,
''
,
''
,
'️'
,
'🛜'
,
'🛝'
,
'🛞'
,
'🛟'
,
'🛠️'
,
'🛡️'
,
'🛢️'
,
'🛣️'
,
'🛤️'
,
'🛥️'
,
'🛦️'
,
'🛧️'
,
'🛨️'
,
'🛩️'
,
'🛪️'
,
'🛫️'
,
'🛬️'
,
'️'
,
'️'
,
'️'
,
'🛰️'
,
'🛱️'
,
'🛲️'
,
'🛳️'
,
'🛴️'
,
'🛵️'
,
'🛶️'
,
'🛷️'
,
'🛸️'
,
'🛹️'
,
'🛺️'
,
'🛻️'
,
'🛼️'
,
'️'
,
'️'
,
'️'
,
'🦠'
,
'🦸'
,
'🦹'
,
'🦺'
,
'🦻'
,
'🦼'
,
'🦽'
,
'🧐'
,
'🤓'
,
'😎'
,
'🤩'
,
'🤔'
,
'🤐'
,
'🤨'
,
'😐'
,
'😑'
,
'😶'
,
'🙄'
,
'😏'
,
'😒'
,
'🙃'
,
'😬'
,
'😴'
,
'😌'
,
'😛'
,
'😜'
,
'😝'
,
'🤗'
,
'🤭'
,
'🤫'
,
'🤔'
,
'🤐'
,
'🤨'
,
'😐'
,
'😑'
,
'😶'
,
'🙄'
,
'😏'
,
'😒'
,
'🙃'
,
'😬'
,
'😴'
,
'😌'
,
'😛'
,
'😜'
,
'😝'
,
'🤗'
,
'🤭'
,
'🤫'
,
'🤔'
,
'🤐'
,
'🤨'
,
'😐'
,
'😑'
,
'😶'
,
'🙄'
,
'😏'
,
'😒'
,
'🙃'
,
'😬'
,
'😴'
,
'😌'
,
'😛'
,
'😜'
,
'😝'
,
'🤗'
,
'🤭'
,
'🤫'
];
// 从菜单树中获取所有菜单项
const
getAllMenuItems
=
(
menuNodes
)
=>
{
const
items
=
[];
// // 有效的快捷菜单路由列表,从路由配置中提取
menuNodes
.
forEach
(
menuNode
=>
{
// 只有叶子节点且路径有效才作为可点击的菜单项
if
(
menuNode
.
path
&&
menuNode
.
path
!==
'#'
&&
menuNode
.
path
.
trim
()
!==
''
&&
typeof
menuNode
.
path
===
'string'
&&
menuNode
.
menuType
!==
'F'
&&
(
!
menuNode
.
children
||
menuNode
.
children
.
length
===
0
))
{
// 确保路径以斜杠开头
// const normalizedPath = node.path.startsWith('/') ? node.path : `/${node.path}`;
const
normalizedPath
=
"/"
+
menuNode
.
parentPath
+
(
menuNode
.
path
.
startsWith
(
'/'
)
?
menuNode
.
path
:
`/
${
menuNode
.
path
}
`
);
// 检查路径是否在有效的快捷菜单路由列表中
items
.
push
({
id
:
menuNode
.
menuId
.
toString
(),
label
:
menuNode
.
menuName
,
path
:
normalizedPath
,
icon
:
this
.
getMenuIcon
(
menuNode
.
menuName
)
});
}
if
(
menuNode
.
children
&&
menuNode
.
children
.
length
>
0
)
{
items
.
push
(...
getAllMenuItems
(
menuNode
.
children
));
}
});
return
items
;
};
// 构建完整的菜单列表(包括从菜单树中获取的),并去重
const
menuMap
=
new
Map
();
// 先添加this.allMenus中的菜单项
this
.
allMenus
.
forEach
(
menu
=>
{
if
(
menu
&&
menu
.
id
)
{
menuMap
.
set
(
menu
.
id
,
menu
);
}
});
// 再添加从菜单树中获取的菜单项,相同id的会覆盖,避免重复
const
treeMenus
=
getAllMenuItems
(
this
.
menuTree
);
treeMenus
.
forEach
(
menu
=>
{
if
(
menu
&&
menu
.
id
)
{
menuMap
.
set
(
menu
.
id
,
menu
);
}
});
// 转换为数组,得到去重后的菜单列表
const
completeMenuList
=
Array
.
from
(
menuMap
.
values
());
// 根据选中的菜单ID获取菜单详情,并为每个菜单分配随机图标
// 覆盖已选取的 菜单图标
const
selectedMenuConfig
=
completeMenuList
.
filter
(
menu
=>
menu
&&
this
.
configForm
.
selectedMenus
.
includes
(
menu
.
id
)
&&
menu
.
path
&&
typeof
menu
.
path
===
'string'
&&
menu
.
path
.
trim
()
!==
''
&&
menu
.
path
!==
'#'
).
map
(
menu
=>
{
// 为每个菜单生成随机图标
const
randomIcon
=
randomIcons
[
Math
.
floor
(
Math
.
random
()
*
randomIcons
.
length
)];
return
{
...
menu
,
icon
:
randomIcon
};
});
// 如果没有选择菜单,使用默认配置
const
finalMenuConfig
=
selectedMenuConfig
.
length
>
0
?
selectedMenuConfig
:
this
.
defaultMenuConfig
;
localStorage
.
setItem
(
'quickMenuConfig'
,
JSON
.
stringify
(
finalMenuConfig
));
// 更新时间戳,触发displayMenus计算属性重新计算
this
.
menuUpdateTime
=
Date
.
now
();
this
.
configDialogVisible
=
false
;
this
.
$message
.
success
(
'配置保存成功!'
);
},
// 切换菜单展开/折叠状态
toggleMenu
(
menuId
)
{
this
.
$set
(
this
.
expandedMenus
,
menuId
,
!
this
.
expandedMenus
[
menuId
]);
},
// 取消配置
cancelMenuConfig
()
{
// 重置选中的菜单
this
.
configForm
.
selectedMenus
=
[];
// 关闭配置抽屉
this
.
configDialogVisible
=
false
;
this
.
$message
.
info
(
'已取消配置'
);
},
}
}
</
script
>
...
...
@@ -32,5 +434,86 @@ export default {
.dashboard-description
{
font-size
:
16px
;
color
:
#606266
;
margin-bottom
:
30px
;
}
.quick-menu
{
width
:
100%
;
max-width
:
800px
;
margin-top
:
20px
;
}
.menu-header
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
margin-bottom
:
15px
;
}
.menu-header
h3
{
font-size
:
18px
;
font-weight
:
600
;
color
:
#303133
;
margin
:
0
;
}
.menu-grid
{
display
:
grid
;
grid-template-columns
:
repeat
(
auto-fit
,
minmax
(
200px
,
1
fr
));
gap
:
15px
;
}
.menu-item
{
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
padding
:
20px
;
background-color
:
#f5f7fa
;
border-radius
:
8px
;
text-decoration
:
none
;
color
:
#303133
;
transition
:
all
0.3s
ease
;
border
:
1px
solid
#ebeef5
;
}
.menu-item
:hover
{
background-color
:
#ecf5ff
;
border-color
:
#d9ecff
;
transform
:
translateY
(
-2px
);
box-shadow
:
0
2px
12px
0
rgba
(
0
,
0
,
0
,
0.1
);
}
.menu-icon
{
font-size
:
32px
;
margin-bottom
:
10px
;
}
.menu-label
{
font-size
:
14px
;
font-weight
:
500
;
text-align
:
center
;
}
/* 菜单级别样式 */
.menu-level-1
{
font-size
:
20px
!important
;
font-weight
:
700
!important
;
color
:
#FF7A00
!important
;
/* 橙色 */
cursor
:
pointer
!important
;
margin-left
:
-10px
!important
;
}
.menu-level-2
{
font-size
:
16px
!important
;
font-weight
:
600
!important
;
color
:
#9D50BB
!important
;
/* 浅紫色 */
cursor
:
pointer
!important
;
}
.menu-level-3
span
.el-checkbox__label
{
font-size
:
14px
!important
;
font-weight
:
400
!important
;
color
:
#606266
!important
;
}
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论