<template>
|
<section class="my-center-page">
|
<!-- 头部:返回 + 个人中心 + 右侧客服 -->
|
|
<assets-head :title="$t('个人中心')" :back-func="() => router.push('/')" />
|
|
<!-- 未登录:欢迎 + 登录注册 -->
|
<template v-if="!(userStore.userInfo && userStore.userInfo.token)">
|
<div class="guest-wrap px-8 mt-4">
|
<h1 class="guest-title">{{ $t("welcome") }} {{ $title }}!</h1>
|
<p class="guest-desc">{{ $t("全球最大的区块链资产平台") }}</p>
|
<div class="guest-btns">
|
<van-button class="flex-1" @click="onRoute('/register')">{{ $t("register") }}</van-button>
|
<van-button class="flex-1" type="primary" @click="onRoute('/login')">{{ $t("login") }}</van-button>
|
</div>
|
</div>
|
</template>
|
|
<!-- 已登录:深色用户卡 + 合并菜单列表 -->
|
<template v-else>
|
<!-- 用户信息卡(深色) + user-row 下方弹出框 -->
|
<div class="user-card">
|
<div class="user-card-inner">
|
<div class="user-avatar flex items-center justify-center">
|
<img src="@/assets/image/login_logo.png" alt="avatar" />
|
</div>
|
<div class="user-info">
|
<div class="user-row" @click.stop="showAccountPopup = !showAccountPopup">
|
<span class="user-account">{{ maskedAccount }}</span>
|
<van-icon name="arrow-down" class="user-arrow" />
|
|
<!-- 当前为模拟账户时显示「真实账户」,否则显示「模拟账户」 -->
|
<div v-show="showAccountPopup" class="account-option-pill" @click="isSimulation ? onSwitchToReal() : onSwitchToSimulation()">
|
{{ isSimulation ? ($t('真实账户') || '真实账户') : ($t('模拟账户') || '模拟账户') }}
|
</div>
|
</div>
|
<div class="user-uid">UID: {{ userStore.userInfo.usercode || '--' }}</div>
|
</div>
|
<div class="user-vip">VIP 1</div>
|
</div>
|
</div>
|
|
<!-- 合并列表:快捷入口 + 通用 + 更多(单列白卡片) -->
|
<div class="menu-list">
|
<div v-for="(item, index) in mergedMenuList" :key="index" class="menu-item" @click="onMenuItemClick(item)">
|
<img class="menu-icon" :src="item.icon" alt="" />
|
<span class="menu-title">{{ item.title }}</span>
|
<span v-if="item.rightText" class="menu-right-text">{{ item.rightText }}</span>
|
<van-icon name="arrow" class="menu-arrow" />
|
</div>
|
</div>
|
|
<!-- 退出登录 -->
|
<div class="logout-wrap">
|
<span class="logout-btn" @click="loginOut">{{ $t("loginOut") }}</span>
|
</div>
|
</template>
|
</section>
|
</template>
|
|
<script setup>
|
import assetsHead from '@/components/Transform/assets-head/index.vue'
|
import { ref, computed, onMounted } from 'vue'
|
import { useRouter } from 'vue-router'
|
import { useI18n } from 'vue-i18n'
|
import { _getIdentify, _getKycHighLevel, _logOut, _switchAccount } from '@/service/user.api.js'
|
import { useUserStore } from '@/store/user'
|
import { _getUnreadMsg } from '@/service/im.api'
|
import { themeStore } from '@/store/theme'
|
import store from '@/store/store'
|
import userIcon1 from '@/assets/image/userCenter/user_1.png'
|
import userIcon2 from '@/assets/image/userCenter/user_2.png'
|
import userIcon3 from '@/assets/image/userCenter/user_3.png'
|
import userIcon4 from '@/assets/image/userCenter/user_4.png'
|
import userIcon5 from '@/assets/image/userCenter/user_5.png'
|
import userIcon6 from '@/assets/image/userCenter/user_6.png'
|
import userIcon7 from '@/assets/image/userCenter/user_7.png'
|
import userIcon8 from '@/assets/image/userCenter/user_8.png'
|
|
const { t, locale } = useI18n()
|
const router = useRouter()
|
const userStore = useUserStore()
|
const thStore = themeStore()
|
|
const status = ref(null)
|
const kycHighStatus = ref(null)
|
const unreadMsg = ref('')
|
const showAccountPopup = ref(false)
|
|
const REAL_ACCOUNT_BACKUP_KEY = 'REAL_ACCOUNT_BACKUP'
|
|
// 当前语言展示文案(与语言设置页一致:简体中文、繁体中文、English 等)
|
const languageLabel = computed(() => {
|
const map = {
|
'zh-CN': '简体中文',
|
'CN': '繁体中文',
|
'en': 'English',
|
'de': 'Deutsch',
|
'es': 'Español',
|
'fr': 'Français',
|
'Italy': 'Italiano',
|
'Japanese': '日本語',
|
'Korean': '한국어',
|
'pt': 'Português',
|
'vi': 'Tiếng Việt',
|
'gr': 'Ελληνικά',
|
'th': 'ไทย',
|
}
|
return map[locale.value] || map['zh-CN'] || '简体中文'
|
})
|
const themeLabel = computed(() => {
|
const theme = thStore.theme || 'white'
|
return theme === 'white' ? t('浅色模式') || '浅色模式' : t('深色模式') || '深色模式'
|
})
|
|
// accountType:1 为模拟账户
|
const isSimulation = computed(() => userStore.userInfo?.accountType === 1)
|
|
// 掩码账号:前几位 + ****
|
const maskedAccount = computed(() => {
|
const account = userStore.userInfo?.username || userStore.userInfo?.email || ''
|
if (!account) return '--'
|
if (account.includes('@')) {
|
const [name, domain] = account.split('@')
|
if (name.length <= 3) return name + '****@' + (domain || '')
|
return name.slice(0, 3) + '****@' + (domain || '')
|
}
|
if (account.length <= 4) return account + '****'
|
return account.slice(0, 3) + '****'
|
})
|
|
// 图标:静态导入以便打包后正确解析(动态 new URL 在生产构建中会失效)
|
const userIconUrls = [userIcon1, userIcon2, userIcon3, userIcon4, userIcon5, userIcon6, userIcon7, userIcon8]
|
const userIcon = (n) => userIconUrls[n - 1] || userIconUrls[7]
|
|
// 完整菜单;模拟账户(accountType===1)只保留语言切换
|
const mergedMenuList = computed(() => {
|
const list = [
|
{ title: t('authVerify'), path: '/certificationCenter', icon: userIcon(1), rightText: status.value != null ? statusText(status.value) : undefined },
|
{ title: t('账变记录'), path: '/cryptos/accountChange', icon: userIcon(2) },
|
{ title: t('信用分'), path: '/my/creditScore', icon: userIcon(4) },
|
{ title: t('邀请推广'), path: '/promote', icon: userIcon(5) },
|
{ title: t('安全'), path: '/safety', icon: userIcon(6) },
|
{ title: t('language'), path: '/language', icon: userIcon(7), rightText: languageLabel.value },
|
]
|
if (isSimulation.value) {
|
return list.filter((item) => item.path === '/language')
|
}
|
return list
|
})
|
|
function statusText(s) {
|
if (s === 0 || s === 3) return t('notCertified')
|
if (s === 1) return t('reviewing')
|
if (s === 2) return t('verified')
|
if (s === 3) return t('noPassView')
|
return ''
|
}
|
|
function onRoute(path) {
|
router.push(path)
|
}
|
|
function onMenuItemClick(item) {
|
if (item.path === '/theme') {
|
// 主题切换:无独立页则跳转语言页或弹窗,这里简单跳语言页或保持当前
|
router.push('/language')
|
return
|
}
|
router.push(item.path)
|
}
|
|
function loginOut() {
|
_logOut({ token: userStore.userInfo?.token }).then(() => {
|
userStore.userInfo = {}
|
store.state.user.userInfo = {}
|
router.push('/login')
|
})
|
}
|
|
// 切换为模拟账户:先保存真实账户信息与 token,再请求并替换
|
function onSwitchToSimulation() {
|
const current = userStore.userInfo
|
if (current && current.token && current.accountType !== 1) {
|
try {
|
localStorage.setItem(REAL_ACCOUNT_BACKUP_KEY, JSON.stringify({ ...current }))
|
} catch (e) {}
|
}
|
_switchAccount().then((data) => {
|
const info = data && typeof data === 'object' ? data : {}
|
const token = info.token != null ? info.token : (userStore.userInfo?.token || '')
|
const next = { ...userStore.userInfo, ...info, token }
|
userStore.userInfo = next
|
store.state.user.userInfo = next
|
showAccountPopup.value = false
|
})
|
}
|
|
// 当前为模拟账户时,点击「真实账户」:用本地保存的真实账户与 token 替换
|
function onSwitchToReal() {
|
try {
|
const raw = localStorage.getItem(REAL_ACCOUNT_BACKUP_KEY)
|
if (!raw) return
|
const backup = JSON.parse(raw)
|
if (backup && backup.token) {
|
userStore.userInfo = { ...backup }
|
store.state.user.userInfo = { ...backup }
|
showAccountPopup.value = false
|
}
|
} catch (e) {}
|
}
|
|
onMounted(() => {
|
if (userStore.userInfo?.token) {
|
getIdentify()
|
getKycHighLevel()
|
fetchUnread()
|
}
|
})
|
|
function getIdentify() {
|
_getIdentify().then((data) => { status.value = data?.status })
|
}
|
function getKycHighLevel() {
|
_getKycHighLevel().then((data) => { kycHighStatus.value = data?.status })
|
}
|
function fetchUnread() {
|
_getUnreadMsg().then((res) => { unreadMsg.value = (res * 1 > 0) ? res * 1 : '' })
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
@import '@/assets/css/variable.scss';
|
|
.my-center-page {
|
min-height: 100vh;
|
background: $main_background;
|
padding-bottom: calc(80px + constant(safe-area-inset-bottom));
|
padding-bottom: calc(80px + env(safe-area-inset-bottom));
|
}
|
|
.page-header {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
height: 5.5rem;
|
padding: 0 2rem;
|
background: #fff;
|
box-sizing: border-box;
|
|
.header-left {
|
width: 4rem;
|
height: 4rem;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
cursor: pointer;
|
}
|
|
.back-icon {
|
font-size: 2.2rem;
|
color: $text_color;
|
}
|
|
.header-title {
|
font-size: 3.2rem;
|
font-weight: 700;
|
color: $text_color;
|
margin: 0;
|
}
|
|
.header-right {
|
cursor: pointer;
|
color: $text_color;
|
}
|
}
|
|
.guest-wrap {
|
.guest-title {
|
font-size: 2.4rem;
|
font-weight: 700;
|
color: $text_color;
|
margin: 0 0 0.8rem;
|
}
|
|
.guest-desc {
|
color: $text_color1;
|
font-size: 2.6rem;
|
margin: 0 0 2rem;
|
}
|
|
.guest-btns {
|
display: flex;
|
gap: 1.2rem;
|
}
|
}
|
|
/* 用户信息卡(深色) */
|
.user-card {
|
margin: 2rem 2.4rem;
|
border-radius: 2rem;
|
overflow: visible;
|
background: linear-gradient(-89deg, #5f5f5f 0%, #000000 100%), linear-gradient(#000000, #000000);
|
box-shadow: 0 0.2rem 0.8rem rgba(0, 0, 0, 0.15);
|
position: relative;
|
}
|
|
.user-card-inner {
|
padding: 2.4rem 2rem;
|
display: flex;
|
align-items: center;
|
position: relative;
|
border-radius: inherit;
|
// overflow: hidden;
|
}
|
|
.user-avatar {
|
width: 7rem;
|
height: 7rem;
|
border-radius: 50%;
|
overflow: hidden;
|
background: $main_background;
|
flex-shrink: 0;
|
|
img {
|
width: 70%;
|
height: 70%;
|
object-fit: cover;
|
}
|
}
|
|
.user-info {
|
flex: 1;
|
margin-left: 2rem;
|
min-width: 0;
|
}
|
|
.user-row {
|
display: flex;
|
align-items: center;
|
gap: 0.4rem;
|
cursor: pointer;
|
position: relative;
|
|
.user-account {
|
font-size: 3.2rem;
|
font-weight: 600;
|
color: #fff;
|
}
|
|
.user-arrow {
|
font-size: 2.4rem;
|
color: rgba(255, 255, 255, 0.7);
|
}
|
}
|
|
.user-uid {
|
font-size: 2.6rem;
|
color: rgba(255, 255, 255, 0.75);
|
margin-top: 0.6rem;
|
}
|
|
.user-vip {
|
position: absolute;
|
top: 2rem;
|
right: 2rem;
|
font-size: 2.4rem;
|
font-weight: 600;
|
color: #f5c421;
|
}
|
|
/* 合并菜单列表(白卡片) */
|
.menu-list {
|
margin: 0 2.4rem;
|
}
|
|
.menu-item {
|
display: flex;
|
align-items: center;
|
padding: 2.2rem 2rem;
|
background: #fff;
|
border-radius: 2.2rem;
|
margin-bottom: 1.8rem;
|
box-shadow: 0rem 1.2rem 4rem 0rem rgba(0, 0, 0, 0.18);
|
cursor: pointer;
|
box-sizing: border-box;
|
|
&:last-of-type {
|
margin-bottom: 0;
|
}
|
}
|
|
.menu-icon {
|
width: 3rem;
|
height: 3rem;
|
margin-right: 1.6rem;
|
flex-shrink: 0;
|
object-fit: contain;
|
}
|
|
.menu-title {
|
flex: 1;
|
font-size: 2.2rem;
|
color: $text_color;
|
text-align: left;
|
}
|
|
.menu-right-text {
|
font-size: 2.2rem;
|
color: $text_color;
|
margin-right: 0.6rem;
|
}
|
|
.menu-arrow {
|
font-size: 2.8rem;
|
color: $text_color1;
|
}
|
|
/* user-row 下方弹出框(不用 van-popup) */
|
|
.account-option-pill {
|
position: absolute;
|
left: 0;
|
top: 4rem;
|
border: 1px solid $text_color;
|
border-radius: 1.5rem;
|
font-size: 2.8rem;
|
color: $text_color;
|
text-align: center;
|
background: $main_background;
|
padding: 1.5rem 2rem;
|
display: inline;
|
z-index: 10;
|
// width: 20rem;
|
// height:7rem;
|
}
|
|
.logout-wrap {
|
text-align: center;
|
padding: 3rem 2rem 2rem;
|
}
|
|
.logout-btn {
|
font-size: 3rem;
|
color: #f2495e;
|
cursor: pointer;
|
}
|
</style>
|