feat: establish admin visual foundation
This commit is contained in:
@@ -2,67 +2,495 @@
|
||||
<el-container class="main-layout">
|
||||
<el-aside :width="isCollapse ? '72px' : '220px'" class="sidebar">
|
||||
<div class="brand" :class="{ compact: isCollapse }">
|
||||
<div class="brand-symbol">缘</div>
|
||||
<div v-if="!isCollapse" class="brand-copy"><strong>善缘丹阳</strong><span>公益婚恋运营平台</span></div>
|
||||
<img class="brand-mark" src="/brand/logo-mark.png" alt="" />
|
||||
<div v-if="!isCollapse" class="brand-copy">
|
||||
<strong>善缘丹阳</strong>
|
||||
<span>公益婚恋运营平台</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-scrollbar class="menu-scroll">
|
||||
<el-menu :default-active="activeMenu" :collapse="isCollapse" :router="true" class="sidebar-menu">
|
||||
<el-menu-item index="/dashboard"><el-icon><DataBoard /></el-icon><template #title>工作台</template></el-menu-item>
|
||||
<el-menu-item-group v-if="showGroup(['review.view','user.view'])" title="资料与用户">
|
||||
<el-menu-item v-if="hasPerm('review.view')" index="/review"><el-icon><DocumentChecked /></el-icon><template #title>资料审核</template></el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('user.view')" index="/users"><el-icon><User /></el-icon><template #title>用户管理</template></el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group v-if="showGroup(['counseling.service.view','service_program.manage','referral.manage'])" title="婚恋服务">
|
||||
<el-menu-item v-if="hasPerm('counseling.service.view')" index="/counseling"><el-icon><ChatDotRound /></el-icon><template #title>婚恋咨询</template></el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('service_program.manage')" index="/service-program"><el-icon><Service /></el-icon><template #title>专项公益服务</template></el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('referral.manage')" index="/referral"><el-icon><Connection /></el-icon><template #title>服务转介</template></el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group v-if="showGroup(['activity.review_registration'])" title="活动运营">
|
||||
<el-menu-item index="/activities/interests"><el-icon><Calendar /></el-icon><template #title>活动与互选</template></el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group v-if="showGroup(['banner.view','content.view'])" title="内容运营">
|
||||
<el-menu-item v-if="hasPerm('banner.view')" index="/banner"><el-icon><Promotion /></el-icon><template #title>首页 Banner</template></el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('content.view')" index="/content"><el-icon><Reading /></el-icon><template #title>课堂与反诈内容</template></el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group v-if="showGroup(['service_location.view','service_appointment.view'])" title="服务阵地">
|
||||
<el-menu-item v-if="hasPerm('service_location.view')" index="/service-station"><el-icon><Location /></el-icon><template #title>善缘服务站</template></el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('service_appointment.view')" index="/service-appointment"><el-icon><Memo /></el-icon><template #title>服务预约</template></el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group v-if="showGroup(['risk.report.view','risk.report.process'])" title="安全治理">
|
||||
<el-menu-item v-if="hasPerm('risk.report.view')" index="/risk/reports"><el-icon><Warning /></el-icon><template #title>举报中心</template></el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('risk.report.process')" index="/appeals"><el-icon><CircleCheck /></el-icon><template #title>申诉管理</template></el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group v-if="showGroup(['organization.manage','permission.manage','user.view'])" title="组织与系统">
|
||||
<el-menu-item v-if="hasPerm('organization.manage')" index="/organizations"><el-icon><OfficeBuilding /></el-icon><template #title>组织管理</template></el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('permission.manage')" index="/operators"><el-icon><Setting /></el-icon><template #title>工作人员</template></el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('user.view')" index="/audit"><el-icon><Document /></el-icon><template #title>操作日志</template></el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item v-if="hasPerm('analytics.view')" index="/analytics"><el-icon><TrendCharts /></el-icon><template #title>数据统计</template></el-menu-item>
|
||||
</el-menu>
|
||||
<nav aria-label="管理后台主导航">
|
||||
<el-menu :default-active="activeMenu" :collapse="isCollapse" :router="true" class="sidebar-menu">
|
||||
<el-menu-item index="/dashboard">
|
||||
<el-icon><DataBoard /></el-icon>
|
||||
<template #title>工作台</template>
|
||||
</el-menu-item>
|
||||
|
||||
<el-menu-item-group v-if="showGroup(['review.view', 'user.view'])" title="用户与资料审核">
|
||||
<el-menu-item v-if="hasPerm('review.view')" index="/review">
|
||||
<el-icon><DocumentChecked /></el-icon>
|
||||
<template #title>资料审核</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('user.view')" index="/users">
|
||||
<el-icon><User /></el-icon>
|
||||
<template #title>用户管理</template>
|
||||
</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
|
||||
<el-menu-item-group v-if="hasPerm('activity.review_registration')" title="匹配与活动服务">
|
||||
<el-menu-item index="/activities/interests">
|
||||
<el-icon><Calendar /></el-icon>
|
||||
<template #title>活动与互选</template>
|
||||
</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
|
||||
<el-menu-item-group
|
||||
v-if="showGroup(['counseling.service.view', 'referral.manage'])"
|
||||
title="公益咨询与转介"
|
||||
>
|
||||
<el-menu-item v-if="hasPerm('counseling.service.view')" index="/counseling">
|
||||
<el-icon><ChatDotRound /></el-icon>
|
||||
<template #title>婚恋咨询</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('referral.manage')" index="/referral">
|
||||
<el-icon><Connection /></el-icon>
|
||||
<template #title>服务转介</template>
|
||||
</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
|
||||
<el-menu-item-group
|
||||
v-if="showGroup(['service_location.view', 'service_appointment.view', 'service_program.manage'])"
|
||||
title="服务站、预约与专项服务"
|
||||
>
|
||||
<el-menu-item v-if="hasPerm('service_location.view')" index="/service-station">
|
||||
<el-icon><Location /></el-icon>
|
||||
<template #title>善缘服务站</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('service_appointment.view')" index="/service-appointment">
|
||||
<el-icon><Memo /></el-icon>
|
||||
<template #title>服务预约</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('service_program.manage')" index="/service-program">
|
||||
<el-icon><Service /></el-icon>
|
||||
<template #title>专项公益服务</template>
|
||||
</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
|
||||
<el-menu-item-group v-if="showGroup(['banner.view', 'content.view'])" title="Banner 与内容运营">
|
||||
<el-menu-item v-if="hasPerm('banner.view')" index="/banner">
|
||||
<el-icon><Promotion /></el-icon>
|
||||
<template #title>首页 Banner</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('content.view')" index="/content">
|
||||
<el-icon><Reading /></el-icon>
|
||||
<template #title>课堂与反诈内容</template>
|
||||
</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
|
||||
<el-menu-item-group
|
||||
v-if="showGroup(['risk.report.view', 'risk.report.process', 'user.view'])"
|
||||
title="举报、申诉与审计"
|
||||
>
|
||||
<el-menu-item v-if="hasPerm('risk.report.view')" index="/risk/reports">
|
||||
<el-icon><Warning /></el-icon>
|
||||
<template #title>举报中心</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('risk.report.process')" index="/appeals">
|
||||
<el-icon><CircleCheck /></el-icon>
|
||||
<template #title>申诉管理</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('user.view')" index="/audit">
|
||||
<el-icon><Document /></el-icon>
|
||||
<template #title>操作日志</template>
|
||||
</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
|
||||
<el-menu-item-group
|
||||
v-if="showGroup(['organization.manage', 'permission.manage'])"
|
||||
title="组织、人员与权限"
|
||||
>
|
||||
<el-menu-item v-if="hasPerm('organization.manage')" index="/organizations">
|
||||
<el-icon><OfficeBuilding /></el-icon>
|
||||
<template #title>组织管理</template>
|
||||
</el-menu-item>
|
||||
<el-menu-item v-if="hasPerm('permission.manage')" index="/operators">
|
||||
<el-icon><Setting /></el-icon>
|
||||
<template #title>工作人员</template>
|
||||
</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
|
||||
<el-menu-item v-if="hasPerm('analytics.view')" index="/analytics">
|
||||
<el-icon><TrendCharts /></el-icon>
|
||||
<template #title>数据统计</template>
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</nav>
|
||||
</el-scrollbar>
|
||||
<button class="collapse-control" type="button" @click="isCollapse=!isCollapse"><el-icon><Fold v-if="!isCollapse"/><Expand v-else/></el-icon><span v-if="!isCollapse">收起导航</span></button>
|
||||
|
||||
<button
|
||||
class="collapse-control"
|
||||
type="button"
|
||||
:aria-label="isCollapse ? '展开导航' : '收起导航'"
|
||||
@click="isCollapse = !isCollapse"
|
||||
>
|
||||
<el-icon><Fold v-if="!isCollapse" /><Expand v-else /></el-icon>
|
||||
<span v-if="!isCollapse">收起导航</span>
|
||||
</button>
|
||||
</el-aside>
|
||||
|
||||
<el-container class="workspace">
|
||||
<el-header class="header">
|
||||
<div><div class="context-kicker">善缘丹阳 · 公益服务</div><el-breadcrumb separator="/"><el-breadcrumb-item :to="{path:'/dashboard'}">工作台</el-breadcrumb-item><el-breadcrumb-item v-if="currentTitle!=='工作台'">{{currentTitle}}</el-breadcrumb-item></el-breadcrumb></div>
|
||||
<div class="header-right"><div class="service-state"><i></i>服务正常</div><el-dropdown><span class="user-info"><el-avatar :size="36">{{(operator?.name||'工')[0]}}</el-avatar><span><strong>{{operator?.name||'工作人员'}}</strong><small>运营人员</small></span><el-icon><ArrowDown/></el-icon></span><template #dropdown><el-dropdown-menu><el-dropdown-item @click="handleLogout">退出登录</el-dropdown-item></el-dropdown-menu></template></el-dropdown></div>
|
||||
<div class="page-context">
|
||||
<div class="context-kicker">善缘丹阳 · 公益服务</div>
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item :to="{ path: '/dashboard' }">工作台</el-breadcrumb-item>
|
||||
<el-breadcrumb-item v-if="currentTitle !== '工作台'">{{ currentTitle }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
|
||||
<div class="header-tools">
|
||||
<el-input
|
||||
v-model="globalSearch"
|
||||
class="global-search"
|
||||
clearable
|
||||
aria-label="搜索后台页面"
|
||||
placeholder="搜索用户、活动、内容…"
|
||||
@keyup.enter="handleSearch"
|
||||
>
|
||||
<template #prefix><el-icon><Search /></el-icon></template>
|
||||
</el-input>
|
||||
<button class="notification-button" type="button" aria-label="查看系统通知" @click="showNotifications">
|
||||
<el-icon><Bell /></el-icon>
|
||||
<span class="notification-dot" aria-hidden="true"></span>
|
||||
</button>
|
||||
<el-dropdown>
|
||||
<span class="user-info">
|
||||
<el-avatar :size="36">{{ (operator?.name || '工')[0] }}</el-avatar>
|
||||
<span class="user-copy">
|
||||
<strong>{{ operator?.name || '工作人员' }}</strong>
|
||||
<small>运营人员</small>
|
||||
</span>
|
||||
<el-icon><ArrowDown /></el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="handleLogout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main class="main-content"><router-view v-slot="{Component}"><keep-alive><component :is="Component"/></keep-alive></router-view></el-main>
|
||||
|
||||
<el-main class="main-content">
|
||||
<router-view v-slot="{ Component }">
|
||||
<keep-alive><component :is="Component" /></keep-alive>
|
||||
</router-view>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref,computed} from 'vue'
|
||||
import {useRoute,useRouter} from 'vue-router'
|
||||
import {DataBoard,DocumentChecked,User,OfficeBuilding,Setting,Calendar,Warning,ChatDotRound,TrendCharts,Document,Service,Location,Memo,Promotion,Reading,Connection,CircleCheck,Fold,Expand,ArrowDown} from '@element-plus/icons-vue'
|
||||
import {useAuthStore} from '@/stores/auth'
|
||||
const route=useRoute();const router=useRouter();const authStore=useAuthStore();const isCollapse=ref(false)
|
||||
const activeMenu=computed(()=>route.path);const currentTitle=computed(()=>(route.meta?.title as string)||'页面');const operator=computed(()=>authStore.operator)
|
||||
function hasPerm(permission:string){return (authStore.permissions||[]).includes(permission)}
|
||||
function showGroup(perms:string[]){return perms.some(hasPerm)}
|
||||
function handleLogout(){authStore.logout();router.push('/login')}
|
||||
import { computed, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import {
|
||||
ArrowDown,
|
||||
Bell,
|
||||
Calendar,
|
||||
ChatDotRound,
|
||||
CircleCheck,
|
||||
Connection,
|
||||
DataBoard,
|
||||
Document,
|
||||
DocumentChecked,
|
||||
Expand,
|
||||
Fold,
|
||||
Location,
|
||||
Memo,
|
||||
OfficeBuilding,
|
||||
Promotion,
|
||||
Reading,
|
||||
Search,
|
||||
Service,
|
||||
Setting,
|
||||
TrendCharts,
|
||||
User,
|
||||
Warning,
|
||||
} from '@element-plus/icons-vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const authStore = useAuthStore()
|
||||
const isCollapse = ref(false)
|
||||
const globalSearch = ref('')
|
||||
|
||||
const activeMenu = computed(() => route.path === '/users/detail' ? '/users' : route.path)
|
||||
const currentTitle = computed(() => (route.meta?.title as string) || '页面')
|
||||
const operator = computed(() => authStore.operator)
|
||||
|
||||
function hasPerm(permission: string) {
|
||||
return (authStore.permissions || []).includes(permission)
|
||||
}
|
||||
|
||||
function showGroup(permissions: string[]) {
|
||||
return permissions.some(hasPerm)
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
const query = globalSearch.value.trim()
|
||||
if (!query) return
|
||||
const destination = router.getRoutes().find((item) => {
|
||||
const title = String(item.meta?.title || '')
|
||||
const permissions = (item.meta?.permissions as string[] | undefined) || []
|
||||
return item.path !== '/login' && title.includes(query) && permissions.every(hasPerm)
|
||||
})
|
||||
if (!destination) {
|
||||
ElMessage.info('没有找到可访问的相关页面')
|
||||
return
|
||||
}
|
||||
router.push(destination.path)
|
||||
globalSearch.value = ''
|
||||
}
|
||||
|
||||
function showNotifications() {
|
||||
ElMessage.info('当前没有新的系统通知')
|
||||
}
|
||||
|
||||
function handleLogout() {
|
||||
authStore.logout()
|
||||
router.push('/login')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.main-layout{height:100vh;width:100%}.sidebar{display:flex;flex-direction:column;background:#FFFCFA;border-right:1px solid var(--color-border-light);transition:width .2s ease;overflow:hidden}.brand{height:92px;padding:20px 18px;display:flex;align-items:center;gap:12px;border-bottom:1px solid var(--color-border-light)}.brand.compact{justify-content:center;padding:18px 10px}.brand-symbol{width:42px;height:42px;flex:none;display:grid;place-items:center;border-radius:14px;background:linear-gradient(145deg,var(--color-primary),#EF8A7B);color:#fff;font-size:19px;font-weight:700;box-shadow:0 8px 18px rgba(233,107,107,.2)}.brand-copy{display:flex;flex-direction:column;white-space:nowrap}.brand-copy strong{font-size:17px;letter-spacing:1px}.brand-copy span{margin-top:3px;font-size:11px;color:var(--color-text-tertiary)}.menu-scroll{flex:1}.sidebar-menu{border:0;background:transparent;padding:12px 10px}.sidebar-menu :deep(.el-menu-item){height:44px;margin:3px 0;border-radius:10px;color:var(--color-text-secondary)}.sidebar-menu :deep(.el-menu-item:hover){background:var(--color-primary-lighter);color:var(--color-primary)}.sidebar-menu :deep(.el-menu-item.is-active){background:var(--color-primary-light);color:var(--color-primary);font-weight:600}.sidebar-menu :deep(.el-menu-item-group__title){padding:18px 12px 5px!important;color:#AAA09A;font-size:11px;letter-spacing:1px}.collapse-control{height:52px;margin:10px;border:0;border-top:1px solid var(--color-border-light);background:transparent;color:var(--color-text-tertiary);display:flex;align-items:center;justify-content:center;gap:8px;cursor:pointer}.workspace{min-width:0}.header{height:var(--header-height);padding:0 24px;background:rgba(255,255,255,.94);border-bottom:1px solid var(--color-border-light);display:flex;align-items:center;justify-content:space-between}.context-kicker{font-size:10px;color:var(--color-primary);margin-bottom:4px;letter-spacing:1px}.header-right,.user-info{display:flex;align-items:center}.header-right{gap:24px}.service-state{font-size:12px;color:var(--color-success)}.service-state i{display:inline-block;width:7px;height:7px;margin-right:6px;border-radius:50%;background:var(--color-success)}.user-info{gap:9px;cursor:pointer}.user-info .el-avatar{background:var(--color-primary);color:#fff}.user-info span{display:flex;flex-direction:column}.user-info strong{font-size:13px}.user-info small{font-size:11px;color:var(--color-text-tertiary);margin-top:2px}.main-content{background:var(--color-bg-page);padding:0;overflow:auto}
|
||||
@media(max-width:900px){.sidebar{width:72px!important}.brand-copy,.collapse-control span,.sidebar-menu :deep(.el-menu-item-group__title){display:none}.brand{justify-content:center}.header{padding:0 16px}.service-state{display:none}}
|
||||
</style>
|
||||
.main-layout {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
color: var(--admin-sidebar-text);
|
||||
background: var(--admin-sidebar-bg);
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.06);
|
||||
transition: width 0.2s ease;
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
height: 92px;
|
||||
padding: 20px 18px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.brand.compact {
|
||||
justify-content: center;
|
||||
padding: 18px 10px;
|
||||
}
|
||||
|
||||
.brand-mark {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
flex: none;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.brand-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.brand-copy strong {
|
||||
color: #FFFFFF;
|
||||
font-size: 18px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.brand-copy span {
|
||||
margin-top: 4px;
|
||||
color: var(--admin-sidebar-muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.menu-scroll {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
padding: 12px 10px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-menu-item) {
|
||||
height: 42px;
|
||||
margin: 3px 0;
|
||||
color: var(--admin-sidebar-text);
|
||||
border-radius: 9px;
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-menu-item:hover) {
|
||||
color: #FFFFFF;
|
||||
background: var(--admin-sidebar-surface);
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-menu-item.is-active) {
|
||||
color: #FFFFFF;
|
||||
font-weight: 600;
|
||||
background: var(--admin-primary);
|
||||
}
|
||||
|
||||
.sidebar-menu :deep(.el-menu-item-group__title) {
|
||||
padding: 18px 12px 5px !important;
|
||||
overflow: hidden;
|
||||
color: var(--admin-sidebar-muted);
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.5px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.collapse-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
height: 52px;
|
||||
margin: 10px;
|
||||
color: var(--admin-sidebar-muted);
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.collapse-control:hover {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.workspace {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: var(--header-height);
|
||||
padding: 0 24px;
|
||||
background: var(--admin-header-bg);
|
||||
border-bottom: 1px solid var(--color-border-light);
|
||||
}
|
||||
|
||||
.page-context {
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.context-kicker {
|
||||
margin-bottom: 4px;
|
||||
color: var(--admin-primary);
|
||||
font-size: 10px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.header-tools,
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-tools {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.global-search {
|
||||
width: 260px;
|
||||
}
|
||||
|
||||
.global-search :deep(.el-input__wrapper) {
|
||||
background: #F5F6F7;
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 0 1px #E8EAED;
|
||||
}
|
||||
|
||||
.notification-button {
|
||||
position: relative;
|
||||
display: grid;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
background: #FFFFFF;
|
||||
border: 1px solid var(--color-border-light);
|
||||
border-radius: 10px;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.notification-dot {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
background: var(--admin-primary);
|
||||
border: 2px solid #FFFFFF;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
gap: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.user-info .el-avatar {
|
||||
color: #FFFFFF;
|
||||
background: var(--admin-primary);
|
||||
}
|
||||
|
||||
.user-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.user-copy strong {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.user-copy small {
|
||||
margin-top: 2px;
|
||||
color: var(--color-text-tertiary);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 0;
|
||||
overflow: auto;
|
||||
background: var(--admin-page-bg);
|
||||
}
|
||||
|
||||
@media (max-width: 1000px) {
|
||||
.sidebar {
|
||||
width: 72px !important;
|
||||
}
|
||||
|
||||
.brand-copy,
|
||||
.collapse-control span,
|
||||
.sidebar-menu :deep(.el-menu-item-group__title) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.brand {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.header {
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.page-context,
|
||||
.global-search,
|
||||
.user-copy {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
:root {
|
||||
--color-primary: #E96B6B;
|
||||
--color-primary-hover: #D95F5F;
|
||||
--admin-sidebar-bg: #172733;
|
||||
--admin-sidebar-surface: #213542;
|
||||
--admin-sidebar-text: #D9E1E6;
|
||||
--admin-sidebar-muted: #8FA1AC;
|
||||
--admin-page-bg: #F7F7F5;
|
||||
--admin-primary: #EE666B;
|
||||
--admin-primary-hover: #D9545A;
|
||||
--admin-card-radius: 14px;
|
||||
--admin-header-bg: #FFFFFF;
|
||||
--admin-soft-pink: #FFF0F1;
|
||||
--admin-soft-blue: #EEF5FF;
|
||||
--admin-soft-green: #EDF8F1;
|
||||
--admin-soft-purple: #F4EFFF;
|
||||
--color-primary: var(--admin-primary);
|
||||
--color-primary-hover: var(--admin-primary-hover);
|
||||
--color-primary-light: #FFF3F2;
|
||||
--color-primary-lighter: #FFF8F7;
|
||||
--color-success: #2E9B68;
|
||||
@@ -12,13 +25,13 @@
|
||||
--color-text-tertiary: #888888;
|
||||
--color-bg-primary: #FFFFFF;
|
||||
--color-bg-secondary: #FFF8F7;
|
||||
--color-bg-page: #FAFAF8;
|
||||
--color-bg-page: var(--admin-page-bg);
|
||||
--color-border: #E8E5E2;
|
||||
--color-border-light: #F0EDE9;
|
||||
--sidebar-width: 220px;
|
||||
--header-height: 64px;
|
||||
--border-radius-sm: 8px;
|
||||
--border-radius-md: 12px;
|
||||
--border-radius-md: var(--admin-card-radius);
|
||||
--border-radius-lg: 16px;
|
||||
--shadow-card: 0 8px 24px rgba(75, 55, 46, 0.06);
|
||||
--el-color-primary: var(--color-primary);
|
||||
@@ -34,6 +47,13 @@ html, body, #app {
|
||||
background-color: var(--color-bg-page);
|
||||
}
|
||||
body { min-width: 1100px; }
|
||||
button:focus-visible,
|
||||
a:focus-visible,
|
||||
input:focus-visible,
|
||||
[tabindex]:focus-visible {
|
||||
outline: 3px solid rgba(238, 102, 107, 0.32);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.el-button--primary {
|
||||
--el-button-bg-color: var(--color-primary);
|
||||
--el-button-border-color: var(--color-primary);
|
||||
@@ -45,7 +65,7 @@ body { min-width: 1100px; }
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
.el-card { --el-card-border-radius: var(--border-radius-md); --el-card-border-color: var(--color-border-light); }
|
||||
.el-table { --el-table-header-bg-color: #FCFAF8; --el-table-border-color: var(--color-border-light); }
|
||||
.el-table { --el-table-header-bg-color: #FBFAF8; --el-table-border-color: var(--color-border-light); }
|
||||
.el-tag { border-radius: 999px; }
|
||||
.page-container { padding: 24px; }
|
||||
.page-shell { max-width: 1440px; margin: 0 auto; }
|
||||
@@ -64,4 +84,4 @@ body { min-width: 1100px; }
|
||||
.mb-lg { margin-bottom: 24px; }
|
||||
.flex-center { display: flex; align-items: center; justify-content: center; }
|
||||
@media (max-width: 1200px) { body { min-width: 0; } }
|
||||
@media (max-width: 900px) { .page-container { padding: 16px; } .page-heading { align-items: flex-start; flex-direction: column; } }
|
||||
@media (max-width: 900px) { .page-container { padding: 16px; } .page-heading { align-items: flex-start; flex-direction: column; } }
|
||||
|
||||
Reference in New Issue
Block a user