650c480416
部署开发环境 / deploy-dev (push) Failing after 14s
- 更新 AdminView.vue 组件结构,使用新的布局和导航设计 - 集成 Element Plus 图标组件,提升界面美观度 - 添加响应式设计支持,适配移动端设备 - 重构 HomeView.vue 组件,改进 Token 查询功能 - 实现自动刷新机制,每5秒更新 Token 信息 - 优化 TokenDetailView.vue 组件,增强数据管理功能 - 添加确认对话框,防止误删操作 - 在 App.vue 中引入全局 CSS 变量和主题系统 - 创建通用组件样式类,统一页面外观 - 优化数据加载逻辑,提升页面性能和用户体验
224 lines
4.0 KiB
Vue
224 lines
4.0 KiB
Vue
<script setup lang="ts">
|
|
import {ref, watch, computed} from 'vue'
|
|
import {useRoute, useRouter} from "vue-router"
|
|
import {useCounterStore} from "@/stores/counter.ts"
|
|
import {Edit, Delete, Clock, User, Document} from '@element-plus/icons-vue'
|
|
|
|
const router = useRouter()
|
|
const route = useRoute()
|
|
const store = useCounterStore()
|
|
|
|
const activeIndex = ref(route.name?.toString() || "TokenManage")
|
|
|
|
watch(route, (newRoute) => {
|
|
activeIndex.value = newRoute.name?.toString() || "TokenManage"
|
|
})
|
|
|
|
const handleSelect = (key: string) => {
|
|
router.push({name: key})
|
|
}
|
|
|
|
const menuItems = [
|
|
{key: 'TokenManage', label: '管理 Token', icon: Edit},
|
|
{key: 'TokenDetail', label: 'Token 详情', icon: Document},
|
|
]
|
|
|
|
const logout = () => {
|
|
store.isAdmin = false
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="admin-layout">
|
|
<header class="admin-header">
|
|
<div class="header-left">
|
|
<div class="logo">
|
|
<el-icon size="24">
|
|
<Edit/>
|
|
</el-icon>
|
|
<span class="logo-text">DYPID 管理后台</span>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="header-nav">
|
|
<div
|
|
v-for="item in menuItems"
|
|
:key="item.key"
|
|
class="nav-item"
|
|
:class="{ active: activeIndex === item.key }"
|
|
@click="handleSelect(item.key)"
|
|
>
|
|
<el-icon>
|
|
<component :is="item.icon"/>
|
|
</el-icon>
|
|
<span>{{ item.label }}</span>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="header-right">
|
|
<div v-if="store.isAdmin" class="admin-badge">
|
|
<el-icon>
|
|
<User/>
|
|
</el-icon>
|
|
<span>管理员</span>
|
|
</div>
|
|
<el-button
|
|
v-if="store.isAdmin"
|
|
type="danger"
|
|
plain
|
|
size="small"
|
|
@click="logout"
|
|
>
|
|
<el-icon>
|
|
<Delete/>
|
|
</el-icon>
|
|
退出
|
|
</el-button>
|
|
</div>
|
|
</header>
|
|
|
|
<main class="admin-main">
|
|
<router-view v-slot="{ Component }">
|
|
<transition name="fade" mode="out-in">
|
|
<component :is="Component"/>
|
|
</transition>
|
|
</router-view>
|
|
</main>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.admin-layout {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: var(--bg-page);
|
|
}
|
|
|
|
.admin-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 24px;
|
|
height: 60px;
|
|
background: var(--bg-header);
|
|
border-bottom: 1px solid var(--border-color);
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 100;
|
|
}
|
|
|
|
.header-left {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.logo {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
color: var(--primary-color);
|
|
font-weight: 600;
|
|
font-size: 18px;
|
|
}
|
|
|
|
.logo-text {
|
|
display: none;
|
|
}
|
|
|
|
@media (min-width: 768px) {
|
|
.logo-text {
|
|
display: inline;
|
|
}
|
|
}
|
|
|
|
.header-nav {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.nav-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 8px 16px;
|
|
border-radius: 8px;
|
|
cursor: pointer;
|
|
color: var(--text-regular);
|
|
font-size: 14px;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.nav-item:hover {
|
|
background: var(--bg-page);
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.nav-item.active {
|
|
background: var(--primary-color);
|
|
color: #fff;
|
|
}
|
|
|
|
.header-right {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
.admin-badge {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 6px 12px;
|
|
background: var(--danger-color);
|
|
color: #fff;
|
|
border-radius: 20px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.admin-main {
|
|
flex: 1;
|
|
padding: 24px 48px;
|
|
max-width: 100%;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.fade-enter-active,
|
|
.fade-leave-active {
|
|
transition: opacity 0.2s ease;
|
|
}
|
|
|
|
.fade-enter-from,
|
|
.fade-leave-to {
|
|
opacity: 0;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.admin-header {
|
|
padding: 0 16px;
|
|
flex-wrap: wrap;
|
|
height: auto;
|
|
padding: 12px 16px;
|
|
}
|
|
|
|
.header-nav {
|
|
order: 3;
|
|
width: 100%;
|
|
margin-top: 12px;
|
|
overflow-x: auto;
|
|
}
|
|
|
|
.nav-item {
|
|
padding: 8px 12px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.nav-item span {
|
|
display: none;
|
|
}
|
|
|
|
.admin-main {
|
|
padding: 16px;
|
|
}
|
|
}
|
|
</style> |