feat: scaffold mediai admin
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<div class="admin-shell" :class="{ collapsed: appStore.collapsed, dark: appStore.darkMode }">
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="brand-mark">M</div>
|
||||
<div class="brand-copy">
|
||||
<strong>MediAI</strong>
|
||||
<span>医疗AI平台</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-scrollbar class="sidebar-scroll">
|
||||
<nav class="nav-list">
|
||||
<section v-for="section in visibleSections" :key="section.title" class="nav-section">
|
||||
<div class="nav-section-title">{{ section.title }}</div>
|
||||
<router-link v-for="item in section.items" :key="item.page" :to="getPagePath(item.page)" class="nav-item">
|
||||
<el-icon><component :is="item.icon" /></el-icon>
|
||||
<span>{{ item.title }}</span>
|
||||
</router-link>
|
||||
</section>
|
||||
</nav>
|
||||
</el-scrollbar>
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<div class="user-card">
|
||||
<el-avatar :size="38">{{ appStore.user.avatarText }}</el-avatar>
|
||||
<div class="user-meta">
|
||||
<strong>{{ appStore.user.name }}</strong>
|
||||
<span>{{ appStore.roleLabel }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-select v-model="role" class="role-select" size="small" @change="handleRoleChange">
|
||||
<el-option v-for="item in roleOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<section class="main-panel">
|
||||
<header class="top-header">
|
||||
<div class="header-left">
|
||||
<el-tooltip content="折叠菜单" placement="bottom">
|
||||
<el-button :icon="Fold" circle @click="appStore.collapsed = !appStore.collapsed" />
|
||||
</el-tooltip>
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item>首页</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>{{ pageTitle }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
|
||||
<div class="header-right">
|
||||
<el-input v-model="keyword" class="global-search" :prefix-icon="Search" clearable placeholder="全局搜索..." />
|
||||
<el-badge :value="3" class="header-badge">
|
||||
<el-button :icon="Bell" circle />
|
||||
</el-badge>
|
||||
<el-tooltip content="切换主题" placement="bottom">
|
||||
<el-button :icon="appStore.darkMode ? Sunny : Moon" circle @click="appStore.darkMode = !appStore.darkMode" />
|
||||
</el-tooltip>
|
||||
<el-button :icon="QuestionFilled" circle />
|
||||
<div class="header-user">
|
||||
<strong>{{ appStore.user.name }}</strong>
|
||||
<span>{{ appStore.roleLabel }}</span>
|
||||
</div>
|
||||
<el-dropdown @command="handleCommand">
|
||||
<el-button :icon="ArrowDown" circle />
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item command="profile">个人中心</el-dropdown-item>
|
||||
<el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="content-area">
|
||||
<router-view />
|
||||
</main>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ArrowDown, Bell, Fold, Moon, QuestionFilled, Search, Sunny } from '@element-plus/icons-vue'
|
||||
import { roleOptions } from '@/mock/dashboard'
|
||||
import { getFirstPage, getPagePath, pageTitles, roleMenus } from '@/mock/navigation'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import type { RoleKey } from '@/types'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const appStore = useAppStore()
|
||||
const keyword = ref('')
|
||||
const role = computed({
|
||||
get: () => appStore.user.role,
|
||||
set: value => appStore.switchRole(value)
|
||||
})
|
||||
|
||||
const visibleSections = computed(() => roleMenus[appStore.user.role])
|
||||
const pageTitle = computed(() => {
|
||||
const page = route.params.page
|
||||
if (typeof page === 'string') {
|
||||
return pageTitles[page] || '业务模块'
|
||||
}
|
||||
return String(route.meta.title || '数据驾驶舱')
|
||||
})
|
||||
|
||||
function handleRoleChange(value: RoleKey) {
|
||||
appStore.switchRole(value)
|
||||
router.push(getPagePath(getFirstPage(value)))
|
||||
}
|
||||
|
||||
function handleCommand(command: string) {
|
||||
if (command === 'logout') {
|
||||
appStore.logout()
|
||||
router.push('/login')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user