UI样式第一次优化

This commit is contained in:
zlwu committed 2026-06-12 20:40:31 +08:00
1 parent 7f7979679f
commit e1d6de45a3
47 files changed
+316 -201

No files matched your search

@@ -29,7 +29,7 @@
const scrollThreshold = 300
onMounted(() => {
const scrollContainer = document.getElementById('app-main')
const scrollContainer = document.getElementById('app-content-scroll')
if (scrollContainer) {
const { y } = useScroll(scrollContainer)
watch(y, (newY: number) => {
@@ -1,6 +1,6 @@
<!-- 系统logo -->
<template>
<div class="flex-cc">
<div class="art-logo flex-cc" :class="{ 'art-logo--height-fit': fit === 'height' }">
<img :style="logoStyle" src="/logo.png" alt="中科兴皖" class="block object-contain" />
</div>
</template>
@@ -9,16 +9,35 @@
defineOptions({ name: 'ArtLogo' })
interface Props {
/** logo 大小 */
/** logo 大小(square 模式为边长,height 模式为高度) */
size?: number | string
/** square=正方形裁剪区;height=按高度等比(适用于横向 logo 图) */
fit?: 'square' | 'height'
}
const props = withDefaults(defineProps<Props>(), {
size: 36
size: 36,
fit: 'square'
})
const logoStyle = computed(() => ({
width: `${props.size}px`,
height: `${props.size}px`
}))
const logoStyle = computed(() => {
const size = `${props.size}px`
if (props.fit === 'height') {
return {
height: size,
width: 'auto',
maxWidth: 'none'
}
}
return {
width: size,
height: size
}
})
</script>
<style scoped>
.art-logo--height-fit {
flex-shrink: 0;
}
</style>
@@ -1,21 +1,15 @@
<!-- 顶部栏 -->
<template>
<div
class="w-full bg-[var(--default-bg-color)]"
:class="[
tabStyle === 'tab-card' || tabStyle === 'tab-google' ? 'mb-5 max-sm:mb-3 !bg-box' : ''
]"
>
<div
class="relative box-border flex-b items-center h-15 leading-15 select-none"
:class="[
tabStyle === 'tab-card' || tabStyle === 'tab-google'
? 'border-b border-[var(--art-card-border)]'
: ''
]"
>
<div class="w-full bg-[var(--default-bg-color)]">
<div class="relative box-border flex-b items-center h-15 leading-15 select-none">
<div class="flex-c flex-1 min-w-0 leading-15" style="display: flex">
<!-- 系统信息 -->
<!-- 品牌区:Logo + 系统名称(混合菜单模式,与侧栏原 header 合并至顶栏) -->
<div v-if="isTopLeftMenu" class="header-brand" @click="toHome">
<ArtLogo :size="42" fit="height" />
<p v-if="width >= 1180" class="header-brand__title">{{ AppConfig.systemInfo.name }}</p>
</div>
<!-- 系统信息(纯顶部菜单模式) -->
<div class="flex-c c-p" @click="toHome" v-if="isTopMenu">
<ArtLogo class="pl-4.5" />
<p v-if="width >= 1400" class="my-0 mx-2 ml-2 text-lg">{{ AppConfig.systemInfo.name }}</p>
@@ -34,15 +28,6 @@
@click="visibleMenu"
/>
<!-- 刷新按钮 - 已隐藏 -->
<ArtIconButton
v-if="shouldShowRefreshButton"
icon="refresh"
class="!ml-3 refresh-btn max-sm:!hidden"
:style="{ marginLeft: !isLeftMenu ? '10px' : '0' }"
@click="reload"
/>
<!-- 快速入口 - 已隐藏 -->
<!-- <ArtFastEnter v-if="shouldShowFastEnter && width >= headerBarFastEnterMinWidth">
<ArtIconButton icon="ri:function-line" class="ml-3" />
@@ -61,15 +46,6 @@
</div>
<div class="flex-c gap-2.5 leading-none">
<!-- 全屏按钮 -->
<ArtIconButton
v-if="shouldShowFullscreen"
:icon="isFullscreen ? 'fullscreen' : 'fullscreen'"
:class="[!isFullscreen ? 'full-screen-btn' : 'exit-full-screen-btn', 'ml-3']"
class="max-md:!hidden"
@click="toggleFullScreen"
/>
<!-- 国际化按钮 - 已隐藏 -->
<!-- <ElDropdown
@command="changeLanguage"
@@ -124,9 +100,6 @@
</div>
</div>
<!-- 标签页 -->
<ArtWorkTab />
<!-- 通知组件 - 已隐藏 -->
<!-- <ArtNotification v-model:value="showNotice" ref="notice" /> -->
</div>
@@ -136,7 +109,7 @@
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import { storeToRefs } from 'pinia'
import { useFullscreen, useWindowSize } from '@vueuse/core'
import { useWindowSize } from '@vueuse/core'
import { LanguageEnum, MenuTypeEnum } from '@/enums/appEnum'
import { useSettingStore } from '@/store/modules/setting'
import { useUserStore } from '@/store/modules/user'
@@ -162,10 +135,8 @@
// 顶部栏功能配置
const {
shouldShowMenuButton,
shouldShowRefreshButton,
shouldShowFastEnter,
shouldShowBreadcrumb,
shouldShowFullscreen,
shouldShowNotification,
shouldShowChat,
shouldShowLanguage,
@@ -173,7 +144,7 @@
fastEnterMinWidth: headerBarFastEnterMinWidth
} = useHeaderBar()
const { menuOpen, menuType, isDark, tabStyle } = storeToRefs(settingStore)
const { menuOpen, menuType, isDark } = storeToRefs(settingStore)
const { language } = storeToRefs(userStore)
const { menuList } = storeToRefs(menuStore)
@@ -187,8 +158,6 @@
const isTopMenu = computed(() => menuType.value === MenuTypeEnum.TOP)
const isTopLeftMenu = computed(() => menuType.value === MenuTypeEnum.TOP_LEFT)
const { isFullscreen, toggle: toggleFullscreen } = useFullscreen()
onMounted(() => {
initLanguage()
document.addEventListener('click', bodyCloseNotice)
@@ -198,13 +167,6 @@
document.removeEventListener('click', bodyCloseNotice)
})
/**
* 切换全屏状态
*/
const toggleFullScreen = (): void => {
toggleFullscreen()
}
/**
* 切换菜单显示/隐藏状态
*/
@@ -16,25 +16,22 @@
@scroll="handleScroll"
@wheel="handleWheel"
>
<div class="box-border flex-c flex-shrink-0 flex-nowrap h-15 whitespace-nowrap">
<div class="box-border flex-c flex-shrink-0 flex-nowrap h-full whitespace-nowrap">
<template v-for="item in processedMenuList" :key="item.meta.title">
<div
v-if="!item.meta.isHide"
class="menu-item relative flex-shrink-0 h-10 px-3 text-sm flex-c c-p hover:text-theme"
class="menu-item relative flex-shrink-0 c-p"
:class="{
'menu-item-active text-theme': item.isActive
'menu-item-active': item.isActive
}"
@click="handleMenuJump(item, true)"
>
<ArtSvgIcon
:icon="item.meta.icon"
class="text-lg text-g-700 dark:text-g-800 mr-1"
:class="item.isActive && '!text-theme'"
class="menu-item__icon"
:class="item.isActive && 'is-active'"
/>
<span
class="text-md text-g-700 dark:text-g-800"
:class="item.isActive && '!text-theme'"
>
<span class="menu-item__title" :class="item.isActive && 'is-active'">
{{ item.formattedTitle }}
</span>
<div v-if="item.meta.showBadge" class="art-badge art-badge-mixed" />
@@ -255,7 +252,7 @@
}
</style>
<style scoped>
<style lang="scss" scoped>
:deep(.el-scrollbar__bar.is-horizontal) {
bottom: 5px;
display: none;
@@ -265,7 +262,58 @@
:deep(.scrollbar-wrapper) {
flex: 1;
min-width: 0;
margin: 0 50px 0 30px;
margin: 0 50px 0 8px;
}
.menu-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2px;
min-width: 64px;
height: 48px;
padding: 4px 10px;
margin: 0 2px;
border-radius: 8px;
transition:
background-color 0.2s ease,
color 0.2s ease;
&:hover {
background: var(--primary-bg, #ecfdf5);
}
}
.menu-item__icon {
display: block;
font-size: 18px;
line-height: 1;
color: var(--mint-text-muted, #64748b);
&.is-active {
color: var(--theme-color);
}
}
.menu-item__title {
max-width: 80px;
overflow: hidden;
font-size: 13px;
line-height: 1.2;
color: var(--mint-text-muted, #64748b);
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
&.is-active {
font-weight: 600;
color: var(--theme-color);
}
}
.menu-item-active {
background: var(--primary-bg, #ecfdf5);
}
.menu-item-active::after {
@@ -273,11 +321,12 @@
right: 0;
bottom: 0;
left: 0;
width: 40px;
width: 28px;
height: 2px;
margin: auto;
content: '';
background-color: var(--theme-color);
border-radius: 2px;
}
@media (width <= 1440px) {
@@ -70,8 +70,9 @@
:class="`menu-left-${getMenuTheme.theme} menu-left-${!menuOpen ? 'close' : 'open'}`"
:style="{ background: getMenuTheme.background }"
>
<!-- Logo、系统名称 -->
<!-- Logo、系统名称(混合菜单模式下已移至顶栏) -->
<div
v-if="showSidebarBrand"
class="header"
@click="navigateToHome"
:style="{
@@ -182,6 +183,8 @@
// 菜单类型判断
const isTopLeftMenu = computed(() => menuType.value === MenuTypeEnum.TOP_LEFT)
/** 混合菜单模式下品牌区在顶栏,侧栏不再重复展示 */
const showSidebarBrand = computed(() => !isTopLeftMenu.value)
const showLeftMenu = computed(
() => menuType.value === MenuTypeEnum.LEFT || menuType.value === MenuTypeEnum.TOP_LEFT
)
@@ -305,9 +308,14 @@
// 双列菜单收起时的滚动条样式
const scrollbarStyle = computed(() => {
const isCollapsed = isDualMenu.value && !menuOpen.value
const hasBrandHeader = showSidebarBrand.value
return {
transform: isCollapsed ? 'translateY(-50px)' : 'translateY(0)',
height: isCollapsed ? 'calc(100% + 50px)' : 'calc(100% - 60px)',
height: isCollapsed
? 'calc(100% + 50px)'
: hasBrandHeader
? 'calc(100% - 60px)'
: '100%',
transition: 'transform 0.3s ease'
}
})
@@ -1,6 +1,6 @@
.layout-sidebar {
display: flex;
height: 100vh;
height: 100%;
user-select: none;
scrollbar-width: none;
border-right: none;
@@ -98,7 +98,7 @@
.menu-left {
position: relative;
box-sizing: border-box;
height: 100vh;
height: 100%;
overflow: hidden;
background: var(--mint-surface, #fff);
@@ -2,7 +2,7 @@
<template>
<div
v-if="showWorkTab"
class="worktab-strip box-border flex w-full items-center px-5 mb-3 select-none max-sm:px-[15px]"
class="worktab-strip box-border flex w-full items-center px-5 select-none max-sm:px-[15px]"
>
<div class="worktab-scroll-wrap min-w-0 flex-1" ref="scrollRef">
<ul
@@ -480,7 +480,7 @@
<style scoped>
.worktab-strip {
position: relative;
padding: 0 24px 12px !important;
padding: 0 24px 4px !important;
background: var(--mint-surface);
overflow: visible !important;
}
@@ -495,7 +495,7 @@
z-index: 1;
max-width: 220px;
padding: 10px 16px !important;
margin-bottom: -11px;
margin-bottom: -7px;
overflow: hidden;
font-size: 13px;
font-weight: 600;