228 lines
8.8 KiB
HTML
228 lines
8.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>售后服务平台</title>
|
|
<link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
height: 100vh;
|
|
}
|
|
.layout-container {
|
|
height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.header {
|
|
background-color: #001529;
|
|
color: #fff;
|
|
padding: 0 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
height: 60px;
|
|
}
|
|
.logo {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
}
|
|
.main-container {
|
|
flex: 1;
|
|
display: flex;
|
|
overflow: hidden;
|
|
}
|
|
.sidebar {
|
|
width: 220px;
|
|
height: 100%;
|
|
background-color: #001529;
|
|
transition: width 0.3s;
|
|
}
|
|
.sidebar.collapsed {
|
|
width: 64px;
|
|
}
|
|
.content {
|
|
flex: 1;
|
|
padding: 20px;
|
|
overflow-y: auto;
|
|
background-color: #f5f7fa;
|
|
}
|
|
.user-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: #fff;
|
|
}
|
|
.el-menu {
|
|
border-right: none !important;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<div class="layout-container">
|
|
<header class="header">
|
|
<div class="logo">
|
|
<el-button type="text" style="color: #fff" @click="toggleSidebar">
|
|
<el-icon><Fold v-if="!isCollapse" /><Expand v-else /></el-icon>
|
|
</el-button>
|
|
<span v-show="!isCollapse">售后服务平台</span>
|
|
</div>
|
|
<div class="user-info">
|
|
<el-dropdown @command="handleCommand">
|
|
<span class="el-dropdown-link">
|
|
{{ userInfo.userName }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
|
|
</span>
|
|
<template #dropdown>
|
|
<el-dropdown-menu>
|
|
<el-dropdown-item command="profile">个人信息</el-dropdown-item>
|
|
<el-dropdown-item command="password">修改密码</el-dropdown-item>
|
|
<el-dropdown-item divided command="logout">退出登录</el-dropdown-item>
|
|
</el-dropdown-menu>
|
|
</template>
|
|
</el-dropdown>
|
|
</div>
|
|
</header>
|
|
<div class="main-container">
|
|
<div class="sidebar" :class="{ collapsed: isCollapse }">
|
|
<el-menu
|
|
:default-active="activeMenu"
|
|
:collapse="isCollapse"
|
|
background-color="#001529"
|
|
text-color="#fff"
|
|
active-text-color="#409EFF"
|
|
:unique-opened="true"
|
|
:collapse-transition="false"
|
|
@select="handleSelect">
|
|
<template v-for="menu in menus" :key="menu.menuId">
|
|
<el-sub-menu v-if="menu.children && menu.children.length" :index="menu.menuId.toString()">
|
|
<template #title>
|
|
<el-icon><component :is="menu.icon || 'Menu'" /></el-icon>
|
|
<span>{{ menu.menuName }}</span>
|
|
</template>
|
|
<el-menu-item
|
|
v-for="child in menu.children"
|
|
:key="child.menuId"
|
|
:index="child.menuId.toString()">
|
|
<el-icon><component :is="child.icon || 'Menu'" /></el-icon>
|
|
<template #title>{{ child.menuName }}</template>
|
|
</el-menu-item>
|
|
</el-sub-menu>
|
|
<el-menu-item v-else :index="menu.menuId.toString()">
|
|
<el-icon><component :is="menu.icon || 'Menu'" /></el-icon>
|
|
<template #title>{{ menu.menuName }}</template>
|
|
</el-menu-item>
|
|
</template>
|
|
</el-menu>
|
|
</div>
|
|
<main class="content">
|
|
<iframe :src="currentUrl" frameborder="0" style="width: 100%; height: 100%;"></iframe>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
|
|
<script src="https://unpkg.com/element-plus"></script>
|
|
<script src="https://unpkg.com/@element-plus/icons-vue"></script>
|
|
<script>
|
|
const { createApp, ref, onMounted } = Vue
|
|
|
|
const app = createApp({
|
|
setup() {
|
|
const isCollapse = ref(false)
|
|
const activeMenu = ref('')
|
|
const currentUrl = ref('')
|
|
const menus = ref([])
|
|
const userInfo = ref({
|
|
userName: ''
|
|
})
|
|
|
|
const toggleSidebar = () => {
|
|
isCollapse.value = !isCollapse.value
|
|
}
|
|
|
|
const handleSelect = (index) => {
|
|
const findMenu = (menus, id) => {
|
|
for (const menu of menus) {
|
|
if (menu.menuId.toString() === id) return menu
|
|
if (menu.children) {
|
|
const found = findMenu(menu.children, id)
|
|
if (found) return found
|
|
}
|
|
}
|
|
return null
|
|
}
|
|
const menu = findMenu(menus.value, index)
|
|
if (menu && menu.url) {
|
|
currentUrl.value = menu.url
|
|
}
|
|
}
|
|
|
|
const handleCommand = (command) => {
|
|
switch (command) {
|
|
case 'logout':
|
|
fetch('/api/logout', { method: 'POST' })
|
|
.then(() => window.location.href = '/login')
|
|
break
|
|
case 'profile':
|
|
currentUrl.value = '/profile'
|
|
break
|
|
case 'password':
|
|
currentUrl.value = '/password'
|
|
break
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
// 获取用户信息和菜单数据
|
|
Promise.all([
|
|
fetch('/api/user/info').then(res => res.json()),
|
|
fetch('/api/user/menus').then(res => res.json())
|
|
])
|
|
.then(([userRes, menuRes]) => {
|
|
if (userRes.code === 0) {
|
|
userInfo.value = userRes.data
|
|
}
|
|
if (menuRes.code === 0) {
|
|
menus.value = menuRes.data
|
|
if (menus.value.length > 0) {
|
|
const firstMenu = menus.value[0]
|
|
activeMenu.value = firstMenu.menuId.toString()
|
|
if (firstMenu.url) {
|
|
currentUrl.value = firstMenu.url
|
|
} else if (firstMenu.children && firstMenu.children.length > 0) {
|
|
currentUrl.value = firstMenu.children[0].url
|
|
activeMenu.value = firstMenu.children[0].menuId.toString()
|
|
}
|
|
}
|
|
}
|
|
})
|
|
.catch(error => {
|
|
ElementPlus.ElMessage.error('获取用户信息失败')
|
|
})
|
|
})
|
|
|
|
return {
|
|
isCollapse,
|
|
activeMenu,
|
|
currentUrl,
|
|
menus,
|
|
userInfo,
|
|
toggleSidebar,
|
|
handleSelect,
|
|
handleCommand
|
|
}
|
|
}
|
|
})
|
|
|
|
app.use(ElementPlus)
|
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|
app.component(key, component)
|
|
}
|
|
app.mount('#app')
|
|
</script>
|
|
</body>
|
|
</html> |