[重大更新] 整体主题样式重写 改为卡片式布局 样式更企业化

This commit is contained in:
疯狂的狮子Li
2026-03-17 12:35:56 +08:00
parent b83755e626
commit 833dfa67fc
70 changed files with 5250 additions and 1568 deletions
+8 -19
View File
@@ -22,11 +22,9 @@ const tagsViewStore = useTagsViewStore();
// 随机动画集合
const animate = ref<string>('');
const animationEnable = ref(useSettingsStore().animationEnable);
watch(
() => useSettingsStore().animationEnable,
(val: boolean) => {
animationEnable.value = val;
if (val) {
animate.value = proxy?.animate.animateList[Math.round(Math.random() * proxy?.animate.animateList.length)] as string;
} else {
@@ -36,10 +34,6 @@ watch(
{ immediate: true }
);
onMounted(() => {
addIframe();
});
watchEffect(() => {
addIframe();
});
@@ -53,26 +47,21 @@ function addIframe() {
<style lang="scss" scoped>
.app-main {
/* 50= navbar 50 */
min-height: calc(100vh - 50px);
min-height: 100vh;
width: 100%;
position: relative;
overflow: hidden;
padding: 12px;
}
.fixed-header + .app-main {
padding-top: 50px;
.app-main.with-fixed-header {
padding-top: 76px;
min-height: calc(100vh - 76px);
}
.hasTagsView {
.app-main {
/* 84 = navbar + tags-view = 50 + 34 */
min-height: calc(100vh - 84px);
}
.fixed-header + .app-main {
padding-top: 84px;
}
.app-main.with-fixed-header.with-tags-view {
min-height: calc(100vh - 111px);
padding-top: 111px;
}
</style>
<style lang="scss">
+246 -53
View File
@@ -1,14 +1,22 @@
<template>
<div class="navbar" :class="'nav' + navType">
<hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggle-click="toggleSideBar" />
<div class="navbar-left">
<div v-if="navType !== NavTypeEnum.TOP" class="hamburger-shell">
<hamburger id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggle-click="toggleSideBar" />
</div>
<router-link v-else-if="showLogo" to="/" class="navtop-logo-shell">
<img :src="appLogo" class="navtop-logo-icon" alt="logo" />
</router-link>
<breadcrumb v-if="navType == NavTypeEnum.LEFT" id="breadcrumb-container" class="breadcrumb-container" />
<top-nav v-if="navType == NavTypeEnum.MIX" id="topmenu-container" class="topmenu-container" />
<div class="nav-context">
<breadcrumb v-if="navType == NavTypeEnum.LEFT" id="breadcrumb-container" class="breadcrumb-container" />
<top-nav v-if="navType == NavTypeEnum.MIX" id="topmenu-container" class="topmenu-container" />
<template v-if="navType == NavTypeEnum.TOP">
<logo v-show="showLogo" :collapse="false"></logo>
<top-bar id="topbar-container" class="topbar-container" />
</template>
<template v-if="navType == NavTypeEnum.TOP">
<top-bar id="topbar-container" class="topbar-container" />
</template>
</div>
</div>
<div class="right-menu flex align-center">
<template v-if="appStore.device !== 'mobile'">
<search-menu ref="searchMenuRef" />
@@ -23,7 +31,7 @@
<el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false">
<template #reference>
<el-badge :value="newNotice > 0 ? newNotice : ''" :max="99">
<div class="right-menu-item hover-effect" style="display: block"><svg-icon icon-class="message" /></div>
<div class="right-menu-item hover-effect message-trigger"><svg-icon icon-class="message" /></div>
</el-badge>
</template>
<template #default>
@@ -53,10 +61,14 @@
</el-tooltip>
</template>
<div class="avatar-container">
<el-dropdown class="right-menu-item hover-effect" trigger="click" @command="handleCommand">
<el-dropdown class="avatar-dropdown" trigger="click" @command="handleCommand">
<div class="avatar-wrapper">
<img :src="userStore.avatar" class="user-avatar" />
<el-icon><caret-bottom /></el-icon>
<div class="avatar-meta">
<span class="avatar-name">{{ displayName }}</span>
<span class="avatar-role">Workspace</span>
</div>
<el-icon class="avatar-arrow"><caret-bottom /></el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
@@ -87,8 +99,9 @@ import notice from './notice/index.vue';
import router from '@/router';
import type { ElMessageBoxOptions } from 'element-plus';
import { NavTypeEnum } from '@/enums/NavTypeEnum';
import Logo from "@/layout/components/Sidebar/Logo.vue";
import TopBar from './TopBar/index.vue';
import { CaretBottom } from '@element-plus/icons-vue';
import appLogo from '@/assets/logo/logo.png';
const appStore = useAppStore();
const userStore = useUserStore();
@@ -98,9 +111,9 @@ const newNotice = ref(<number>0);
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const userId = ref(userStore.userId);
const navType = computed(() => settingsStore.navType);
const showLogo = computed(() => settingsStore.sidebarLogo);
const displayName = computed(() => userStore.nickname || '管理员');
// 搜索菜单
const searchMenuRef = ref<InstanceType<typeof SearchMenu>>();
@@ -157,8 +170,56 @@ watch(
<style lang="scss" scoped>
.navbar.navtop {
.hamburger-container {
display: none !important;
.nav-context {
flex: 1;
}
.navtop-logo-shell {
width: 48px;
height: 40px;
display: inline-flex;
align-items: center;
justify-content: center;
margin-right: 12px;
flex-shrink: 0;
border-radius: 14px;
border: 1px solid rgba(148, 163, 184, 0.18);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(248, 250, 252, 0.82));
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.72),
0 6px 14px rgba(15, 23, 42, 0.04);
transition:
transform 0.2s ease,
border-color 0.2s ease,
box-shadow 0.2s ease;
&:hover {
transform: translateY(-1px);
border-color: rgba(64, 158, 255, 0.22);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.76),
0 10px 22px rgba(15, 23, 42, 0.08);
}
}
.navtop-logo-icon {
width: 32px;
height: 32px;
display: block;
border-radius: 11px;
}
.topbar-container {
flex: 1;
min-width: 0;
margin-left: 0;
padding: 4px 8px;
border-radius: 16px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(248, 250, 252, 0.58));
border: 1px solid rgba(148, 163, 184, 0.14);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.72),
0 6px 18px rgba(15, 23, 42, 0.04);
}
}
@@ -167,7 +228,17 @@ watch(
}
:deep(.el-badge__content.is-fixed) {
top: 12px;
top: 8px;
right: 6px;
}
:deep(.el-badge) {
display: inline-flex;
align-items: center;
}
:deep(.el-dropdown) {
outline: none;
}
.flex {
@@ -179,42 +250,71 @@ watch(
}
.navbar {
height: 50px;
min-height: 52px;
overflow: hidden;
position: relative;
background: var(--el-bg-color);
border-bottom: 1px solid var(--el-border-color-lighter);
box-shadow: none;
background: var(--app-navbar-bg);
border: 1px solid var(--app-navbar-border);
box-shadow: var(--app-navbar-shadow);
display: flex;
align-items: center;
// padding: 0 8px;
justify-content: space-between;
border-radius: 16px;
padding: 6px 12px;
box-sizing: border-box;
.navbar-left {
display: flex;
align-items: center;
min-width: 0;
gap: 10px;
flex: 1;
}
.hamburger-shell {
width: 36px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 12px;
background: transparent;
color: var(--app-accent-strong);
flex-shrink: 0;
border: 1px solid var(--app-surface-border);
}
.hamburger-container {
line-height: 46px;
line-height: 32px;
height: 100%;
//float: left;
cursor: pointer;
transition: background 0.3s;
-webkit-tap-highlight-color: transparent;
display: flex;
align-items: center;
flex-shrink: 0;
margin-right: 8px;
justify-content: center;
&:hover {
background: var(--el-fill-color-lighter);
background: transparent;
}
}
.nav-context {
min-width: 0;
display: flex;
flex-direction: column;
justify-content: center;
gap: 0;
}
.breadcrumb-container {
//float: left;
flex-shrink: 0;
}
.topmenu-container {
position: absolute;
left: 50px;
position: static;
min-width: 0;
}
.topbar-container {
@@ -226,66 +326,159 @@ watch(
margin-left: 8px;
}
.errLog-container {
display: inline-block;
vertical-align: top;
}
.right-menu {
//float: right;
height: 100%;
line-height: 50px;
line-height: 1;
display: flex;
align-items: center;
gap: 6px;
margin-left: auto;
flex-wrap: nowrap;
&:focus {
outline: none;
}
> * {
flex-shrink: 0;
}
.right-menu-item {
display: inline-block;
padding: 0 8px;
height: 100%;
font-size: 18px;
color: var(--el-text-color-regular);
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
font-size: 16px;
color: var(--app-text-muted);
border-radius: 12px;
vertical-align: text-bottom;
background: transparent;
border: 1px solid transparent;
flex-shrink: 0;
:deep(.svg-icon),
:deep(svg),
:deep(.el-icon) {
width: 16px;
height: 16px;
font-size: 16px;
display: block;
}
&.hover-effect {
cursor: pointer;
transition: background 0.3s;
transition:
background 0.3s,
color 0.3s;
&:hover {
background: var(--el-fill-color-lighter);
background: var(--app-accent-soft);
color: var(--app-accent-strong);
border-color: rgba(64, 158, 255, 0.16);
}
}
}
.message-trigger {
display: inline-flex;
}
.avatar-container {
margin-right: 40px;
margin-left: 6px;
margin-right: 0;
flex-shrink: 0;
.avatar-dropdown {
display: block;
width: auto;
height: auto;
border: none;
background: transparent;
}
.avatar-wrapper {
margin-top: 5px;
position: relative;
display: flex;
align-items: center;
gap: 12px;
padding: 4px 8px 4px 4px;
border-radius: 16px;
background: #fff;
border: 1px solid var(--app-surface-border);
min-width: 0;
cursor: pointer;
transition:
background 0.3s,
border-color 0.3s;
&:hover {
background: var(--app-accent-soft);
border-color: rgba(64, 158, 255, 0.16);
}
.user-avatar {
cursor: pointer;
width: 40px;
height: 40px;
border-radius: var(--app-radius-md);
margin-top: 10px;
width: 28px;
height: 28px;
border-radius: 12px;
object-fit: cover;
box-shadow: none;
}
i {
cursor: pointer;
position: absolute;
right: -20px;
top: 25px;
.avatar-meta {
display: flex;
flex-direction: column;
min-width: 0;
gap: 2px;
}
.avatar-name {
max-width: 88px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--app-text-title);
font-size: 12px;
font-weight: 600;
}
.avatar-role {
color: var(--app-text-muted);
font-size: 11px;
}
.avatar-arrow {
color: var(--app-text-muted);
font-size: 12px;
flex-shrink: 0;
}
}
}
}
}
:global(html.dark) {
.navbar.navtop .navtop-logo-shell {
background: linear-gradient(180deg, rgba(15, 23, 42, 0.92), rgba(30, 41, 59, 0.82));
border-color: rgba(71, 85, 105, 0.42);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.06),
0 8px 18px rgba(0, 0, 0, 0.24);
}
.navbar.navtop .topbar-container {
background: linear-gradient(180deg, rgba(15, 23, 42, 0.82), rgba(15, 23, 42, 0.7));
border-color: rgba(71, 85, 105, 0.34);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.05),
0 8px 22px rgba(0, 0, 0, 0.2);
}
.navbar .right-menu .right-menu-item,
.navbar .right-menu .avatar-wrapper {
background: var(--app-navbar-bg);
border-color: var(--app-navbar-border);
}
}
</style>
+41 -4
View File
@@ -1,5 +1,5 @@
<template>
<el-drawer v-model="showSettings" :with-header="false" direction="rtl" size="300px" close-on-click-modal>
<el-drawer v-model="showSettings" class="settings-drawer" :with-header="false" direction="rtl" size="300px" close-on-click-modal>
<h3 class="drawer-title">菜单导航设置</h3>
<div class="nav-wrap">
<el-tooltip content="左侧菜单" placement="bottom">
@@ -229,6 +229,15 @@ defineExpose({
</script>
<style lang="scss" scoped>
.settings-drawer {
:deep(.el-drawer__body) {
display: flex;
flex-direction: column;
gap: 4px;
padding: 18px 18px 20px;
}
}
.setting-drawer-title {
margin-bottom: 12px;
color: rgba(0, 0, 0, 0.85);
@@ -248,12 +257,23 @@ defineExpose({
.setting-drawer-block-checbox-item {
position: relative;
margin-right: 16px;
border-radius: 2px;
border-radius: 12px;
cursor: pointer;
overflow: hidden;
border: 1px solid rgba(148, 163, 184, 0.16);
transition:
border-color 0.2s ease,
transform 0.2s ease;
&:hover {
border-color: rgba(64, 158, 255, 0.28);
transform: translateY(-1px);
}
img {
width: 48px;
height: 48px;
display: block;
}
.custom-img {
@@ -281,6 +301,8 @@ defineExpose({
.drawer-item {
padding: 12px 0;
font-size: 14px;
color: var(--app-text-title);
border-bottom: 1px solid rgba(148, 163, 184, 0.08);
.comp-style {
float: right;
@@ -306,9 +328,16 @@ defineExpose({
cursor: pointer;
width: 56px;
height: 48px;
border-radius: 4px;
background: #f0f2f5;
border-radius: 12px;
background: var(--app-elevated-soft-bg);
border: 2px solid transparent;
transition:
transform 0.2s ease,
border-color 0.2s ease;
&:hover {
transform: translateY(-1px);
}
}
.left {
@@ -317,6 +346,7 @@ defineExpose({
height: 30%;
background: #fff;
}
b:last-child {
width: 30%;
background: #1b2a47;
@@ -326,6 +356,7 @@ defineExpose({
border-radius: 4px 0 0 4px;
}
}
.mix {
b:first-child {
border-radius: 4px 4px 0 0;
@@ -333,6 +364,7 @@ defineExpose({
height: 30%;
background: #1b2a47;
}
b:last-child {
width: 30%;
background: #1b2a47;
@@ -341,6 +373,7 @@ defineExpose({
border-radius: 0 0 0 4px;
}
}
.top {
b:first-child {
display: block;
@@ -348,6 +381,10 @@ defineExpose({
background: #1b2a47;
border-radius: 4px 4px 0 0;
}
b:last-child {
display: none;
}
}
}
</style>
+39 -35
View File
@@ -21,7 +21,6 @@
</template>
<script setup lang="ts">
import variables from '@/assets/styles/variables.module.scss';
import logo from '@/assets/logo/logo.png';
import { useSettingsStore } from '@/store/modules/settings';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -37,28 +36,11 @@ defineProps({
const title = import.meta.env.VITE_APP_LOGO_TITLE;
const settingsStore = useSettingsStore();
const sideTheme = computed(() => settingsStore.sideTheme);
// 获取Logo背景色
const getLogoBackground = computed(() => {
if (settingsStore.isDark) {
return 'var(--sidebar-bg)'
}
if (settingsStore.navType == NavTypeEnum.TOP) {
return variables.menuLightBackground
}
return sideTheme.value === 'theme-dark' ? variables.menuBg : variables.menuLightBackground
})
// 获取Logo文字颜色
const getLogoTextColor = computed(() => {
if (settingsStore.isDark) {
return 'var(--sidebar-text)'
}
if (settingsStore.navType == NavTypeEnum.TOP) {
return variables.logoLightTitleColor
}
return sideTheme.value === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor
})
const isTopNav = computed(() => settingsStore.navType === NavTypeEnum.TOP);
const isDarkSide = computed(() => !isTopNav.value && sideTheme.value === 'theme-dark');
const logoSurface = computed(() => (isDarkSide.value ? 'rgba(255, 255, 255, 0.04)' : '#f8fafc'));
const logoBorder = computed(() => (isDarkSide.value ? 'rgba(148, 163, 184, 0.12)' : '#e5e7eb'));
const logoTextColor = computed(() => (isDarkSide.value ? '#f8fbff' : 'var(--app-text-title)'));
</script>
<style lang="scss" scoped>
@@ -73,39 +55,61 @@ const getLogoTextColor = computed(() => {
.sidebar-logo-container {
position: relative;
height: 50px;
line-height: 50px;
background: v-bind(getLogoBackground);
flex-shrink: 0;
height: 46px;
line-height: 46px;
padding: 0 8px;
margin-top: 8px;
background: transparent;
text-align: center;
overflow: hidden;
margin-bottom: 0;
& .sidebar-logo-link {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
border-radius: 14px;
background: v-bind(logoSurface);
border: 1px solid v-bind(logoBorder);
& .sidebar-logo {
width: 32px;
height: 32px;
width: 28px;
height: 28px;
vertical-align: middle;
margin-right: 12px;
margin-left: 12px;
margin-right: 0;
margin-left: 0;
border-radius: 10px;
box-shadow: none;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: v-bind(getLogoTextColor);
color: v-bind(logoTextColor);
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
line-height: 1;
font-size: 15px;
letter-spacing: 0.02em;
font-family:
'MiSans',
'HarmonyOS Sans SC',
'PingFang SC',
sans-serif;
vertical-align: middle;
}
}
&.collapse {
.sidebar-logo-link {
padding: 0;
}
.sidebar-logo {
margin-right: 0px;
margin-right: 0;
}
}
}
@@ -11,7 +11,7 @@
</app-link>
</template>
<el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
<el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" :popper-offset="isNest ? 4 : 12" :popper-class="popperClass" teleported>
<template v-if="item.meta" #title>
<svg-icon :icon-class="item.meta ? item.meta.icon : ''" />
<span class="menu-title" :title="hasTitle(item.meta?.title)">{{ item.meta?.title }}</span>
@@ -22,6 +22,7 @@
:key="child.path + index"
:is-nest="true"
:item="child"
:popper-class="popperClass"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
@@ -47,6 +48,10 @@ const props = defineProps({
basePath: {
type: String,
default: ''
},
popperClass: {
type: String,
default: ''
}
});
+34 -4
View File
@@ -1,5 +1,5 @@
<template>
<div :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: bgColor }">
<div class="sidebar-shell" :class="{ 'has-logo': showLogo }" :style="{ backgroundColor: bgColor }">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar :class="sideTheme" wrap-class="scrollbar-wrapper">
<transition :enter-active-class="proxy?.animate.menuSearchAnimate.enter" mode="out-in">
@@ -24,7 +24,6 @@
<script setup lang="ts">
import Logo from './Logo.vue';
import SidebarItem from './SidebarItem.vue';
import variables from '@/assets/styles/variables.module.scss';
import { useAppStore } from '@/store/modules/app';
import { useSettingsStore } from '@/store/modules/settings';
import { usePermissionStore } from '@/store/modules/permission';
@@ -51,6 +50,37 @@ const activeMenu = computed(() => {
return path;
});
const bgColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground));
const textColor = computed(() => (sideTheme.value === 'theme-dark' ? variables.menuColor : variables.menuLightColor));
const bgColor = computed(() => (sideTheme.value === 'theme-dark' ? '#111827' : '#ffffff'));
const textColor = computed(() => (sideTheme.value === 'theme-dark' ? '#e5edf8' : '#1f2937'));
</script>
<style lang="scss" scoped>
.sidebar-shell {
height: 100%;
display: flex;
flex-direction: column;
gap: 8px;
padding: 10px 8px 12px;
border: 1px solid var(--app-sidebar-border);
border-radius: 22px;
box-shadow: var(--app-shadow-sm);
background: v-bind(bgColor) !important;
overflow: hidden;
}
:deep(.el-scrollbar__view) {
min-height: 0;
padding-bottom: 12px;
}
:deep(.el-scrollbar) {
flex: 1;
min-height: 0;
height: auto !important;
}
:deep(.el-scrollbar__wrap) {
height: 100%;
overflow-x: hidden;
}
</style>
+222 -35
View File
@@ -1,30 +1,26 @@
<template>
<el-menu class="topbar-menu" :ellipsis="false" :default-active="activeMenu" :active-text-color="theme" mode="horizontal">
<sidebar-item :key="route.path + index" v-for="(route, index) in topMenus" :item="route" :base-path="route.path" />
<sidebar-item :key="route.path + index" v-for="(route, index) in topMenus" :item="route" :base-path="route.path" popper-class="topbar-menu-popper" />
<el-sub-menu index="more" class="el-sub-menu__hide-arrow" v-if="moreRoutes.length > 0">
<el-sub-menu index="more" class="el-sub-menu__hide-arrow" popper-class="topbar-menu-popper" v-if="moreRoutes.length > 0">
<template #title>
<span>更多菜单</span>
</template>
<sidebar-item :key="route.path + index" v-for="(route, index) in moreRoutes" :item="route" :base-path="route.path" />
<sidebar-item :key="route.path + index" v-for="(route, index) in moreRoutes" :item="route" :base-path="route.path" popper-class="topbar-menu-popper" />
</el-sub-menu>
</el-menu>
</template>
<script setup>
<script setup lang="ts">
import SidebarItem from '../Sidebar/SidebarItem'
import {useAppStore} from '@/store/modules/app'
import {useSettingsStore} from '@/store/modules/settings'
import {usePermissionStore} from '@/store/modules/permission'
const route = useRoute()
const appStore = useAppStore()
const settingsStore = useSettingsStore()
const permissionStore = usePermissionStore()
const sidebarRouters = computed(() => permissionStore.sidebarRouters)
const theme = computed(() => settingsStore.theme)
const device = computed(() => appStore.device)
const activeMenu = computed(() => {
const { meta, path } = route
if (meta.activeMenu) {
@@ -38,14 +34,14 @@ const topMenus = computed(() => {
return permissionStore.sidebarRouters.filter((f) => !f.hidden).slice(0, visibleNumber.value)
})
const moreRoutes = computed(() => {
return permissionStore.sidebarRouters.filter((f) => !f.hidden).slice(visibleNumber.value, sidebarRouters.value.length - visibleNumber.value)
return permissionStore.sidebarRouters.filter((f) => !f.hidden).slice(visibleNumber.value)
})
function setVisibleNumber() {
let width = document.body.getBoundingClientRect().width
if (width >= 1000) {
width -= 500
width -= 420
}
visibleNumber.value = parseInt(width / 3 / 85)
visibleNumber.value = Math.max(1, Math.floor(width / 3 / 92) + 2)
}
onMounted(() => {
@@ -61,43 +57,234 @@ onMounted(() => {
</script>
<style lang="scss">
.topbar-menu.el-menu--horizontal {
--topbar-pill-bg: rgba(255, 255, 255, 0.7);
--topbar-pill-hover-bg: rgba(255, 255, 255, 0.9);
--topbar-pill-active-bg: rgba(255, 255, 255, 0.82);
--topbar-pill-text: var(--app-text-title);
--topbar-pill-muted: var(--app-text-muted);
--topbar-pill-border: rgba(148, 163, 184, 0.12);
--topbar-pill-active-border: rgba(148, 163, 184, 0.14);
/* menu item */
#app .topbar-menu.el-menu--horizontal .el-sub-menu__title, #app .topbar-menu.el-menu--horizontal .el-menu-item {
padding: 0 10px !important;
display: flex;
align-items: center;
gap: 6px;
flex: 1;
min-width: 0;
height: 44px;
padding: 0;
border: none !important;
background: transparent !important;
&::after {
display: none !important;
}
}
.topbar-menu.el-menu--horizontal > .el-menu-item {
float: left;
height: 50px !important;
line-height: 50px !important;
color: #303133 !important;
padding: 0 5px !important;
margin: 0 10px !important;
#app .topbar-menu.el-menu--horizontal > div > a > .el-menu-item,
#app .topbar-menu.el-menu--horizontal > div > .el-sub-menu > .el-sub-menu__title,
#app .topbar-menu.el-menu--horizontal > .el-sub-menu > .el-sub-menu__title {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 7px;
height: 36px !important;
line-height: 36px !important;
margin: 0 !important;
padding: 0 18px !important;
border: 1px solid transparent !important;
border-radius: 13px;
color: var(--topbar-pill-text) !important;
background: transparent !important;
transition:
background-color 0.2s ease,
color 0.2s ease,
box-shadow 0.2s ease,
border-color 0.2s ease,
transform 0.2s ease;
}
.el-sub-menu.is-active .svg-icon, .el-menu-item.is-active .svg-icon + span, .el-sub-menu.is-active .svg-icon + span, .el-sub-menu.is-active .el-sub-menu__title span {
color: v-bind(theme);
#app .topbar-menu.el-menu--horizontal > div > a > .el-menu-item:hover,
#app .topbar-menu.el-menu--horizontal > div > .el-sub-menu > .el-sub-menu__title:hover,
#app .topbar-menu.el-menu--horizontal > .el-sub-menu > .el-sub-menu__title:hover {
background: linear-gradient(180deg, var(--topbar-pill-hover-bg), var(--topbar-pill-bg)) !important;
border-color: var(--topbar-pill-border) !important;
color: v-bind(theme) !important;
transform: translateY(-1px);
}
/* sub-menu item */
.topbar-menu.el-menu--horizontal > .el-sub-menu .el-sub-menu__title {
float: left;
line-height: 50px !important;
color: #303133 !important;
margin: 0 15px -3px!important;
#app .topbar-menu.el-menu--horizontal > div > a > .el-menu-item.is-active,
#app .topbar-menu.el-menu--horizontal > div > .el-sub-menu.is-active > .el-sub-menu__title,
#app .topbar-menu.el-menu--horizontal > .el-sub-menu.is-active > .el-sub-menu__title {
background: linear-gradient(180deg, var(--topbar-pill-hover-bg), var(--topbar-pill-active-bg)) !important;
border-color: var(--topbar-pill-active-border) !important;
color: v-bind(theme) !important;
box-shadow: none !important;
transform: none !important;
}
#app .topbar-menu.el-menu--horizontal > div > a > .el-menu-item .svg-icon,
#app .topbar-menu.el-menu--horizontal > div > .el-sub-menu > .el-sub-menu__title .svg-icon,
#app .topbar-menu.el-menu--horizontal > .el-sub-menu > .el-sub-menu__title .svg-icon {
width: 14px;
height: 14px;
margin-right: 0 !important;
flex-shrink: 0;
}
#app .topbar-menu.el-menu--horizontal > div > a > .el-menu-item span,
#app .topbar-menu.el-menu--horizontal > div > .el-sub-menu > .el-sub-menu__title span,
#app .topbar-menu.el-menu--horizontal > .el-sub-menu > .el-sub-menu__title span {
color: inherit !important;
font-size: 13px;
font-weight: 500;
letter-spacing: 0.01em;
}
.topbar-menu.el-menu--horizontal > div > a > .el-menu-item.is-active span,
.topbar-menu.el-menu--horizontal > div > .el-sub-menu.is-active > .el-sub-menu__title span,
.topbar-menu.el-menu--horizontal > .el-sub-menu.is-active > .el-sub-menu__title span {
font-weight: 500;
}
/* topbar more arrow */
.topbar-menu .el-sub-menu .el-sub-menu__icon-arrow {
position: static;
margin-left: 8px;
margin-top: 0px;
margin: 0 0 0 2px;
display: block !important;
color: inherit;
font-size: 11px;
}
/* menu__title el-menu-item */
.topbar-menu.el-menu--horizontal .el-sub-menu__title, .topbar-menu.el-menu--horizontal .el-menu-item {
height: 60px;
.topbar-menu.el-menu--horizontal > div > a > .el-menu-item::after,
.topbar-menu.el-menu--horizontal > div > .el-sub-menu > .el-sub-menu__title::after,
.topbar-menu.el-menu--horizontal > .el-sub-menu > .el-sub-menu__title::after {
display: none !important;
}
.topbar-menu.el-menu--horizontal > .el-sub-menu.el-sub-menu__hide-arrow > .el-sub-menu__title {
color: var(--topbar-pill-muted) !important;
padding-right: 16px !important;
}
html.dark .topbar-menu.el-menu--horizontal {
--topbar-pill-bg: rgba(30, 41, 59, 0.64);
--topbar-pill-hover-bg: rgba(51, 65, 85, 0.88);
--topbar-pill-active-bg: rgba(51, 65, 85, 0.78);
--topbar-pill-border: rgba(71, 85, 105, 0.28);
--topbar-pill-active-border: rgba(71, 85, 105, 0.32);
}
html.dark #app .topbar-menu.el-menu--horizontal > div > a > .el-menu-item.is-active,
html.dark #app .topbar-menu.el-menu--horizontal > div > .el-sub-menu.is-active > .el-sub-menu__title,
html.dark #app .topbar-menu.el-menu--horizontal > .el-sub-menu.is-active > .el-sub-menu__title {
box-shadow: none !important;
}
.topbar-menu-popper.el-popper {
border: none !important;
border-radius: 18px !important;
background: transparent !important;
box-shadow: none !important;
padding: 0 !important;
}
.topbar-menu-popper.el-popper .el-popper__arrow {
display: none !important;
}
.topbar-menu-popper .el-menu--popup {
min-width: 188px;
padding: 10px !important;
border: 1px solid rgba(148, 163, 184, 0.14);
border-radius: 18px;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 250, 252, 0.94)) !important;
box-shadow:
0 18px 40px rgba(15, 23, 42, 0.12),
inset 0 1px 0 rgba(255, 255, 255, 0.72);
}
.topbar-menu-popper .el-menu--popup .el-menu-item,
.topbar-menu-popper .el-menu--popup .el-sub-menu__title {
display: flex;
align-items: center;
height: 38px;
line-height: 38px;
padding: 0 14px !important;
margin: 0 0 4px !important;
border-radius: 12px;
color: var(--app-text-title) !important;
background: transparent !important;
transition:
background-color 0.2s ease,
color 0.2s ease,
box-shadow 0.2s ease,
transform 0.2s ease;
}
.topbar-menu-popper .el-menu--popup .el-menu-item:last-child,
.topbar-menu-popper .el-menu--popup .el-sub-menu:last-child > .el-sub-menu__title {
margin-bottom: 0 !important;
}
.topbar-menu-popper .el-menu--popup .el-menu-item:hover,
.topbar-menu-popper .el-menu--popup .el-sub-menu__title:hover {
background: rgba(64, 158, 255, 0.08) !important;
color: v-bind(theme) !important;
transform: translateX(1px);
}
.topbar-menu-popper .el-menu--popup .el-menu-item.is-active,
.topbar-menu-popper .el-menu--popup .el-sub-menu.is-active > .el-sub-menu__title {
background: linear-gradient(180deg, rgba(64, 158, 255, 0.16), rgba(64, 158, 255, 0.1)) !important;
color: v-bind(theme) !important;
box-shadow: inset 0 0 0 1px rgba(64, 158, 255, 0.12);
}
.topbar-menu-popper .el-menu--popup .svg-icon {
width: 14px;
height: 14px;
margin-right: 10px !important;
}
.topbar-menu-popper .el-menu--popup .menu-title,
.topbar-menu-popper .el-menu--popup .el-sub-menu__title > span,
.topbar-menu-popper .el-menu--popup .el-menu-item > span {
display: inline-flex;
align-items: center;
font-size: 13px;
font-weight: 500;
letter-spacing: 0.01em;
}
.topbar-menu-popper .el-menu--popup .el-sub-menu__icon-arrow {
position: static;
margin-left: auto;
margin-top: 0;
font-size: 11px;
align-self: center;
}
html.dark .topbar-menu-popper .el-menu--popup {
border-color: rgba(71, 85, 105, 0.34);
background: linear-gradient(180deg, rgba(15, 23, 42, 0.98), rgba(30, 41, 59, 0.94)) !important;
box-shadow:
0 20px 42px rgba(0, 0, 0, 0.34),
inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
html.dark .topbar-menu-popper .el-menu--popup .el-menu-item,
html.dark .topbar-menu-popper .el-menu--popup .el-sub-menu__title {
color: #e5edf8 !important;
}
html.dark .topbar-menu-popper .el-menu--popup .el-menu-item:hover,
html.dark .topbar-menu-popper .el-menu--popup .el-sub-menu__title:hover {
background: rgba(96, 165, 250, 0.14) !important;
}
html.dark .topbar-menu-popper .el-menu--popup .el-menu-item.is-active,
html.dark .topbar-menu-popper .el-menu--popup .el-sub-menu.is-active > .el-sub-menu__title {
background: linear-gradient(180deg, rgba(37, 99, 235, 0.28), rgba(59, 130, 246, 0.18)) !important;
box-shadow: inset 0 0 0 1px rgba(96, 165, 250, 0.16);
}
</style>
+3
View File
@@ -145,6 +145,9 @@ defineExpose({
left: 50%;
transform: translateX(-50%);
top: -53vh;
padding: 0;
border-top: none;
background: transparent;
}
}
:deep(.el-autocomplete) {
+55 -13
View File
@@ -66,59 +66,101 @@ onMounted(() => {
<style lang="scss" scoped>
.layout-navbars-breadcrumb-user-news {
display: flex;
flex-direction: column;
min-width: 0;
.head-box {
display: flex;
border-bottom: 1px solid var(--el-border-color-lighter);
border-bottom: 1px solid rgba(148, 163, 184, 0.14);
box-sizing: border-box;
color: var(--el-text-color-primary);
color: var(--app-text-title);
justify-content: space-between;
height: 35px;
height: 40px;
align-items: center;
padding: 0 2px 10px;
.head-box-title {
font-size: 14px;
font-weight: 600;
}
.head-box-btn {
color: var(--el-color-primary);
font-size: 13px;
color: var(--app-accent-strong);
font-size: 12px;
font-weight: 600;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
.content-box {
height: 300px;
overflow: auto;
font-size: 13px;
padding: 8px 0;
.content-box-item {
padding-top: 12px;
display: flex;
&:last-of-type {
padding-bottom: 12px;
gap: 10px;
align-items: flex-start;
padding: 12px;
margin: 4px 0;
border-radius: 12px;
cursor: pointer;
transition:
background-color 0.2s ease,
transform 0.2s ease;
&:hover {
background: var(--app-accent-soft);
transform: translateY(-1px);
}
.content-box-msg {
color: var(--el-text-color-secondary);
margin-top: 5px;
margin-bottom: 5px;
}
.content-box-time {
color: var(--el-text-color-secondary);
color: var(--app-text-muted);
font-size: 12px;
}
.item-conten {
width: 100%;
display: flex;
flex-direction: column;
gap: 6px;
color: var(--app-text-title);
line-height: 1.6;
}
.read {
flex-shrink: 0;
margin-top: 2px;
}
}
}
.foot-box {
height: 35px;
color: var(--el-color-primary);
font-size: 13px;
height: 40px;
color: var(--app-accent-strong);
font-size: 12px;
font-weight: 600;
cursor: pointer;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid var(--el-border-color-lighter);
border-top: 1px solid rgba(148, 163, 184, 0.14);
margin-top: 4px;
&:hover {
opacity: 1;
}
+19 -18
View File
@@ -1,21 +1,13 @@
<template>
<div :class="classObj" class="app-wrapper" :style="{ '--current-color': theme }">
<div v-if="device === 'mobile' && sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<side-bar v-if="!sidebar.hide" class="sidebar-container" />
<side-bar v-if="showSidebar" class="sidebar-container" />
<div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide }" class="main-container">
<!-- <el-scrollbar>
<div :class="{ 'fixed-header': fixedHeader }">
<navbar ref="navbarRef" @setLayout="setLayout" />
<tags-view v-if="needTagsView" />
</div>
<app-main />
<settings ref="settingRef" />
</el-scrollbar> -->
<div :class="{ 'fixed-header': fixedHeader }">
<navbar ref="navbarRef" @set-layout="setLayout" />
<div :class="{ 'fixed-header': fixedHeader }" class="layout-header">
<navbar @set-layout="setLayout" />
<tags-view v-if="needTagsView" />
</div>
<app-main />
<app-main :class="{ 'with-fixed-header': fixedHeader, 'with-tags-view': needTagsView }" />
<settings ref="settingRef" />
</div>
</div>
@@ -66,7 +58,6 @@ watchEffect(() => {
}
});
const navbarRef = ref<InstanceType<typeof Navbar>>();
const settingRef = ref<InstanceType<typeof Settings>>();
onMounted(() => {
@@ -96,6 +87,7 @@ const setLayout = () => {
position: relative;
height: 100%;
width: 100%;
background: var(--app-shell-bg);
&.mobile.openSidebar {
position: fixed;
@@ -105,7 +97,7 @@ const setLayout = () => {
.drawer-bg {
background: #000;
opacity: 0.3;
opacity: 0.4;
width: 100%;
top: 0;
height: 100%;
@@ -113,18 +105,26 @@ const setLayout = () => {
z-index: 999;
}
.layout-header {
position: relative;
z-index: 9;
display: flex;
flex-direction: column;
gap: 3px;
padding: 12px 12px 0;
background: transparent;
}
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$base-sidebar-width});
width: calc(100% - #{$base-sidebar-width} - 12px);
transition: width 0.28s;
background: $fixed-header-bg;
}
.hideSidebar .fixed-header {
width: calc(100% - 54px);
width: calc(100% - 70px);
}
.sidebarHide .fixed-header {
@@ -133,5 +133,6 @@ const setLayout = () => {
.mobile .fixed-header {
width: 100%;
top: 0;
}
</style>