This commit is contained in:
zlwu committed 2026-07-05 10:07:24 +08:00
1 parent 33c038b8d9
commit 54b27a3f0e
253 files changed
+30060 -14298

No files matched your search

@@ -384,12 +384,6 @@
* 监听窗口尺寸变化,自动处理移动端菜单
*/
watch(width, (newWidth) => {
if (isPortalMenu.value) {
settingStore.setMenuOpen(true)
showMobileModal.value = false
return
}
if (newWidth < MOBILE_BREAKPOINT) {
settingStore.setMenuOpen(false)
if (!menuOpen.value) {
@@ -1,26 +1,34 @@
<!-- 一体化门户顶栏 -->
<template>
<header class="portal-header">
<div class="portal-header-brand" @click="toHome">
<ArtLogo class="portal-header-logo" src="/logo-sx.svg" :size="38" />
<p class="portal-header-title">{{ AppConfig.systemInfo.name }}</p>
<div class="portal-header-start">
<div class="portal-header-brand" @click="toHome">
<ArtLogo class="portal-header-logo" src="/logo-sx.svg" :size="38" />
<p class="portal-header-title">{{ AppConfig.systemInfo.name }}</p>
</div>
<div class="portal-header-nav">
<ArtIconButton
icon="fold"
class="portal-header-icon-btn portal-header-fold-btn"
@click="toggleSidebar"
/>
<ArtPortalModuleSelect />
</div>
</div>
<div class="portal-header-nav">
<ArtPortalModuleSelect />
<ArtPortalSubNav class="portal-header-sub-nav" />
<div class="portal-header-center" aria-hidden="false">
<p v-if="pageTitle" class="portal-header-page-title">{{ pageTitle }}</p>
</div>
<div class="portal-header-actions">
<ArtPortalMobileMenu />
<ArtIconButton
v-if="shouldShowFullscreen"
icon="fullscreen"
:class="[
'portal-header-icon-btn',
'portal-header-icon-btn max-md:!hidden',
!isFullscreen ? 'full-screen-btn' : 'exit-full-screen-btn'
]"
class="max-md:!hidden"
@click="toggleFullScreen"
/>
<ArtUserMenu />
@@ -29,19 +37,34 @@
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useRoute, useRouter } from 'vue-router'
import { useFullscreen } from '@vueuse/core'
import AppConfig from '@/config'
import { useCommon } from '@/hooks/core/useCommon'
import { useHeaderBar } from '@/hooks/core/useHeaderBar'
import { useSettingStore } from '@/store/modules/setting'
import { formatMenuTitle } from '@/utils/router'
import ArtUserMenu from '../art-header-bar/widget/ArtUserMenu.vue'
defineOptions({ name: 'ArtPortalHeader' })
const route = useRoute()
const router = useRouter()
const { homePath } = useCommon()
const { shouldShowFullscreen } = useHeaderBar()
const { isFullscreen, toggle: toggleFullscreen } = useFullscreen()
const settingStore = useSettingStore()
const { menuOpen } = storeToRefs(settingStore)
const pageTitle = computed(() => {
const matched = route.matched
if (!matched.length) return ''
const current = matched[matched.length - 1]
const title = current.meta?.title
return title ? formatMenuTitle(String(title)) : ''
})
const toHome = (): void => {
router.push(homePath.value)
@@ -50,14 +73,20 @@
const toggleFullScreen = (): void => {
toggleFullscreen()
}
const toggleSidebar = (): void => {
settingStore.setMenuOpen(!menuOpen.value)
}
</script>
<style lang="scss" scoped>
.portal-header {
position: relative;
box-sizing: border-box;
display: flex;
gap: 12px;
align-items: center;
justify-content: space-between;
width: 100%;
height: 56px;
padding: 0 var(--mint-content-padding, 24px);
@@ -66,6 +95,15 @@
border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.portal-header-start {
display: flex;
flex-shrink: 0;
gap: 12px;
align-items: center;
min-width: 0;
z-index: 1;
}
.portal-header-brand {
display: flex;
flex-shrink: 0;
@@ -93,15 +131,33 @@
.portal-header-nav {
display: flex;
flex: 1;
gap: 12px;
align-items: center;
min-width: 0;
}
.portal-header-sub-nav {
flex: 1;
min-width: 0;
.portal-header-center {
position: absolute;
left: 50%;
z-index: 0;
display: flex;
align-items: center;
justify-content: center;
max-width: min(520px, calc(100% - 420px));
pointer-events: none;
transform: translateX(-50%);
}
.portal-header-page-title {
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
font-size: 16px;
font-weight: 600;
line-height: 1.35;
color: #fff;
text-align: center;
white-space: nowrap;
}
.portal-header-actions {
@@ -109,11 +165,11 @@
flex-shrink: 0;
gap: 8px;
align-items: center;
z-index: 1;
}
:deep(.portal-module-select-trigger) {
background: rgba(255, 255, 255, 0.12);
border-color: rgba(255, 255, 255, 0.28);
background: transparent;
.portal-module-select-trigger__icon,
.portal-module-select-trigger__label,
@@ -122,58 +178,7 @@
}
&:hover:not(.is-disabled) {
background: rgba(255, 255, 255, 0.18);
border-color: rgba(255, 255, 255, 0.45);
}
}
:deep(.portal-sub-nav-card__icon),
:deep(.portal-sub-nav-card__label) {
color: rgba(255, 255, 255, 0.88);
}
:deep(.portal-sub-nav-menu > .el-sub-menu .el-sub-menu__icon-arrow) {
color: rgba(255, 255, 255, 0.88);
}
:deep(.portal-sub-nav-menu > .el-sub-menu.el-sub-menu__hide-arrow .el-sub-menu__title) {
color: #fff !important;
}
:deep(.portal-sub-nav-menu > .el-sub-menu.el-sub-menu__hide-arrow .el-sub-menu__icon-more),
:deep(.portal-sub-nav-menu > .el-sub-menu.el-sub-menu__hide-arrow .el-icon) {
color: #fff !important;
}
:deep(.portal-sub-nav-menu > .el-sub-menu.el-sub-menu__hide-arrow:hover .el-sub-menu__title) {
background: rgba(255, 255, 255, 0.14) !important;
border-radius: 8px;
}
:deep(.portal-sub-nav-menu > .el-menu-item:hover .portal-sub-nav-card),
:deep(.portal-sub-nav-menu > .el-sub-menu:hover .portal-sub-nav-card) {
background: rgba(255, 255, 255, 0.14);
}
:deep(.portal-sub-nav-menu > .el-menu-item.is-active .portal-sub-nav-card),
:deep(.portal-sub-nav-menu > .el-sub-menu.is-active .portal-sub-nav-card) {
background: #fff;
.portal-sub-nav-card__icon,
.portal-sub-nav-card__label {
color: var(--mint-primary, #1ca851);
}
}
:deep(.portal-mobile-menu-trigger) {
color: #fff;
background: rgba(255, 255, 255, 0.12);
border-color: rgba(255, 255, 255, 0.28);
&:hover {
color: #fff;
background: rgba(255, 255, 255, 0.18);
border-color: rgba(255, 255, 255, 0.45);
background: transparent;
}
}
@@ -190,8 +195,12 @@
display: none;
}
.portal-header-sub-nav {
display: none !important;
.portal-header-center {
max-width: min(240px, calc(100% - 220px));
}
.portal-header-page-title {
font-size: 15px;
}
}
</style>
@@ -119,12 +119,9 @@
height: 36px;
padding: 0 12px;
cursor: pointer;
background: var(--primary-bg, #e6f8ed);
border: 1px solid var(--mint-border, #d9e8e2);
background: transparent;
border: none;
border-radius: 8px;
transition:
background-color 0.2s ease,
border-color 0.2s ease;
&__icon {
flex-shrink: 0;
@@ -149,12 +146,13 @@
}
&:hover:not(.is-disabled) {
border-color: var(--primary, #1ca851);
background: transparent;
}
&.is-disabled {
cursor: not-allowed;
background: var(--mint-bg-page, #f8fafc);
background: transparent;
opacity: 0.72;
}
}
</style>