Files
webs/power_leasing/src/views/account/index.vue

329 lines
9.0 KiB
Vue
Raw Normal View History

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-10-31 14:09:58 +08:00
:class="['side-link', isActiveLink(item.to) ? '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 }
}
2025-10-31 14:09:58 +08:00
const val =getVal('leasEmail') || ''
2025-09-26 16:40:38 +08:00
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') {
2025-10-31 14:09:58 +08:00
this.activeRole = savedRole
2025-10-20 10:15:13 +08:00
}
2025-10-31 14:09:58 +08:00
// 根据当前路由自动匹配分组,确保左侧导航高亮正确
this.setActiveRoleByRoute()
2025-10-20 10:15:13 +08:00
},
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-10-31 14:09:58 +08:00
// 切换分组后,立即跳转到该分组的第一个导航页面
try {
const firstPath = role === 'buyer'
? (this.buyerLinks && this.buyerLinks[0] && this.buyerLinks[0].to)
: (this.sellerLinks && this.sellerLinks[0] && this.sellerLinks[0].to)
if (firstPath && this.$route && this.$route.path !== firstPath) {
this.$router.push(firstPath)
}
} catch (e) { /* noop */ }
2025-10-20 10:15:13 +08:00
},
2025-10-31 14:09:58 +08:00
/**
* 根据当前路由自动选择导航分组保证进入我的店铺等卖家页面时左侧高亮正确
*/
setActiveRoleByRoute() {
const path = (this.$route && this.$route.path) || ''
// 买家前缀优先匹配,确保“已购详情”等页面归属买家侧
const buyerPrefixes = [
'/account/wallet',
'/account/purchased',
'/account/purchased-detail',
'/account/orders',
'/account/funds-flow'
]
const sellerPrefixes = [
'/account/shops',
'/account/shop-new',
'/account/product-new',
'/account/products',
'/account/product-detail',
'/account/product-machine-add',
'/account/seller-orders',
'/account/order-detail',
'/account/receipt-record',
'/account/shop-config'
]
const shouldBuyer = buyerPrefixes.some(p => path.indexOf(p) === 0)
const shouldSeller = sellerPrefixes.some(p => path.indexOf(p) === 0)
const role = shouldBuyer ? 'buyer' : (shouldSeller ? 'seller' : this.activeRole)
if (this.activeRole !== role) {
this.activeRole = role
try { localStorage.setItem('accountActiveRole', JSON.stringify(role)) } catch (e) {}
}
},
/**
* 判断左侧导航项是否高亮
* - 普通路径完全匹配
* - 已售出订单需同时匹配详情页 /account/order-detail/:id
*/
isActiveLink(pathLike) {
const current = (this.$route && this.$route.path) || ''
if (!pathLike) return false
// 列表-详情联动高亮映射
const map = {
'/account/seller-orders': ['/account/seller-orders', '/account/order-detail'],
'/account/products': ['/account/products', '/account/product-detail'],
'/account/purchased': ['/account/purchased', '/account/purchased-detail']
}
const prefixes = map[pathLike]
if (Array.isArray(prefixes)) {
return prefixes.some(p => current.indexOf(p) === 0)
}
return current.indexOf(pathLike) === 0
}
2025-09-26 16:40:38 +08:00
},
2025-10-31 14:09:58 +08:00
watch: {
'$route.path': {
immediate: true,
handler() {
this.setActiveRoleByRoute()
}
}
}
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;
2025-10-31 14:09:58 +08:00
margin-top: 18px;
2025-10-20 10:15:13 +08:00
}
.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>