| | |
| | | <span class="label">LIMS实验室管理系统</span> |
| | | </div> |
| | | <div class="right-menu"> |
| | | <div class="menu-search"> |
| | | <el-select |
| | | v-model="selectedMenu" |
| | | placeholder="搜索菜单" |
| | | filterable |
| | | clearable |
| | | :fit-input-width="false" |
| | | :filter-method="filterMenus" |
| | | @change="handleMenuSelect" |
| | | @clear="resetMenuFilter" |
| | | > |
| | | <template #prefix> |
| | | <lims-icon name="el-icon-search" /> |
| | | </template> |
| | | <el-option |
| | | v-for="item in filteredMenus" |
| | | :key="item.path" |
| | | :label="item.breadcrumb" |
| | | :value="item.path" |
| | | /> |
| | | </el-select> |
| | | </div> |
| | | <div class="avatar-wrapper"> |
| | | <el-avatar shape="square" :size="30">{{ avatarText }}</el-avatar> |
| | | <span class="userName">{{ userStore.nickName }}</span> |
| | |
| | | import Hamburger from '@/components/Hamburger' |
| | | import useAppStore from '@/store/modules/app' |
| | | import useUserStore from '@/store/modules/user' |
| | | import usePermissionStore from '@/store/modules/permission' |
| | | import { getNormalPath } from '@/utils/ruoyi' |
| | | |
| | | const appStore = useAppStore() |
| | | const userStore = useUserStore() |
| | | const permissionStore = usePermissionStore() |
| | | const router = useRouter() |
| | | |
| | | const avatarText = computed(() => (userStore.nickName || '').substring(0, 1)) |
| | | |
| | | const selectedMenu = ref(undefined) |
| | | const filteredMenus = ref([]) |
| | | |
| | | // 侧边栏菜单树拍平成可搜索列表(标题 + 完整路径面包屑) |
| | | const menuList = computed(() => { |
| | | const list = [] |
| | | const walk = (routes, basePath, parents) => { |
| | | ;(routes || []).forEach(route => { |
| | | if (!route || route.hidden || typeof route.path !== 'string') return |
| | | const fullPath = getNormalPath(`${basePath}/${route.path}`) |
| | | const title = route.meta && route.meta.title |
| | | const children = Array.isArray(route.children) ? route.children : [] |
| | | if (children.length) { |
| | | walk(children, fullPath, title ? parents.concat(title) : parents) |
| | | } else if (title && fullPath) { |
| | | list.push({ title, path: fullPath, breadcrumb: parents.concat(title).join(' / ') }) |
| | | } |
| | | }) |
| | | } |
| | | walk(permissionStore.sidebarRouters, '', []) |
| | | return list |
| | | }) |
| | | |
| | | function filterMenus(query) { |
| | | const q = (query || '').trim().toLowerCase() |
| | | filteredMenus.value = q |
| | | ? menuList.value.filter(item => |
| | | item.title.toLowerCase().includes(q) || item.breadcrumb.toLowerCase().includes(q) |
| | | ) |
| | | : menuList.value |
| | | } |
| | | |
| | | function resetMenuFilter() { |
| | | filteredMenus.value = menuList.value |
| | | } |
| | | |
| | | function handleMenuSelect(path) { |
| | | if (path) { |
| | | router.push(path).catch(() => {}) |
| | | } |
| | | selectedMenu.value = undefined |
| | | resetMenuFilter() |
| | | } |
| | | |
| | | watch(menuList, resetMenuFilter, { immediate: true }) |
| | | |
| | | function toggleSideBar() { |
| | | appStore.toggleSideBar() |
| | |
| | | outline: none; |
| | | } |
| | | |
| | | .menu-search { |
| | | margin-right: 20px; |
| | | |
| | | :deep(.el-select) { |
| | | width: 210px; |
| | | } |
| | | |
| | | :deep(.el-select__wrapper) { |
| | | border-radius: 16px; |
| | | } |
| | | } |
| | | |
| | | .avatar-wrapper { |
| | | display: flex; |
| | | align-items: center; |