2025-09-26 16:40:38 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<div class="account-page">
|
|
|
|
|
|
<!-- <div class="account-header">
|
|
|
|
|
|
<h1 class="title">个人中心</h1>
|
|
|
|
|
|
</div> -->
|
|
|
|
|
|
|
|
|
|
|
|
<div class="account-layout">
|
|
|
|
|
|
<!-- 左侧导航 -->
|
|
|
|
|
|
<aside class="sidebar">
|
|
|
|
|
|
<nav class="side-nav">
|
|
|
|
|
|
<div class="user-info-card" role="region" v-show="userEmail" aria-label="用户信息" tabindex="0">
|
|
|
|
|
|
<div class="user-meta">
|
|
|
|
|
|
<div class="user-email" :title="userEmail || '未登录'">{{ userEmail || '未登录' }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-10-20 10:15:13 +08:00
|
|
|
|
<div class="user-role" role="group" aria-label="导航分组切换">
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="role-button"
|
|
|
|
|
|
:class="{ active: activeRole === 'buyer' }"
|
|
|
|
|
|
@click="handleClickRole('buyer')"
|
|
|
|
|
|
@keydown.enter.prevent="handleClickRole('buyer')"
|
|
|
|
|
|
@keydown.space.prevent="handleClickRole('buyer')"
|
|
|
|
|
|
:aria-pressed="activeRole === 'buyer'"
|
|
|
|
|
|
tabindex="0"
|
|
|
|
|
|
>买家相关</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="role-button"
|
|
|
|
|
|
:class="{ active: activeRole === 'seller' }"
|
|
|
|
|
|
@click="handleClickRole('seller')"
|
|
|
|
|
|
@keydown.enter.prevent="handleClickRole('seller')"
|
|
|
|
|
|
@keydown.space.prevent="handleClickRole('seller')"
|
|
|
|
|
|
:aria-pressed="activeRole === 'seller'"
|
|
|
|
|
|
tabindex="0"
|
|
|
|
|
|
>卖家相关</button>
|
2025-09-26 16:40:38 +08:00
|
|
|
|
</div>
|
2025-10-20 10:15:13 +08:00
|
|
|
|
|
2025-09-26 16:40:38 +08:00
|
|
|
|
<router-link
|
2025-10-20 10:15:13 +08:00
|
|
|
|
v-for="item in displayedLinks"
|
|
|
|
|
|
:key="item.to"
|
|
|
|
|
|
:to="item.to"
|
2025-09-26 16:40:38 +08:00
|
|
|
|
class="side-link"
|
|
|
|
|
|
active-class="active"
|
2025-10-20 10:15:13 +08:00
|
|
|
|
>{{ item.label }}</router-link>
|
2025-09-26 16:40:38 +08:00
|
|
|
|
</nav>
|
|
|
|
|
|
</aside>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 右侧内容 -->
|
|
|
|
|
|
<section class="content">
|
|
|
|
|
|
<router-view />
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: "AccountPage",
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
activeIndex: '1',
|
|
|
|
|
|
userEmail: '',
|
2025-10-20 10:15:13 +08:00
|
|
|
|
// 导航分组:buyer(买家) / seller(卖家);默认卖家
|
|
|
|
|
|
activeRole: 'seller',
|
|
|
|
|
|
// 买家侧导航
|
|
|
|
|
|
buyerLinks: [
|
|
|
|
|
|
{ label: '我的钱包', to: '/account/wallet' },
|
|
|
|
|
|
{ label: '已购商品', to: '/account/purchased' },
|
|
|
|
|
|
{ label: '订单列表', to: '/account/orders' },
|
|
|
|
|
|
// { label: '充值记录', to: '/account/rechargeRecord' },
|
|
|
|
|
|
// { label: '提现记录', to: '/account/withdrawalHistory' },
|
|
|
|
|
|
{ label: '资金流水', to: '/account/funds-flow' },
|
|
|
|
|
|
],
|
|
|
|
|
|
// 卖家侧导航
|
|
|
|
|
|
sellerLinks: [
|
|
|
|
|
|
// { label: '我的钱包', to: '/account/wallet' },
|
|
|
|
|
|
{ label: '我的店铺', to: '/account/shops' },
|
|
|
|
|
|
{ label: '商品列表', to: '/account/products' },
|
|
|
|
|
|
{ label: '已售出订单', to: '/account/seller-orders' },
|
|
|
|
|
|
{ label: '收款记录', to: '/account/receipt-record' },
|
|
|
|
|
|
|
|
|
|
|
|
],
|
2025-09-26 16:40:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 计算用户邮箱首字母(用于头像)
|
|
|
|
|
|
* @returns {string}
|
|
|
|
|
|
*/
|
|
|
|
|
|
userInitial() {
|
|
|
|
|
|
const email = (this.userEmail || '').trim()
|
|
|
|
|
|
return email ? email[0].toUpperCase() : '?'
|
|
|
|
|
|
},
|
2025-10-20 10:15:13 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 根据当前分组返回展示的导航链接
|
|
|
|
|
|
* @returns {{label:string,to:string}[]}
|
|
|
|
|
|
*/
|
|
|
|
|
|
displayedLinks() {
|
|
|
|
|
|
return this.activeRole === 'buyer' ? this.buyerLinks : this.sellerLinks
|
|
|
|
|
|
},
|
2025-09-26 16:40:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
mounted() {
|
|
|
|
|
|
const getVal = (key) => {
|
|
|
|
|
|
const raw = localStorage.getItem(key)
|
|
|
|
|
|
if (raw == null) return null
|
|
|
|
|
|
try { return JSON.parse(raw) } catch (e) { return raw }
|
|
|
|
|
|
}
|
|
|
|
|
|
const val = getVal('userName') || getVal('userEmail') || ''
|
|
|
|
|
|
this.userEmail = typeof val === 'string' ? val : String(val)
|
2025-10-20 10:15:13 +08:00
|
|
|
|
// 恢复上次选择的导航分组(如无则默认 seller)
|
|
|
|
|
|
const savedRole = getVal('accountActiveRole')
|
|
|
|
|
|
if (savedRole === 'buyer' || savedRole === 'seller') {
|
|
|
|
|
|
this.activeRole = savedRole
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 点击切换导航分组
|
|
|
|
|
|
* @param {('buyer'|'seller')} role 要切换到的分组
|
|
|
|
|
|
* @returns {void}
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleClickRole(role) {
|
|
|
|
|
|
if (role !== 'buyer' && role !== 'seller') return
|
|
|
|
|
|
this.activeRole = role
|
|
|
|
|
|
try { localStorage.setItem('accountActiveRole', JSON.stringify(role)) } catch (e) {}
|
|
|
|
|
|
},
|
2025-09-26 16:40:38 +08:00
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.account-page {
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.account-header {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
/* border: 1px solid #eee; */
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
padding-left: 3vw;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
.title {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.account-layout {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: 220px 1fr;
|
|
|
|
|
|
gap: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.sidebar {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid #eee;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
min-height: 80vh;
|
|
|
|
|
|
}
|
|
|
|
|
|
.side-nav {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
}
|
2025-10-20 10:15:13 +08:00
|
|
|
|
/* 分组切换按钮样式 */
|
|
|
|
|
|
.user-role {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.role-button {
|
|
|
|
|
|
appearance: none;
|
|
|
|
|
|
background: #f6f8fa;
|
|
|
|
|
|
border: 1px solid #e5e7eb;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
padding: 6px 10px;
|
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.role-button.active {
|
|
|
|
|
|
background: #42b983;
|
|
|
|
|
|
border-color: #42b983;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.role-button:focus {
|
|
|
|
|
|
outline: 2px solid #42b98333;
|
|
|
|
|
|
outline-offset: 2px;
|
|
|
|
|
|
}
|
2025-09-26 16:40:38 +08:00
|
|
|
|
/* 用户信息卡片:置于导航最前,展示邮箱与首字母头像 */
|
|
|
|
|
|
.user-info-card {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 12px;
|
|
|
|
|
|
background: #f8fafc;
|
|
|
|
|
|
border: 1px solid #eee;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
margin-bottom: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.avatar {
|
|
|
|
|
|
width: 36px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
background: linear-gradient(135deg, #42b983, #67c23a);
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.user-email {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.side-link {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
padding: 10px 12px;
|
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
transition: background 0.2s;
|
|
|
|
|
|
}
|
|
|
|
|
|
.side-link:hover {
|
|
|
|
|
|
background: #f6f8fa;
|
|
|
|
|
|
}
|
|
|
|
|
|
.side-link.active {
|
|
|
|
|
|
background: #42b983;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid #eee;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
min-height: 420px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.account-layout {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|