From 3688ce656d6dabd0fe14ff78fa999379925070da Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 8 Feb 2026 18:42:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E5=8E=86=E5=8F=B2=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Wallet.vue | 273 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 260 insertions(+), 13 deletions(-) diff --git a/src/views/Wallet.vue b/src/views/Wallet.vue index 44bd66c..16aa16d 100644 --- a/src/views/Wallet.vue +++ b/src/views/Wallet.vue @@ -87,13 +87,31 @@ class="search-field" prepend-inner-icon="mdi-magnify" /> - + + mdi-filter - Current value + Market - + + MARKET @@ -110,13 +128,11 @@ - - - No positions found. - + + No positions found. - - {{ pos.market }} + + {{ pos.market }} {{ pos.avgNow }} {{ pos.bet }} {{ pos.toWin }} @@ -124,6 +140,87 @@ + + + + + MARKET + SIDE + OUTCOME + PRICE + FILLED + TOTAL + EXPIRATION + ACTION + + + + + No open orders found. + + + {{ ord.market }} + + {{ ord.side }} + + {{ ord.outcome }} + {{ ord.price }} + {{ ord.filled }} + {{ ord.total }} + {{ ord.expiration }} + + Cancel + + + + + + + + + ACTIVITY + MARKET + VALUE + + + + + You haven't traded any polymarkets yet + + + + {{ h.activity }} + + {{ h.market }} + {{ h.value }} + + + + +
+ + {{ currentPageStart }}–{{ currentPageEnd }} of {{ currentListTotal }} + +
+ + +
+
@@ -152,11 +249,100 @@ 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 activeTab = ref<'positions' | 'orders' | 'history'>('positions') const search = ref('') const depositDialogOpen = ref(false) const withdrawDialogOpen = ref(false) -const positions = ref<{ id: string; market: string; avgNow: string; bet: string; toWin: string; value: string }[]>([]) + +interface Position { + id: string + market: string + avgNow: string + bet: string + toWin: string + value: string +} +interface OpenOrder { + id: string + market: string + side: 'Yes' | 'No' + outcome: string + price: string + filled: string + total: string + expiration: string +} +interface HistoryItem { + id: string + market: string + side: 'Yes' | 'No' + activity: string + value: string +} + +const positions = ref([ + { id: 'p1', market: 'Will Bitcoin hit $100k by end of 2025?', avgNow: '72¢ → 75¢', bet: '$50', toWin: '$18', value: '$52' }, + { id: 'p2', market: 'Will ETH merge complete by Q3?', avgNow: '45¢ → 48¢', bet: '$30', toWin: '$36', value: '$32' }, +]) +const openOrders = ref([ + { id: 'o1', market: 'Will Bitcoin hit $100k by end of 2025?', side: 'Yes', outcome: 'Yes', price: '70¢', filled: '0', total: '$70', expiration: 'Dec 31, 2025' }, + { id: 'o2', market: 'Will ETH merge complete by Q3?', side: 'No', outcome: 'No', price: '52¢', filled: '25', total: '$26', expiration: 'Sep 30, 2025' }, +]) +const history = ref([ + { id: 'h1', market: 'Will Bitcoin hit $100k by end of 2025?', side: 'Yes', activity: 'Buy Yes', value: '$68' }, + { id: 'h2', market: 'Will ETH merge complete by Q3?', side: 'No', activity: 'Sell No', value: '$35.20' }, +]) + +function matchSearch(text: string): boolean { + const q = search.value.trim().toLowerCase() + return !q || text.toLowerCase().includes(q) +} +const filteredPositions = computed(() => positions.value.filter((p) => matchSearch(p.market))) +const filteredOpenOrders = computed(() => openOrders.value.filter((o) => matchSearch(o.market))) +const filteredHistory = computed(() => history.value.filter((h) => matchSearch(h.market))) + +const page = ref(1) +const itemsPerPage = ref(10) +const pageSizeOptions = [5, 10, 25, 50] + +function paginate(list: T[]) { + const start = (page.value - 1) * itemsPerPage.value + return list.slice(start, start + itemsPerPage.value) +} +const paginatedPositions = computed(() => paginate(filteredPositions.value)) +const paginatedOpenOrders = computed(() => paginate(filteredOpenOrders.value)) +const paginatedHistory = computed(() => paginate(filteredHistory.value)) + +const totalPagesPositions = computed(() => Math.max(1, Math.ceil(filteredPositions.value.length / itemsPerPage.value))) +const totalPagesOrders = computed(() => Math.max(1, Math.ceil(filteredOpenOrders.value.length / itemsPerPage.value))) +const totalPagesHistory = computed(() => Math.max(1, Math.ceil(filteredHistory.value.length / itemsPerPage.value))) + +const currentListTotal = computed(() => { + if (activeTab.value === 'positions') return filteredPositions.value.length + if (activeTab.value === 'orders') return filteredOpenOrders.value.length + return filteredHistory.value.length +}) +const currentTotalPages = computed(() => { + if (activeTab.value === 'positions') return totalPagesPositions.value + if (activeTab.value === 'orders') return totalPagesOrders.value + return totalPagesHistory.value +}) +const currentPageStart = computed(() => currentListTotal.value === 0 ? 0 : (page.value - 1) * itemsPerPage.value + 1) +const currentPageEnd = computed(() => Math.min(page.value * itemsPerPage.value, currentListTotal.value)) + +watch(activeTab, () => { page.value = 1 }) +watch([currentListTotal, itemsPerPage], () => { + const maxPage = currentTotalPages.value + if (page.value > maxPage) page.value = Math.max(1, maxPage) +}) + +function onPageChange() { + // 可选:翻页后滚动到表格顶部 +} + +function cancelOrder(id: string) { + openOrders.value = openOrders.value.filter((o) => o.id !== id) +} const plChartRef = ref(null) let plChartInstance: ECharts | null = null @@ -418,10 +604,12 @@ function onWithdrawSuccess() { overflow: hidden; } -.positions-table { +.positions-table, +.wallet-table { font-size: 14px; } +.wallet-table th, .positions-table th { font-size: 11px; font-weight: 600; @@ -437,15 +625,74 @@ function onWithdrawSuccess() { color: #9ca3af; } -.positions-table td { +.positions-table td, +.wallet-table td { padding: 12px 16px; color: #374151; } +.cell-market { + max-width: 280px; + word-break: break-word; +} + +.side-yes { + color: #059669; + font-weight: 500; +} + +.side-no { + color: #dc2626; + font-weight: 500; +} + .empty-cell { text-align: center; color: #6b7280; padding: 48px 16px !important; font-size: 14px; } + +.pagination-bar { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 12px; + padding: 12px 16px; + border-top: 1px solid #e5e7eb; + font-size: 14px; + color: #6b7280; +} + +.pagination-info { + flex-shrink: 0; +} + +.pagination-controls { + display: flex; + align-items: center; + gap: 12px; +} + +.page-size-select { + min-width: 88px; + width: 88px; + font-size: 14px; +} + +.page-size-select :deep(.v-field) { + font-size: 14px; +} + +.page-size-select :deep(.v-field__input) { + min-width: 2ch; +} + +.pagination :deep(.v-pagination__item), +.pagination :deep(.v-pagination__prev), +.pagination :deep(.v-pagination__next) { + min-width: 32px; + height: 32px; +}