style: 全局菜单搜索仅过滤菜单名称
This commit is contained in:
@@ -2,11 +2,7 @@
|
|||||||
<!-- 搜索按钮 -->
|
<!-- 搜索按钮 -->
|
||||||
<a-tooltip placement="bottom">
|
<a-tooltip placement="bottom">
|
||||||
<template #title>{{ t('common.search') }}</template>
|
<template #title>{{ t('common.search') }}</template>
|
||||||
<a-button
|
<a-button type="text" style="color: inherit" @click="fnClickSearch">
|
||||||
type="text"
|
|
||||||
style="color: inherit"
|
|
||||||
@click="fnClickSearch"
|
|
||||||
>
|
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<SearchOutlined />
|
<SearchOutlined />
|
||||||
</template>
|
</template>
|
||||||
@@ -38,11 +34,13 @@
|
|||||||
<SearchOutlined style="color: #bfbfbf" />
|
<SearchOutlined style="color: #bfbfbf" />
|
||||||
</template>
|
</template>
|
||||||
</a-input>
|
</a-input>
|
||||||
|
|
||||||
<div class="search-results">
|
<div class="search-results">
|
||||||
<div v-if="filteredMenus.length === 0" class="no-results">
|
<div v-if="filteredMenus.length === 0" class="no-results">
|
||||||
<a-empty
|
<a-empty
|
||||||
:description="searchKeyword ? t('common.noData') : t('common.searchTip')"
|
:description="
|
||||||
|
searchKeyword ? t('common.noData') : t('common.searchTip')
|
||||||
|
"
|
||||||
:image="false"
|
:image="false"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,15 +53,15 @@
|
|||||||
>
|
>
|
||||||
<div class="menu-icon">
|
<div class="menu-icon">
|
||||||
<!-- 处理自定义图标字体 -->
|
<!-- 处理自定义图标字体 -->
|
||||||
<IconFont
|
<IconFont
|
||||||
v-if="menu.icon && menu.icon.startsWith('icon-')"
|
v-if="menu.icon && menu.icon.startsWith('icon-')"
|
||||||
:type="menu.icon"
|
:type="menu.icon"
|
||||||
class="icon"
|
class="icon"
|
||||||
/>
|
/>
|
||||||
<!-- 处理Ant Design图标组件 -->
|
<!-- 处理Ant Design图标组件 -->
|
||||||
<component
|
<component
|
||||||
:is="menu.icon"
|
:is="menu.icon"
|
||||||
v-else-if="menu.icon && !menu.icon.startsWith('icon-')"
|
v-else-if="menu.icon && !menu.icon.startsWith('icon-')"
|
||||||
class="icon"
|
class="icon"
|
||||||
/>
|
/>
|
||||||
<!-- 默认图标 -->
|
<!-- 默认图标 -->
|
||||||
@@ -83,10 +81,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import { getMenuData, clearMenuItem } from 'antdv-pro-layout';
|
||||||
getMenuData,
|
|
||||||
clearMenuItem
|
|
||||||
} from 'antdv-pro-layout';
|
|
||||||
import { ProModal } from 'antdv-pro-modal';
|
import { ProModal } from 'antdv-pro-modal';
|
||||||
import IconFont from '@/components/IconFont/index.vue';
|
import IconFont from '@/components/IconFont/index.vue';
|
||||||
import { ref, computed, nextTick } from 'vue';
|
import { ref, computed, nextTick } from 'vue';
|
||||||
@@ -127,7 +122,7 @@ const searchableMenus = computed(() => {
|
|||||||
} else {
|
} else {
|
||||||
rootRoute.children = children;
|
rootRoute.children = children;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据用户角色过滤
|
// 根据用户角色过滤
|
||||||
if (!userStore.roles.includes('tenant')) {
|
if (!userStore.roles.includes('tenant')) {
|
||||||
rootRoute.children = rootRoute.children.filter(
|
rootRoute.children = rootRoute.children.filter(
|
||||||
@@ -164,26 +159,30 @@ const searchableMenus = computed(() => {
|
|||||||
try {
|
try {
|
||||||
const title = t(route.meta.title);
|
const title = t(route.meta.title);
|
||||||
// 避免重复添加已存在的路由
|
// 避免重复添加已存在的路由
|
||||||
const exists = menus.find(m => m.routeName === route.name || m.path === fullPath);
|
const exists = menus.find(
|
||||||
|
m => m.routeName === route.name || m.path === fullPath
|
||||||
|
);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
menus.push({
|
menus.push({
|
||||||
title: title,
|
title: title,
|
||||||
path: fullPath,
|
path: fullPath,
|
||||||
icon: route.meta.icon,
|
icon: route.meta.icon,
|
||||||
key: route.name || fullPath,
|
key: route.name || fullPath,
|
||||||
routeName: route.name
|
routeName: route.name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 如果翻译失败,使用原始标题
|
// 如果翻译失败,使用原始标题
|
||||||
const exists = menus.find(m => m.routeName === route.name || m.path === fullPath);
|
const exists = menus.find(
|
||||||
|
m => m.routeName === route.name || m.path === fullPath
|
||||||
|
);
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
menus.push({
|
menus.push({
|
||||||
title: route.meta.title,
|
title: route.meta.title,
|
||||||
path: fullPath,
|
path: fullPath,
|
||||||
icon: route.meta.icon,
|
icon: route.meta.icon,
|
||||||
key: route.name || fullPath,
|
key: route.name || fullPath,
|
||||||
routeName: route.name
|
routeName: route.name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,7 +197,7 @@ const searchableMenus = computed(() => {
|
|||||||
|
|
||||||
// 使用和菜单面板相同的数据源
|
// 使用和菜单面板相同的数据源
|
||||||
const menuRoutes = getMenuDataForSearch();
|
const menuRoutes = getMenuDataForSearch();
|
||||||
|
|
||||||
if (menuRoutes && menuRoutes.length > 0) {
|
if (menuRoutes && menuRoutes.length > 0) {
|
||||||
getRouteItems(menuRoutes);
|
getRouteItems(menuRoutes);
|
||||||
}
|
}
|
||||||
@@ -211,18 +210,22 @@ const filteredMenus = computed(() => {
|
|||||||
if (!searchKeyword.value.trim()) {
|
if (!searchKeyword.value.trim()) {
|
||||||
return searchableMenus.value.slice(0, 10); // 默认显示前10个
|
return searchableMenus.value.slice(0, 10); // 默认显示前10个
|
||||||
}
|
}
|
||||||
|
|
||||||
return searchableMenus.value.filter(menu =>
|
// return searchableMenus.value.filter(menu =>
|
||||||
menu.title.toLowerCase().includes(searchKeyword.value.toLowerCase()) ||
|
// menu.title.toLowerCase().includes(searchKeyword.value.toLowerCase()) ||
|
||||||
menu.path.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
// menu.path.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
||||||
).slice(0, 10);
|
// ).slice(0, 10);
|
||||||
|
const value = searchKeyword.value.toLowerCase();
|
||||||
|
return searchableMenus.value
|
||||||
|
.filter(menu => menu.title.toLowerCase().includes(value))
|
||||||
|
.slice(0, 10);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**打开搜索弹窗 */
|
/**打开搜索弹窗 */
|
||||||
function fnClickSearch() {
|
function fnClickSearch() {
|
||||||
searchModalOpen.value = true;
|
searchModalOpen.value = true;
|
||||||
searchKeyword.value = '';
|
searchKeyword.value = '';
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
searchInputRef.value?.focus();
|
searchInputRef.value?.focus();
|
||||||
});
|
});
|
||||||
@@ -268,12 +271,12 @@ function fnHandleKeydown(e: KeyboardEvent) {
|
|||||||
.search-results {
|
.search-results {
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
.no-results {
|
.no-results {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px 0;
|
padding: 40px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-list {
|
.menu-list {
|
||||||
.menu-item {
|
.menu-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -283,15 +286,15 @@ function fnHandleKeydown(e: KeyboardEvent) {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
|
|
||||||
.menu-action {
|
.menu-action {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-icon {
|
.menu-icon {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -301,17 +304,17 @@ function fnHandleKeydown(e: KeyboardEvent) {
|
|||||||
height: 32px;
|
height: 32px;
|
||||||
background-color: #f0f2f5;
|
background-color: #f0f2f5;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-info {
|
.menu-info {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
.menu-title {
|
.menu-title {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@@ -321,7 +324,7 @@ function fnHandleKeydown(e: KeyboardEvent) {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-path {
|
.menu-path {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #8c8c8c;
|
color: #8c8c8c;
|
||||||
@@ -330,7 +333,7 @@ function fnHandleKeydown(e: KeyboardEvent) {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-action {
|
.menu-action {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.2s ease;
|
transition: opacity 0.2s ease;
|
||||||
@@ -343,7 +346,7 @@ function fnHandleKeydown(e: KeyboardEvent) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 暗黑主题支持
|
// 暗黑主题支持
|
||||||
[data-theme="dark"] {
|
[data-theme='dark'] {
|
||||||
.search-modal-content {
|
.search-modal-content {
|
||||||
.search-results {
|
.search-results {
|
||||||
.menu-list {
|
.menu-list {
|
||||||
@@ -351,20 +354,20 @@ function fnHandleKeydown(e: KeyboardEvent) {
|
|||||||
&:hover {
|
&:hover {
|
||||||
background-color: #303030;
|
background-color: #303030;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-icon {
|
.menu-icon {
|
||||||
background-color: #262626;
|
background-color: #262626;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
color: #bfbfbf;
|
color: #bfbfbf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-info {
|
.menu-info {
|
||||||
.menu-title {
|
.menu-title {
|
||||||
color: #f0f0f0;
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-path {
|
.menu-path {
|
||||||
color: #8c8c8c;
|
color: #8c8c8c;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user