| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- <template>
- <el-container class="admin-layout">
- <el-aside :width="collapsed ? '64px' : '240px'" class="aside-container">
- <div class="logo-section">
- <router-link to="/bg" class="logo-link">
- <img class="logo-img" src="@/assets/img/logo.png" alt="logo">
- <transition name="logo-fade">
- <h1 v-show="!collapsed" class="logo-text">用户后台</h1>
- </transition>
- </router-link>
- </div>
- <el-menu
- :default-active="$route.path"
- router
- class="admin-menu"
- background-color="#0d131a"
- text-color="rgba(255, 255, 255, 0.65)"
- active-text-color="#ffffff"
- :unique-opened="true"
- :collapse="collapsed"
- :collapse-transition="false"
- >
- <el-submenu v-for="item in menuList" :key="item.path" :index="item.path">
- <template slot="title">
- <i :class="[item.icon, 'menu-icon']" />
- <span class="menu-title-text">{{ item.title }}</span>
- </template>
- <el-menu-item v-for="child in item.children" :key="child.path" :index="child.path">
- <i :class="[child.icon, 'menu-icon-child']" />
- <span slot="title" class="menu-title-text">{{ child.title }}</span>
- </el-menu-item>
- </el-submenu>
- </el-menu>
- </el-aside>
- <el-container class="content-container">
- <el-header class="admin-header">
- <div class="header-left">
- <el-button
- class="toggle-btn"
- :icon="collapsed ? 'el-icon-s-unfold' : 'el-icon-s-fold'"
- @click="collapsed = !collapsed"
- />
- </div>
- <div class="header-right">
- <div class="icon-item-wrapper" @click="goToMessage">
- <el-badge :value="msgCount" :max="99" :hidden="msgCount <= 0" class="badge-item">
- <i class="el-icon-message-solid custom-icon" />
- </el-badge>
- <span class="icon-label">消息</span>
- </div>
- <el-dropdown trigger="hover" class="user-dropdown">
- <div class="user-info">
- <el-avatar
- :size="28"
- :src="user && user.avatarUrl ? user.avatarUrl : ''"
- icon="el-icon-user-solid"
- class="mgr-8"
- />
- <span class="username">{{ user ? user.username : '管理员' }}</span>
- <i class="el-icon-arrow-down el-icon--right" />
- </div>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item icon="el-icon-s-home" @click.native="backToHome">
- 回到前台
- </el-dropdown-item>
- <el-dropdown-item icon="el-icon-switch-button" divided @click.native="goToLogout">
- 退出登录
- </el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- </div>
- </el-header>
- <el-main class="admin-main">
- <div class="main-content-card">
- <router-view />
- </div>
- </el-main>
- </el-container>
- </el-container>
- </template>
- <script>
- import store from '@/store'
- import { userMixin } from 'assets/js/mixin'
- import { getAuthedUser } from '@/utils/auth'
- import { getUnreadCount } from '@/api/user'
- export default {
- name: 'Background',
- mixins: [userMixin],
- data() {
- return {
- collapsed: false,
- user: null,
- menuList: [],
- msgCount: 0
- }
- },
- created() {
- this.user = getAuthedUser()
- if (this.user !== null) {
- getUnreadCount().then(resp => {
- if (resp.code === 0) {
- this.msgCount = resp.data.total
- }
- })
- }
- this.initMenus()
- },
- methods: {
- initMenus() {
- const routes = store.getters.addRoutes || []
- routes.forEach(route => {
- if (route.path === '/bg') {
- if (route.children) this.menuList.push(...route.children)
- } else if (route.path.startsWith('/bg/')) {
- this.menuList.push(route)
- }
- })
- },
- backToHome() {
- this.$router.push('/')
- },
- goToMessage() {
- this.$router.push('/bg/account/message')
- }
- }
- }
- </script>
- <style scoped>
- .admin-layout {
- height: 100vh;
- width: 100%;
- }
- /* ==================== 🌸 现代化侧边栏重塑 ==================== */
- .aside-container {
- background-color: #0d131a; /* 更高级的黑青色,远离沉闷死黑 */
- transition: width 0.25s cubic-bezier(0.3, 0.1, 0.3, 1);
- overflow: hidden;
- box-shadow: 4px 0 24px rgba(0, 0, 0, 0.15);
- display: flex;
- flex-direction: column;
- }
- .admin-menu {
- border-right: none;
- flex: 1;
- padding: 8px 0; /* 让菜单顶部有呼吸感 */
- }
- /* Logo 区域重绘 */
- .logo-section {
- height: 64px;
- display: flex;
- align-items: center;
- padding: 0 16px;
- background-color: #0d131a;
- border-bottom: 1px solid rgba(255, 255, 255, 0.04); /* 极细精致分界线 */
- box-sizing: border-box;
- }
- .logo-link {
- display: flex;
- align-items: center;
- text-decoration: none;
- width: 100%;
- padding-left: 4px;
- }
- .logo-img {
- height: 28px;
- width: 28px;
- object-fit: contain;
- filter: drop-shadow(0 2px 8px rgba(24, 144, 255, 0.3)); /* 让 Logo 微发光 */
- }
- .logo-text {
- color: #ffffff;
- font-size: 16px;
- margin-left: 12px;
- font-weight: 600;
- white-space: nowrap;
- letter-spacing: 0.5px;
- }
- /* Logo 丝滑文字动效 */
- .logo-fade-enter-active {
- transition: all 0.3s ease-out;
- }
- .logo-fade-leave-active {
- transition: all 0.1s ease-in;
- }
- .logo-fade-enter, .logo-fade-leave-to {
- opacity: 0;
- transform: translateX(-10px);
- }
- /* ==================== 🛠️ Element UI 菜单高级覆构 ==================== */
- /* 1. 基础间距与弧度微调 */
- ::v-deep .el-submenu,
- ::v-deep .el-menu-item {
- padding: 0 12px !important; /* 给左右空出间距,打造胶囊浮动感 */
- margin: 4px 0;
- }
- ::v-deep .el-submenu__title,
- ::v-deep .el-menu-item {
- height: 44px !important;
- line-height: 44px !important;
- border-radius: 6px !important; /* 统一小圆角 */
- margin: 2px 0;
- }
- /* 图标与文本精致感调整 */
- .menu-icon {
- font-size: 16px;
- margin-right: 12px !important;
- transition: transform 0.25s ease;
- }
- .menu-icon-child {
- font-size: 14px;
- margin-right: 12px !important;
- opacity: 0.7;
- }
- .menu-title-text {
- font-size: 14px;
- letter-spacing: 0.3px;
- }
- /* 2. 悬浮态(Hover)美化 */
- ::v-deep .el-submenu__title:hover,
- ::v-deep .el-menu-item:hover {
- color: #ffffff !important;
- background-color: rgba(255, 255, 255, 0.05) !important; /* 极其柔和的半透明浅白 */
- }
- ::v-deep .el-submenu__title:hover .menu-icon {
- transform: scale(1.08); /* 悬浮时图标微放大交互 */
- }
- /* 3. 子菜单展开后的深色背景(层级化) */
- ::v-deep .el-menu--inline {
- background-color: #06090d !important; /* 子菜单背景明显更深,营造内陷嵌套感 */
- border-radius: 6px;
- padding: 4px 0;
- margin-top: 2px;
- }
- /* 4. 核心:高难度现代高亮激活态(Floating Capsule & Side Indicator) */
- ::v-deep .el-menu-item.is-active {
- background-color: #1890ff !important; /* 主题蓝渐变基础色 */
- background: linear-gradient(135deg, #1890ff 0%, #0076e4 100%) !important; /* 微渐变极具质感 */
- color: #ffffff !important;
- font-weight: 500;
- box-shadow: 0 4px 12px rgba(24, 144, 255, 0.25); /* 胶囊发光悬浮感 */
- }
- ::v-deep .el-menu-item.is-active .menu-icon-child {
- opacity: 1;
- color: #ffffff !important;
- }
- /* 当子菜单项激活时,父级标题的亮白突出 */
- ::v-deep .el-submenu.is-active > .el-submenu__title {
- color: #ffffff !important;
- }
- ::v-deep .el-submenu.is-active > .el-submenu__title i {
- color: #1890ff !important; /* 父级图标变蓝 */
- }
- /* 5. 折叠状态(Collapse)特殊处理 */
- .admin-menu:not(.el-menu--collapse) {
- width: 240px;
- }
- ::v-deep .el-menu--collapse {
- width: 64px;
- }
- ::v-deep .el-menu--collapse .el-submenu,
- ::v-deep .el-menu--collapse .el-menu-item {
- padding: 0 8px !important; /* 折叠后更紧凑 */
- }
- ::v-deep .el-menu--collapse .menu-icon {
- margin-right: 0 !important;
- }
- /* ==================== 顶部和常规组件保持优秀样式 ==================== */
- .admin-header {
- background-color: #fff;
- padding: 0 20px;
- height: 64px !important;
- display: flex;
- justify-content: space-between;
- align-items: center;
- box-shadow: 0 1px 4px rgba(0, 21, 41, 0.05);
- z-index: 10;
- }
- .toggle-btn {
- font-size: 20px;
- border: none;
- background: transparent;
- color: #333;
- padding: 8px;
- cursor: pointer;
- }
- .toggle-btn:hover { color: #1890ff; }
- .header-right { display: flex; align-items: center; gap: 8px; }
- .user-info { display: flex; align-items: center; padding: 0 12px; height: 64px; cursor: pointer; transition: all 0.3s; }
- .user-info:hover { background-color: rgba(0, 0, 0, 0.025); }
- .username { font-size: 14px; font-weight: 500; color: rgba(0, 0, 0, 0.65); }
- .mgr-8 { margin-right: 8px; }
- .admin-main { background-color: #f4f7f9; padding: 24px; }
- .main-content-card { background: #fff; min-height: calc(100vh - 112px); border-radius: 8px; padding: 24px; box-shadow: 0 1px 3px rgba(0,0,0,0.02); }
- .icon-item-wrapper { display: flex; align-items: center; justify-content: center; gap: 6px; height: 64px; padding: 0 16px; cursor: pointer; transition: all 0.3s; border-radius: 4px; }
- .icon-item-wrapper:hover { background-color: rgba(0, 0, 0, 0.025); }
- .icon-item-wrapper:hover .custom-icon, .icon-item-wrapper:hover .icon-label { color: #1890ff; }
- .custom-icon { font-size: 18px; color: rgba(0, 0, 0, 0.65); transition: color 0.3s; }
- .icon-label { font-size: 14px; font-weight: 500; color: rgba(0, 0, 0, 0.65); transition: color 0.3s; }
- .badge-item ::v-deep .el-badge__content { font-family: sans-serif; border: 1px solid #fff; top: 2px; right: 2px; }
- </style>
|