Files
danyang-match/admin-web/src/layouts/MainLayout.vue
T

138 lines
6.6 KiB
Vue
Raw Normal View History

2026-09-09 22:05:00 +08:00
<template>
<el-container class="main-layout">
<el-aside :width="isCollapse ? '64px' : '220px'" class="sidebar">
<div class="logo">
<span v-if="!isCollapse">丹阳公益婚恋</span>
<span v-else>丹阳</span>
</div>
<el-menu :default-active="activeMenu" :collapse="isCollapse" :router="true"
background-color="#304156" text-color="#bfcbd9" active-text-color="#E96B6B" class="sidebar-menu">
<el-menu-item index="/dashboard" :disabled="false">
<el-icon><DataBoard /></el-icon><template #title>工作台</template>
</el-menu-item>
<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 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('activity.review_registration')" index="/activities/interests">
<el-icon><Calendar /></el-icon><template #title>活动互选</template>
</el-menu-item>
<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><ChatDotRound /></el-icon><template #title>申诉管理</template>
</el-menu-item>
<el-menu-item v-if="hasPerm('analytics.view')" index="/analytics">
<el-icon><TrendCharts /></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>
<!-- V1.1 新增菜单 -->
<el-menu-item v-if="hasPerm('banner.view')" index="/banner">
2026-09-09 22:05:00 +08:00
<el-icon><Promotion /></el-icon><template #title>Banner管理</template>
</el-menu-item>
<el-menu-item v-if="hasPerm('content.view')" index="/content">
2026-09-09 22:05:00 +08:00
<el-icon><FolderOpened /></el-icon><template #title>内容管理</template>
</el-menu-item>
<el-menu-item v-if="hasPerm('service_location.view')" index="/service-station">
2026-09-09 22:05:00 +08:00
<el-icon><Location /></el-icon><template #title>善缘服务站</template>
</el-menu-item>
<el-menu-item v-if="hasPerm('service_appointment.view')" index="/service-appointment">
2026-09-09 22:05:00 +08:00
<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 v-if="hasPerm('counseling.service.view')" index="/counseling">
2026-09-09 22:05:00 +08:00
<el-icon><ChatDotRound /></el-icon><template #title>婚恋咨询</template>
</el-menu-item>
<el-menu-item v-if="hasPerm('referral.manage')" index="/referral">
<el-icon><Bell /></el-icon><template #title>转介管理</template>
</el-menu-item>
</el-menu>
</el-aside>
<el-container>
<el-header class="header">
<div class="header-left">
<el-icon class="collapse-btn" @click="isCollapse = !isCollapse">
<Fold v-if="!isCollapse" /><Expand v-else />
</el-icon>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>{{ currentTitle }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="header-right">
<el-dropdown>
<span class="user-info">
<el-avatar :size="32" style="background:#E96B6B">{{ (operator?.name || '管')[0] }}</el-avatar>
<span class="user-name">{{ operator?.name || '工作人员' }}</span>
</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-container>
</el-container>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Fold, Expand, DataBoard, DocumentChecked, User, OfficeBuilding, Setting, Calendar, Warning, ChatDotRound, TrendCharts, Document, Service, Location, Memo, Promotion, FolderOpened, Bell } 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): boolean {
return (authStore.permissions || []).includes(permission)
}
function handleLogout() {
authStore.logout()
router.push('/login')
}
</script>
<style scoped>
.main-layout { height: 100vh; width: 100%; }
.sidebar { background-color: #304156; transition: width 0.3s; overflow: hidden; }
.logo { height: 60px; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 16px; font-weight: bold; border-bottom: 1px solid #3a4a5e; }
.sidebar-menu { border-right: none; }
.header { background: #fff; border-bottom: 1px solid #e4e7ed; display: flex; align-items: center; justify-content: space-between; padding: 0 20px; }
.header-left { display: flex; align-items: center; gap: 16px; }
.collapse-btn { cursor: pointer; font-size: 20px; color: #666; }
.collapse-btn:hover { color: #E96B6B; }
.header-right { display: flex; align-items: center; gap: 16px; }
.user-info { display: flex; align-items: center; gap: 8px; cursor: pointer; }
.user-name { font-size: 14px; color: #333; }
.main-content { background: #f0f2f5; padding: 20px; overflow: auto; }
</style>