【改进】主页动态化

This commit is contained in:
2025-10-31 17:39:24 +08:00
parent ad98033faa
commit 74034ed26a
2 changed files with 211 additions and 281 deletions

View File

@@ -141,96 +141,9 @@ body {
/* 内容区域 */
.content-wrapper {
padding: 25px;
padding: 0;
}
/* 欢迎卡片 */
.welcome-card {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
color: white;
border-radius: 16px;
padding: 35px;
margin-bottom: 25px;
box-shadow: 0 10px 30px rgba(91, 95, 222, 0.2);
position: relative;
overflow: hidden;
}
.welcome-card::before {
content: '';
position: absolute;
width: 250px;
height: 250px;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
top: -80px;
right: -80px;
}
.welcome-card h2 {
font-size: 26px;
font-weight: 700;
margin-bottom: 10px;
position: relative;
z-index: 1;
}
.welcome-card p {
font-size: 15px;
opacity: 0.95;
position: relative;
z-index: 1;
}
/* 统计卡片 */
.stat-card {
background: white;
border-radius: 12px;
padding: 25px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
transition: all 0.3s;
border: 1px solid #E5E7EB;
}
.stat-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
.stat-card i {
font-size: 40px;
opacity: 0.9;
margin-bottom: 12px;
}
.stat-card h3 {
font-size: 30px;
font-weight: 700;
margin: 12px 0 6px;
color: #1F2937;
}
.stat-card p {
color: #6B7280;
font-size: 13px;
margin: 0;
}
.stat-card.primary i {
color: var(--primary-color);
}
.stat-card.success i {
color: var(--success-color);
}
.stat-card.warning i {
color: var(--warning-color);
}
.stat-card.info i {
color: var(--info-color);
}
/* 页面标题 */
.page-title {
@@ -252,6 +165,24 @@ body {
padding: 25px;
}
/* iframe样式 */
.page-iframe {
width: 100%;
height: calc(100vh - 72px); /* 减去导航栏高度 */
border: none;
transition: opacity 0.3s ease;
border-radius: 8px;
}
/* 加载状态 */
.loading-state {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
/* 响应式 */
@media (max-width: 768px) {
.sidebar {
@@ -278,6 +209,9 @@ body {
}
.content-wrapper {
padding: 20px;
padding: 0;
min-height: calc(100vh - 72px);
}
}

View File

@@ -27,34 +27,26 @@
<div class="sidebar-menu">
<ul class="nav flex-column">
<li class="nav-item">
<a :class="['nav-link', currentPage === 'dashboard' ? 'active' : '']"
<a :class="['nav-link', currentUrl === '/admin/dashboard' ? 'active' : '']"
href="#"
@click.prevent="currentPage = 'dashboard'">
@click.prevent="changeMenu('/admin/dashboard')">
<i class="bi bi-speedometer2"></i>
仪表盘
</a>
</li>
<li class="nav-item">
<a :class="['nav-link', currentPage === 'users' ? 'active' : '']"
<li class="nav-item" v-for="(item, index) in menus" :key="index">
<a :class="['nav-link', currentUrl === item.menuUrl ? 'active' : '']"
href="#"
@click.prevent="currentPage = 'users'">
<i class="bi bi-people-fill"></i>
用户管理
</a>
</li>
<li class="nav-item">
<a :class="['nav-link', currentPage === 'settings' ? 'active' : '']"
href="#"
@click.prevent="currentPage = 'settings'">
<i class="bi bi-gear-fill"></i>
系统设置
@click.prevent="changeMenu(item.menuUrl)">
<i :class="item.menuIcon"></i>
{{ item.menuName }}
</a>
</li>
</ul>
</div>
<div class="sidebar-footer">
<button class="btn-logout" @click="handleLogout">
<button class="btn-logout" data-bs-toggle="modal" data-bs-target="#exitModal">
<i class="bi bi-box-arrow-right me-2"></i>
退出登录
</button>
@@ -67,7 +59,7 @@
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container-fluid">
<span class="navbar-brand">欢迎回来</span>
<div class="user-info">
<div class="user-info" style="cursor: pointer">
<i class="bi bi-person-circle"></i>
<span>{{ userInfo.realName || userInfo.username }}</span>
</div>
@@ -76,62 +68,35 @@
<!-- 内容区域 -->
<div class="content-wrapper">
<!-- 仪表盘 -->
<div v-if="currentPage === 'dashboard'">
<div class="welcome-card">
<h2>
<i class="bi bi-emoji-smile"></i>
你好,{{ userInfo.realName || userInfo.username }}
</h2>
<p class="mb-0 mt-2">欢迎使用 CoreWing 后台管理系统</p>
</div>
<div class="row">
<div class="col-md-4 mb-4">
<div class="stat-card primary">
<i class="bi bi-people-fill"></i>
<h3>1,234</h3>
<p>总用户数</p>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="stat-card success">
<i class="bi bi-file-earmark-text-fill"></i>
<h3>567</h3>
<p>文档数量</p>
</div>
</div>
<div class="col-md-4 mb-4">
<div class="stat-card warning">
<i class="bi bi-graph-up"></i>
<h3>89%</h3>
<p>系统负载</p>
</div>
</div>
</div>
</div>
<!-- 用户管理 -->
<div v-if="currentPage === 'users'">
<h3 class="page-title">用户管理</h3>
<div class="card">
<div class="card-body">
<p>用户管理功能开发中...</p>
</div>
</div>
</div>
<!-- 系统设置 -->
<div v-if="currentPage === 'settings'">
<h3 class="page-title">系统设置</h3>
<div class="card">
<div class="card-body">
<p>系统设置功能开发中...</p>
</div>
</div>
</div>
<!-- iframe容器 - 用于加载菜单对应的URL页面 -->
<iframe
v-if="currentUrl"
class="page-iframe"
:src="currentUrl"
@load="handleIframeLoad"
title="页面内容"
></iframe>
</div>
</main>
<div class="modal fade" id="exitModal" tabindex="-1" aria-labelledby="exitModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">系统提示</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
您确认退出系统吗?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" @click="handleLogout">退出</button>
</div>
</div>
</div>
</div>
</div>
<!-- Vue 3 -->
@@ -158,7 +123,9 @@
realName: '',
userId: ''
},
currentPage: 'dashboard'
menus: [],
currentUrl: '/admin/dashboard', // 当前加载的URL
isLoading: false // 加载状态
}
},
methods: {
@@ -167,11 +134,12 @@
this.userInfo.username = localStorage.getItem('username') || '';
this.userInfo.realName = localStorage.getItem('realName') || '';
this.userInfo.userId = localStorage.getItem('userId') || '';
const token = localStorage.getItem("token");
if (token) {
try {
const response = await request.get('/sys/user/info');
if (response.data.code === 200) {
const user = response.data.data;
if (response.code === 200) {
const user = response.data;
this.userInfo.username = user.username;
this.userInfo.realName = user.realName || user.username;
this.userInfo.userId = user.id;
@@ -183,7 +151,6 @@
},
async handleLogout() {
if (confirm('确定要退出登录吗?')) {
try {
await request.get('/sys/user/logout');
} catch (error) {
@@ -194,7 +161,6 @@
// 跳转到登录页
window.location.href = '/admin/login.html';
}
}
},
checkLogin() {
@@ -207,9 +173,34 @@
async initMenu() {
const response = await request.get('/sys/menu/initSysMenu');
if(response.data.code === 200) {
console.log(response.data.code);
if (response.code === 200) {
this.menus = response.data;
}
this.initCurrentUrlFromHash();
},
// 从浏览器hash初始化当前URL
initCurrentUrlFromHash() {
const hash = window.location.hash.slice(1); // 获取 # 后的内容(如 #/admin/user 取 /admin/user
// 如果hash存在且是有效菜单URL用hash否则用默认的仪表盘
const validMenuUrls = this.menus.map(item => item.menuUrl);
if (hash && (validMenuUrls.includes(hash) || hash === '/admin/dashboard')) {
this.currentUrl = hash;
} else {
this.currentUrl = '/admin/dashboard';
// 同步默认值到地址栏
window.location.hash = this.currentUrl;
}
},
// 切换菜单时更新URL和状态
changeMenu(menuUrl) {
this.currentUrl = menuUrl;
this.isLoading = true;
window.location.hash = menuUrl;
},
handleIframeLoad() {
console.log('加载完成');
this.isLoading = false;
}
},
mounted() {
@@ -219,6 +210,11 @@
this.initMenu();
// 加载用户信息
this.loadUserInfo();
this.isLoading = true;
// 监听浏览器hash变化刷新/前进后退时触发)
window.addEventListener('hashchange', () => {
this.initCurrentUrlFromHash();
});
}
}).mount('#app');
</script>