增加:组合资产和可用资产

This commit is contained in:
马丁 2026-07-07 22:35:36 +08:00
parent c088670028
commit 2bfd171e11
8 changed files with 79 additions and 10 deletions

View File

@ -192,7 +192,16 @@ async function onMenuClick(id: string) {
</template> </template>
<template v-else> <template v-else>
<v-btn class="balance-btn" variant="text" min-width="auto" padding="4 12" @click="$router.push('/wallet')"> <v-btn class="balance-btn" variant="text" min-width="auto" padding="4 12" @click="$router.push('/wallet')">
<span class="balance-text">${{ userStore.totalAssetValue }}</span> <div class="balance-group">
<div class="balance-item">
<span class="balance-label">{{ t('wallet.portfolio') }}</span>
<span class="balance-value">${{ userStore.totalAssetValue }}</span>
</div>
<div class="balance-item">
<span class="balance-label">{{ t('wallet.cash') }}</span>
<span class="balance-value">${{ userStore.availableAssetValue }}</span>
</div>
</div>
</v-btn> </v-btn>
<v-btn icon variant="text" class="avatar-btn" :aria-label="t('common.user')" <v-btn icon variant="text" class="avatar-btn" :aria-label="t('common.user')"
@click="$router.push('/profile')"> @click="$router.push('/profile')">
@ -399,9 +408,31 @@ async function onMenuClick(id: string) {
text-transform: none; text-transform: none;
} }
.balance-text { .balance-group {
display: flex;
align-items: stretch;
gap: 16px;
white-space: nowrap;
line-height: 1.1;
}
.balance-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
.balance-label {
font-size: 0.7rem;
color: rgba(0, 0, 0, 0.5);
font-weight: 500; font-weight: 500;
font-size: 0.95rem; }
.balance-value {
font-size: 1rem;
font-weight: 700;
color: #3a9b5d;
} }
.back-btn { .back-btn {
@ -435,6 +466,18 @@ async function onMenuClick(id: string) {
.brand-name { .brand-name {
font-size: 0.96rem; font-size: 0.96rem;
} }
.balance-group {
gap: 12px;
}
.balance-label {
font-size: 0.64rem;
}
.balance-value {
font-size: 0.9rem;
}
} }
/* 底部导航整条栏上方淡投影z-index 确保覆盖滚动条,显示在滚动条上层 */ /* 底部导航整条栏上方淡投影z-index 确保覆盖滚动条,显示在滚动条上层 */

View File

@ -235,6 +235,7 @@
"wallet": { "wallet": {
"availableAssets": "Available Assets", "availableAssets": "Available Assets",
"portfolio": "Portfolio", "portfolio": "Portfolio",
"cash": "Cash",
"today": "Today", "today": "Today",
"deposit": "Deposit", "deposit": "Deposit",
"withdraw": "Withdraw", "withdraw": "Withdraw",

View File

@ -235,6 +235,7 @@
"wallet": { "wallet": {
"availableAssets": "利用可能資産", "availableAssets": "利用可能資産",
"portfolio": "ポートフォリオ", "portfolio": "ポートフォリオ",
"cash": "現金",
"today": "今日", "today": "今日",
"deposit": "入金", "deposit": "入金",
"withdraw": "出金", "withdraw": "出金",

View File

@ -235,6 +235,7 @@
"wallet": { "wallet": {
"availableAssets": "사용 가능 자산", "availableAssets": "사용 가능 자산",
"portfolio": "포트폴리오", "portfolio": "포트폴리오",
"cash": "현금",
"today": "오늘", "today": "오늘",
"deposit": "입금", "deposit": "입금",
"withdraw": "출금", "withdraw": "출금",

View File

@ -235,6 +235,7 @@
"wallet": { "wallet": {
"availableAssets": "可用资产", "availableAssets": "可用资产",
"portfolio": "资产组合", "portfolio": "资产组合",
"cash": "现金",
"today": "今日", "today": "今日",
"deposit": "入金", "deposit": "入金",
"withdraw": "提现", "withdraw": "提现",

View File

@ -235,6 +235,7 @@
"wallet": { "wallet": {
"availableAssets": "可用資產", "availableAssets": "可用資產",
"portfolio": "資產組合", "portfolio": "資產組合",
"cash": "現金",
"today": "今日", "today": "今日",
"deposit": "入金", "deposit": "入金",
"withdraw": "提現", "withdraw": "提現",

View File

@ -21,8 +21,8 @@ app.use(router)
setHttpUnauthorizedHandler(() => { setHttpUnauthorizedHandler(() => {
const userStore = useUserStore(pinia) const userStore = useUserStore(pinia)
userStore.clearLocalSession() userStore.clearLocalSession()
if (router.currentRoute.value.name !== 'login') { if (router.currentRoute.value.name !== 'home') {
router.replace({ name: 'login' }) router.replace({ name: 'home' })
} }
}) })

View File

@ -85,12 +85,19 @@ export const useUserStore = defineStore('user', () => {
/** 钱包余额显示,如 "0.00",可从接口或 UserSocket 推送更新 */ /** 钱包余额显示,如 "0.00",可从接口或 UserSocket 推送更新 */
const balance = ref<string>('0.00') const balance = ref<string>('0.00')
/** 锁定余额显示,如 "0.00",可从接口或 UserSocket 推送更新 */
const lockedBalance = ref<string>('0.00')
const positionsValue = ref<number>(0) const positionsValue = ref<number>(0)
/** 总资产:余额 + 仓位当前价值 */ /** 可用资产:仅可用余额 */
const availableAssetValue = computed(() => balance.value)
/** 组合资产:可用 + 锁定 + 持仓价值 */
const totalAssetValue = computed(() => { const totalAssetValue = computed(() => {
const bal = parseFloat(balance.value) || 0 const bal = parseFloat(balance.value) || 0
return (bal + positionsValue.value).toFixed(2) const locked = parseFloat(lockedBalance.value) || 0
return (bal + locked + positionsValue.value).toFixed(2)
}) })
let userSdkRef: UserSdk | null = null let userSdkRef: UserSdk | null = null
@ -117,6 +124,10 @@ export const useUserStore = defineStore('user', () => {
if (avail != null) { if (avail != null) {
balance.value = formatUsdcBalance(String(avail)) balance.value = formatUsdcBalance(String(avail))
} }
const locked = (data as BalanceData & { locked?: string }).locked ?? data.frozen
if (locked != null) {
lockedBalance.value = formatUsdcBalance(String(locked))
}
}) })
sdk.onPositionUpdate((data) => { sdk.onPositionUpdate((data) => {
positionUpdateCallbacks.forEach((cb) => cb(data as PositionData & Record<string, unknown>)) positionUpdateCallbacks.forEach((cb) => cb(data as PositionData & Record<string, unknown>))
@ -205,7 +216,12 @@ export const useUserStore = defineStore('user', () => {
try { try {
const res = await getUsdcBalance(headers) const res = await getUsdcBalance(headers)
if (res.code === 0 && res.data) { if (res.code === 0 && res.data) {
balance.value = formatUsdcBalance(res.data.available) if (res.data.available != null) {
balance.value = formatUsdcBalance(res.data.available)
}
if (res.data.locked != null) {
lockedBalance.value = formatUsdcBalance(res.data.locked)
}
} }
} catch (e) { } catch (e) {
console.error('[fetchUsdcBalance] 请求失败:', e) console.error('[fetchUsdcBalance] 请求失败:', e)
@ -220,11 +236,14 @@ export const useUserStore = defineStore('user', () => {
const res = await getUserInfo(headers) const res = await getUserInfo(headers)
const data = res.data as Record<string, unknown> | undefined const data = res.data as Record<string, unknown> | undefined
if (res.code !== 0 && res.code !== 200) return if (res.code !== 0 && res.code !== 200) return
// 更新余额data.balance.available // 更新余额data.balance.available / data.balance.locked
const bal = data?.balance as { available?: string } | undefined const bal = data?.balance as { available?: string; locked?: string } | undefined
if (bal?.available != null) { if (bal?.available != null) {
balance.value = formatUsdcBalance(String(bal.available)) balance.value = formatUsdcBalance(String(bal.available))
} }
if (bal?.locked != null) {
lockedBalance.value = formatUsdcBalance(String(bal.locked))
}
// 更新用户信息data.userInfo // 更新用户信息data.userInfo
const u = (data?.userInfo ?? data?.user ?? data) as Record<string, unknown> | undefined const u = (data?.userInfo ?? data?.user ?? data) as Record<string, unknown> | undefined
if (!u) return if (!u) return
@ -277,7 +296,9 @@ export const useUserStore = defineStore('user', () => {
displayName, displayName,
avatarUrl, avatarUrl,
balance, balance,
lockedBalance,
positionsValue, positionsValue,
availableAssetValue,
totalAssetValue, totalAssetValue,
setUser, setUser,
logout, logout,