feat: add admin UI frontend and complete backend APIs
Some checks failed
continuous-integration/drone/push Build is failing

- Add Vue 3 frontend with Element Plus
- Implement login, dashboard, tenant management
- Add app configuration, logs viewer, stats pages
- Add user management for admins
- Update Drone CI to build and deploy frontend
- Frontend ports: 3001 (test), 4001 (prod)
This commit is contained in:
111
2026-01-23 15:48:50 +08:00
parent daa8125c58
commit b89d5ddee9
31 changed files with 3115 additions and 8 deletions

View File

@@ -0,0 +1,105 @@
<script setup>
import { computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
import { ElMessageBox } from 'element-plus'
const router = useRouter()
const route = useRoute()
const authStore = useAuthStore()
// 菜单项
const menuItems = computed(() => {
const items = [
{ path: '/dashboard', title: '仪表盘', icon: 'Odometer' },
{ path: '/tenants', title: '租户管理', icon: 'OfficeBuilding' },
{ path: '/app-config', title: '应用配置', icon: 'Setting' },
{ path: '/stats', title: '统计分析', icon: 'TrendCharts' },
{ path: '/logs', title: '日志查看', icon: 'Document' }
]
// 管理员才能看到用户管理
if (authStore.isAdmin) {
items.push({ path: '/users', title: '用户管理', icon: 'User' })
}
return items
})
const activeMenu = computed(() => route.path)
function handleMenuSelect(path) {
router.push(path)
}
function handleLogout() {
ElMessageBox.confirm('确定要退出登录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
authStore.logout()
router.push('/login')
})
}
</script>
<template>
<div class="layout">
<!-- 侧边栏 -->
<aside class="sidebar">
<div class="logo">
<el-icon><Platform /></el-icon>
<span style="margin-left: 8px">平台管理</span>
</div>
<el-menu
:default-active="activeMenu"
background-color="transparent"
text-color="rgba(255,255,255,0.7)"
active-text-color="#fff"
@select="handleMenuSelect"
>
<el-menu-item v-for="item in menuItems" :key="item.path" :index="item.path">
<el-icon><component :is="item.icon" /></el-icon>
<span>{{ item.title }}</span>
</el-menu-item>
</el-menu>
</aside>
<!-- 主内容区 -->
<div class="main-container">
<!-- 顶部栏 -->
<header class="header">
<div class="breadcrumb">
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
<el-breadcrumb-item v-if="route.meta.title">{{ route.meta.title }}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="user-info">
<span class="username">{{ authStore.user?.nickname || authStore.user?.username }}</span>
<el-dropdown trigger="click">
<el-avatar :size="32">
{{ (authStore.user?.nickname || authStore.user?.username || 'U')[0].toUpperCase() }}
</el-avatar>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handleLogout">
<el-icon><SwitchButton /></el-icon>
退出登录
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</header>
<!-- 内容区 -->
<main class="main-content">
<router-view />
</main>
</div>
</div>
</template>