每周五更新

This commit is contained in:
2026-01-09 17:13:29 +08:00
parent a83485b4bc
commit cb0a715f4a
31 changed files with 8209 additions and 3074 deletions

View File

@@ -20,8 +20,13 @@
<!-- 右侧用户登录状态 -->
<div class="nav-right">
<!-- 加载中显示占位符防止闪烁 -->
<div v-if="isLoginStatusLoading" class="auth-loading">
<span class="loading-placeholder"></span>
</div>
<!-- 未登录显示注册/登录按钮 -->
<div v-if="!isLoggedIn" class="auth-buttons">
<div v-else-if="!isLoggedIn" class="auth-buttons">
<button class="auth-btn register-btn" @click="goToRegister">
注册
</button>
@@ -33,16 +38,16 @@
<!-- 已登录显示用户邮箱安全设置和退出按钮 -->
<div v-else class="user-info">
<span class="user-email">{{ userEmail }}</span>
<router-link
to="/account/security-settings"
<router-link
to="/account/security-settings"
class="security-link"
active-class="active"
>
安全设置
</router-link>
<el-button
type="text"
size="small"
<el-button
type="text"
size="small"
class="logout-btn"
@click="handleLogout"
>
@@ -71,6 +76,7 @@
import { readCart } from '../utils/cartManager'
import { mainNavigation, getBreadcrumb } from '../utils/navigation'
import { getGoodsListV2 } from '../api/shoppingCart'
import { getToken } from '../utils/request'
export default {
name: 'Header',
@@ -84,7 +90,9 @@ export default {
// 用户邮箱
userEmail: '',
// 登录状态(改为 data 属性,支持响应式更新)
isLoggedIn: false
isLoggedIn: false,
// 登录状态初始化中(防止闪烁)
isLoginStatusLoading: true
}
},
computed: {
@@ -99,9 +107,9 @@ export default {
}
},
watch: {},
mounted() {
// 初始化登录状态
this.updateLoginStatus()
async mounted() {
// 初始化登录状态(异步等待 token 初始化完成)
await this.updateLoginStatus()
this.loadCart()
// 监听购物车变化
window.addEventListener('storage', this.handleStorageChange)
@@ -169,13 +177,13 @@ export default {
console.error('加载购物车数量失败:', e)
}
},
handleStorageChange(event) {
async handleStorageChange(event) {
if (event.key === 'power_leasing_cart_v1') {
this.loadCart()
this.loadServerCartCount()
} else if (event.key === 'leasToken') {
// 当 token 变化时,更新登录状态
this.updateLoginStatus()
await this.updateLoginStatus()
// 如果 token 被清除,同时清除用户信息
if (!event.newValue) {
this.userEmail = ''
@@ -187,8 +195,10 @@ export default {
/**
* 处理登录状态变化事件
*/
handleLoginStatusChanged() {
this.updateLoginStatus()
async handleLoginStatusChanged() {
// 登录状态变化时不需要显示加载状态(已经有数据了)
this.isLoginStatusLoading = false
await this.updateLoginStatus()
// 如果未登录,清除用户信息
if (!this.isLoggedIn) {
this.userEmail = ''
@@ -198,13 +208,24 @@ export default {
},
/**
* 更新登录状态
* 使用 getToken() 从内存缓存或加密存储中读取 token
* 支持等待异步初始化完成
*/
updateLoginStatus() {
async updateLoginStatus() {
try {
const token = localStorage.getItem('leasToken')
// 使用 getToken(true) 等待 token 初始化完成(如果还在初始化中)
const token = await getToken(true)
this.isLoggedIn = !!token && token !== 'null' && token !== 'undefined'
if (process.env.NODE_ENV === 'development') {
console.log('[Header] 登录状态更新:', this.isLoggedIn, token ? '有 token' : '无 token')
}
} catch (e) {
console.error('更新登录状态失败:', e)
this.isLoggedIn = false
} finally {
// 无论成功失败,都结束加载状态
this.isLoginStatusLoading = false
}
},
handleCartUpdated(event) {
@@ -253,28 +274,33 @@ export default {
* 退出登录
* 清除所有登录信息,跳转到登录页
*/
handleLogout() {
// 清除localStorage中的所有登录信息
localStorage.removeItem('leasToken')
async handleLogout() {
// 动态导入 clearToken 函数
const { clearToken } = await import('../utils/request')
// 清除加密存储的 token包括内存缓存
await clearToken()
// 清除其他登录信息
localStorage.removeItem('userInfo')
localStorage.removeItem('leasEmail')
localStorage.removeItem('userId')
localStorage.removeItem('username')
// 更新登录状态
this.updateLoginStatus()
// 清空购物车
this.user = null
this.cart = []
this.userEmail = ''
// 触发登录状态变化事件
window.dispatchEvent(new CustomEvent('login-status-changed'))
// 提示用户
this.$message.success('退出登录成功')
// 跳转到登录页
this.$router.push('/login')
},
@@ -409,6 +435,32 @@ export default {
gap: 12px;
}
/* 登录状态加载中占位符 */
.auth-loading {
display: flex;
align-items: center;
padding: 8px 20px;
}
.loading-placeholder {
display: inline-block;
width: 180px;
height: 32px;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading-shimmer 1.5s infinite;
border-radius: 6px;
}
@keyframes loading-shimmer {
0% {
background-position: 200% 0;
}
100% {
background-position: -200% 0;
}
}
.auth-btn {
padding: 8px 20px;
border-radius: 6px;