feat(App): 添加页面加载状态显示

添加了isLoading响应式变量来控制页面加载状态,
在API请求过程中显示加载动画,并在请求完成(成功或失败)
后隐藏加载状态。同时优化了代码结构,将原来的
链式赋值改为单独赋值语句,提高了代码可读性。
This commit is contained in:
2026-03-27 01:48:25 +08:00
parent e2a08ba5f1
commit 79d035c852
2 changed files with 98 additions and 53 deletions

View File

@@ -4,6 +4,7 @@ import { onMounted } from '@vue/runtime-core';
import Account from './components/Account.vue';
const isLogin = ref(false);
const isLoading = ref(true);
const userName = ref('');
const email = ref('');
const activeNav = ref('profile');
@@ -46,12 +47,18 @@ function BearerVerify() {
}).then(res => {
res.json().then(
(data) => {
;(isLogin.value = true), (userName.value = data.UserName), (email.value = data.Email)
isLogin.value = true;
userName.value = data.UserName;
email.value = data.Email;
isLoading.value = false;
}
)
}).catch(() => {
isLoading.value = false;
})
} else {
isLogin.value = false;
isLoading.value = false;
}
}
@@ -71,61 +78,69 @@ function setActiveNav(name) {
</script>
<template>
<div class="TopBar">
<div class="logo">
<div class="logo-icon">A</div>
<span>账户中心</span>
</div>
<div class="user-section">
<div class="user-info" v-if="isLogin">
<div class="user-avatar">{{ userName.charAt(0).toUpperCase() }}</div>
<span>{{ userName }}</span>
<!-- 加载状态 -->
<div v-if="isLoading" class="loading-container">
<div class="loading-spinner"></div>
<p class="loading-text">加载中...</p>
</div>
<template v-else>
<div class="TopBar">
<div class="logo">
<div class="logo-icon">A</div>
<span>账户中心</span>
</div>
<button v-if="!isLogin" class="login-btn" @click="Login()">
登录
</button>
<button v-else class="logout-btn" @click="Login()">
登出
</button>
</div>
</div>
<div class="Notice">
<span class="Notice-icon"></span>
<span>提示修改密码请登出后使用忘记密码功能</span>
</div>
<div v-if="isLogin" class="main-container">
<div class="LeftBar">
<div class="nav-title">导航菜单</div>
<div class="nav-list">
<RouterLink :to="{name: 'profile'}" @click="setActiveNav('profile')">
<div class="nav-item" :class="{ active: activeNav === 'profile' }">
<div class="nav-icon">👤</div>
<span>个人资料</span>
</div>
</RouterLink>
<RouterLink :to="{name: 'passkey'}" @click="setActiveNav('passkey')">
<div class="nav-item" :class="{ active: activeNav === 'passkey' }">
<div class="nav-icon">🔑</div>
<span>通行密钥</span>
</div>
</RouterLink>
<div class="user-section">
<div class="user-info" v-if="isLogin">
<div class="user-avatar">{{ userName.charAt(0).toUpperCase() }}</div>
<span>{{ userName }}</span>
</div>
<button v-if="!isLogin" class="login-btn" @click="Login()">
登录
</button>
<button v-else class="logout-btn" @click="Login()">
登出
</button>
</div>
</div>
<div class="content-area">
<RouterView :UserName="userName" :Email="email"/>
<div class="Notice">
<span class="Notice-icon"></span>
<span>提示修改密码请登出后使用忘记密码功能</span>
</div>
</div>
<div v-else class="login-prompt">
<div class="login-card">
<div class="login-icon">🔐</div>
<h2 class="login-title">欢迎使用账户中心</h2>
<p class="login-desc">请登录以管理您的账户信息和安全设置</p>
<button class="login-btn" @click="Login()">
立即登录
</button>
<div v-if="isLogin" class="main-container">
<div class="LeftBar">
<div class="nav-title">导航菜单</div>
<div class="nav-list">
<RouterLink :to="{name: 'profile'}" @click="setActiveNav('profile')">
<div class="nav-item" :class="{ active: activeNav === 'profile' }">
<div class="nav-icon">👤</div>
<span>个人资料</span>
</div>
</RouterLink>
<RouterLink :to="{name: 'passkey'}" @click="setActiveNav('passkey')">
<div class="nav-item" :class="{ active: activeNav === 'passkey' }">
<div class="nav-icon">🔑</div>
<span>通行密钥</span>
</div>
</RouterLink>
</div>
</div>
<div class="content-area">
<RouterView :UserName="userName" :Email="email"/>
</div>
</div>
</div>
<div v-else class="login-prompt">
<div class="login-card">
<div class="login-icon">🔐</div>
<h2 class="login-title">欢迎使用账户中心</h2>
<p class="login-desc">请登录以管理您的账户信息和安全设置</p>
<button class="login-btn" @click="Login()">
立即登录
</button>
</div>
</div>
</template>
</template>

View File

@@ -386,4 +386,34 @@ a {
.user-info {
display: none;
}
}
/* 加载状态 */
.loading-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
gap: 16px;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid var(--border-color);
border-top-color: var(--primary-color);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
.loading-text {
color: var(--text-secondary);
font-size: 14px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}