xtraderClient/src/views/Wallet.vue
2026-02-08 14:50:38 +08:00

332 lines
7.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<v-container class="wallet-container">
<!-- 顶部Portfolio + Profit/Loss 卡片 -->
<v-row class="wallet-cards">
<v-col cols="12" md="6">
<v-card class="wallet-card portfolio-card" elevation="0" rounded="lg">
<div class="card-header">
<span class="card-title">
Portfolio
<v-icon size="16" class="title-icon">mdi-eye-off-outline</v-icon>
</span>
<div class="balance-badge">
<v-icon size="14">mdi-sack</v-icon>
<span>${{ portfolioBalance }}</span>
</div>
</div>
<div class="card-value">${{ portfolioBalance }}</div>
<div class="card-timeframe">Today</div>
<div class="card-actions">
<v-btn color="primary" variant="flat" class="action-btn" prepend-icon="mdi-arrow-down">
Deposit
</v-btn>
<v-btn variant="outlined" color="grey" class="action-btn" prepend-icon="mdi-arrow-up">
Withdraw
</v-btn>
</div>
</v-card>
</v-col>
<v-col cols="12" md="6">
<v-card class="wallet-card pl-card" elevation="0" rounded="lg">
<div class="card-header">
<span class="card-title">
<v-icon size="16" color="success">mdi-triangle-small-up</v-icon>
Profit/Loss
</span>
<div class="pl-tabs">
<v-btn
v-for="t in plTimeRanges"
:key="t"
:variant="plRange === t ? 'flat' : 'text'"
:color="plRange === t ? 'primary' : undefined"
size="small"
class="pl-tab"
@click="plRange = t"
>
{{ t }}
</v-btn>
</div>
</div>
<div class="card-value-row">
<span class="card-value">${{ profitLoss }}</span>
<v-icon size="18" class="info-icon">mdi-information-outline</v-icon>
</div>
<div class="card-timeframe">All-Time</div>
<div class="polymarket-logo">
<span class="logo-p">P</span>
</div>
<div class="pl-bar">
<div class="pl-bar-fill" />
</div>
</v-card>
</v-col>
</v-row>
<!-- 下方Positions / Open orders / History -->
<div class="wallet-section">
<v-tabs v-model="activeTab" class="wallet-tabs" density="comfortable">
<v-tab value="positions">Positions</v-tab>
<v-tab value="orders">Open orders</v-tab>
<v-tab value="history">History</v-tab>
</v-tabs>
<div class="toolbar">
<v-text-field
v-model="search"
placeholder="Search"
density="compact"
hide-details
variant="outlined"
rounded
class="search-field"
prepend-inner-icon="mdi-magnify"
/>
<v-btn variant="outlined" size="small" class="filter-btn">
<v-icon size="18">mdi-filter</v-icon>
Current value
</v-btn>
</div>
<v-card class="table-card" elevation="0" rounded="lg">
<v-table class="positions-table">
<thead>
<tr>
<th class="text-left">MARKET</th>
<th class="text-left">
AVG NOW
<v-icon size="14" class="th-icon">mdi-information-outline</v-icon>
</th>
<th class="text-left">BET</th>
<th class="text-left">TO WIN</th>
<th class="text-left">
VALUE
<v-icon size="14" class="th-icon">mdi-chevron-down</v-icon>
</th>
</tr>
</thead>
<tbody>
<tr v-if="positions.length === 0">
<td colspan="5" class="empty-cell">
No positions found.
</td>
</tr>
<tr v-for="pos in positions" :key="pos.id">
<td>{{ pos.market }}</td>
<td>{{ pos.avgNow }}</td>
<td>{{ pos.bet }}</td>
<td>{{ pos.toWin }}</td>
<td>{{ pos.value }}</td>
</tr>
</tbody>
</v-table>
</v-card>
</div>
</v-container>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useUserStore } from '../stores/user'
const userStore = useUserStore()
const portfolioBalance = computed(() => userStore.balance)
const profitLoss = ref('0.00')
const plRange = ref('ALL')
const plTimeRanges = ['1D', '1W', '1M', 'ALL']
const activeTab = ref('positions')
const search = ref('')
const positions = ref<{ id: string; market: string; avgNow: string; bet: string; toWin: string; value: string }[]>([])
</script>
<style scoped>
.wallet-container {
max-width: 1200px;
margin: 0 auto;
padding: 24px 16px;
}
.wallet-cards {
margin-bottom: 32px;
}
.wallet-card {
padding: 20px;
border: 1px solid #e5e7eb;
height: 100%;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.card-title {
font-size: 14px;
font-weight: 500;
color: #374151;
display: inline-flex;
align-items: center;
gap: 4px;
}
.title-icon {
color: #9ca3af;
}
.balance-badge {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 12px;
color: #059669;
background-color: #d1fae5;
padding: 4px 8px;
border-radius: 6px;
}
.card-value {
font-size: 28px;
font-weight: 600;
color: #111827;
margin-bottom: 4px;
}
.card-value-row {
display: flex;
align-items: center;
gap: 6px;
margin-bottom: 4px;
}
.card-value-row .card-value {
margin-bottom: 0;
}
.info-icon {
color: #9ca3af;
}
.card-timeframe {
font-size: 12px;
color: #6b7280;
margin-bottom: 16px;
}
.card-actions {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.action-btn {
text-transform: none;
}
.pl-tabs {
display: flex;
gap: 4px;
}
.pl-tab {
min-width: 40px;
text-transform: none;
font-size: 12px;
}
.polymarket-logo {
margin-bottom: 12px;
}
.logo-p {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
background: linear-gradient(135deg, #1a73e8 0%, #34a853 100%);
color: white;
font-weight: 700;
font-size: 14px;
border-radius: 6px;
}
.pl-bar {
height: 6px;
background: #e5e7eb;
border-radius: 3px;
overflow: hidden;
}
.pl-bar-fill {
height: 100%;
width: 40%;
background: linear-gradient(90deg, #93c5fd 0%, #bfdbfe 100%);
border-radius: 3px;
}
.wallet-section {
margin-top: 8px;
}
.wallet-tabs {
margin-bottom: 16px;
}
.toolbar {
display: flex;
gap: 12px;
align-items: center;
margin-bottom: 16px;
flex-wrap: wrap;
}
.search-field {
max-width: 280px;
}
.search-field :deep(.v-field) {
font-size: 14px;
}
.filter-btn {
text-transform: none;
font-size: 13px;
}
.table-card {
border: 1px solid #e5e7eb;
overflow: hidden;
}
.positions-table {
font-size: 14px;
}
.positions-table th {
font-size: 11px;
font-weight: 600;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.02em;
padding: 12px 16px;
}
.th-icon {
vertical-align: middle;
margin-left: 2px;
color: #9ca3af;
}
.positions-table td {
padding: 12px 16px;
color: #374151;
}
.empty-cell {
text-align: center;
color: #6b7280;
padding: 48px 16px !important;
font-size: 14px;
}
</style>