feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
<template>
|
||||
<a-layout class="layout">
|
||||
<a-layout-sider
|
||||
v-model:collapsed="collapsed"
|
||||
:trigger="null"
|
||||
collapsible
|
||||
:width="240"
|
||||
:collapsed-width="64"
|
||||
class="layout-sider"
|
||||
>
|
||||
<div class="logo">
|
||||
<template v-if="!collapsed">
|
||||
<span>管理系统</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="logo-icon">M</span>
|
||||
</template>
|
||||
</div>
|
||||
<a-menu
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
v-model:openKeys="openKeys"
|
||||
mode="inline"
|
||||
theme="dark"
|
||||
:inline-collapsed="collapsed"
|
||||
>
|
||||
<a-menu-item key="dashboard" @click="handleMenuClick('/dashboard')">
|
||||
<template #icon>
|
||||
<DashboardOutlined />
|
||||
</template>
|
||||
<span>仪表盘</span>
|
||||
</a-menu-item>
|
||||
<a-sub-menu key="system">
|
||||
<template #icon>
|
||||
<SettingOutlined />
|
||||
</template>
|
||||
<template #title>系统管理</template>
|
||||
<a-menu-item key="users" @click="handleMenuClick('/users')">
|
||||
<template #icon>
|
||||
<UserOutlined />
|
||||
</template>
|
||||
<span>用户管理</span>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="roles" @click="handleMenuClick('/roles')">
|
||||
<template #icon>
|
||||
<LockOutlined />
|
||||
</template>
|
||||
<span>角色管理</span>
|
||||
</a-menu-item>
|
||||
<a-menu-item key="menus" @click="handleMenuClick('/menus')">
|
||||
<template #icon>
|
||||
<MenuOutlined />
|
||||
</template>
|
||||
<span>菜单管理</span>
|
||||
</a-menu-item>
|
||||
</a-sub-menu>
|
||||
</a-menu>
|
||||
</a-layout-sider>
|
||||
<a-layout>
|
||||
<a-layout-header class="header">
|
||||
<div class="header-left">
|
||||
<MenuUnfoldOutlined
|
||||
v-if="collapsed"
|
||||
class="trigger"
|
||||
@click="toggleSidebar"
|
||||
/>
|
||||
<MenuFoldOutlined
|
||||
v-else
|
||||
class="trigger"
|
||||
@click="toggleSidebar"
|
||||
/>
|
||||
<a-breadcrumb class="breadcrumb">
|
||||
<a-breadcrumb-item>首页</a-breadcrumb-item>
|
||||
<a-breadcrumb-item v-for="item in breadcrumbItems" :key="item">
|
||||
{{ item }}
|
||||
</a-breadcrumb-item>
|
||||
</a-breadcrumb>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<a-space>
|
||||
<a-button type="text" :icon="h(BellOutlined)" />
|
||||
<a-dropdown>
|
||||
<a class="ant-dropdown-link" @click.prevent>
|
||||
<UserOutlined />
|
||||
<span class="user-name">{{ user?.username || '用户' }}</span>
|
||||
<DownOutlined />
|
||||
</a>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="profile">
|
||||
<UserOutlined />
|
||||
个人中心
|
||||
</a-menu-item>
|
||||
<a-menu-item key="settings">
|
||||
<SettingOutlined />
|
||||
设置
|
||||
</a-menu-item>
|
||||
<a-menu-divider />
|
||||
<a-menu-item key="logout" @click="handleLogout">
|
||||
<LogoutOutlined />
|
||||
退出登录
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-space>
|
||||
</div>
|
||||
</a-layout-header>
|
||||
<a-layout-content class="content">
|
||||
<div class="content-wrapper">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="fade" mode="out-in">
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
</div>
|
||||
</a-layout-content>
|
||||
</a-layout>
|
||||
</a-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, h } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { useAuthStore, useAppStore } from '../stores'
|
||||
import {
|
||||
DashboardOutlined,
|
||||
SettingOutlined,
|
||||
UserOutlined,
|
||||
LockOutlined,
|
||||
MenuOutlined,
|
||||
MenuUnfoldOutlined,
|
||||
MenuFoldOutlined,
|
||||
DownOutlined,
|
||||
LogoutOutlined,
|
||||
BellOutlined
|
||||
} from '@ant-design/icons-vue'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const authStore = useAuthStore()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const collapsed = computed(() => appStore.sidebarCollapsed)
|
||||
const selectedKeys = ref<string[]>(['dashboard'])
|
||||
const openKeys = ref<string[]>(['system'])
|
||||
const user = computed(() => authStore.user)
|
||||
|
||||
const breadcrumbItems = computed(() => {
|
||||
const pathMap: Record<string, string> = {
|
||||
'/dashboard': '仪表盘',
|
||||
'/users': '用户管理',
|
||||
'/roles': '角色管理',
|
||||
'/menus': '菜单管理'
|
||||
}
|
||||
const items = []
|
||||
const currentPath = route.path
|
||||
if (pathMap[currentPath]) {
|
||||
items.push(pathMap[currentPath])
|
||||
}
|
||||
return items
|
||||
})
|
||||
|
||||
function toggleSidebar() {
|
||||
appStore.toggleSidebar()
|
||||
}
|
||||
|
||||
function handleMenuClick(path: string) {
|
||||
router.push(path)
|
||||
}
|
||||
|
||||
async function handleLogout() {
|
||||
try {
|
||||
await authStore.logout()
|
||||
message.success('退出登录成功')
|
||||
router.push('/login')
|
||||
} catch (error) {
|
||||
message.error('退出登录失败')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.layout {
|
||||
min-height: 100vh;
|
||||
|
||||
.logo {
|
||||
height: 32px;
|
||||
margin: 16px;
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header {
|
||||
background: white;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.header-left {
|
||||
.trigger {
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-right {
|
||||
.ant-dropdown-link {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 16px;
|
||||
padding: 24px;
|
||||
background: white;
|
||||
min-height: 280px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user