From 9abfbfcedd975a55723ad1b044058815ccc69731 Mon Sep 17 00:00:00 2001 From: mars <3361409208@qq.com> Date: Fri, 10 Jul 2026 17:01:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(player):=20theme-3=20PC=20=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E5=BC=B9=E7=AA=97=E8=AF=A6=E6=83=85=E4=B8=8E=E6=94=B6?= =?UTF-8?q?=E4=BB=B6=E7=AE=B1=E6=A0=B7=E5=BC=8F=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 投注/资金/充值/返水列表改为 theme-3 实心弹窗,修复收件箱背景、左侧裁切与滚动。 --- .../player/src/components/FloatingMailbox.vue | 26 +- .../src/components/MessageListPanel.vue | 9 +- .../desktop/DesktopBetDetailModal.vue | 298 +++++++++++++ .../desktop/DesktopCashbackDetailModal.vue | 147 +++++++ .../desktop/DesktopDetailModalShell.vue | 141 +++++++ .../desktop/DesktopRechargeDetailModal.vue | 392 ++++++++++++++++++ .../desktop/DesktopTxDetailModal.vue | 292 +++++++++++++ apps/player/src/styles/desktop/records.css | 18 +- apps/player/src/styles/desktop/tokens.css | 11 + apps/player/src/utils/depositOrderLookup.ts | 63 +++ apps/player/src/views/BetDetailView.vue | 14 + apps/player/src/views/MobileInboxHubView.vue | 6 +- .../src/views/MobileRechargeHistoryView.vue | 26 +- apps/player/src/views/RechargeDetailView.vue | 15 + .../src/views/WalletTransactionDetailView.vue | 17 + .../desktop/DesktopCashbackRecordsView.vue | 47 ++- .../src/views/desktop/DesktopMyBetsView.vue | 37 +- .../desktop/DesktopRechargeHistoryView.vue | 59 ++- .../views/desktop/DesktopWalletDetailView.vue | 53 ++- .../src/views/desktop/DesktopWalletView.vue | 19 +- 20 files changed, 1628 insertions(+), 62 deletions(-) create mode 100644 apps/player/src/components/desktop/DesktopBetDetailModal.vue create mode 100644 apps/player/src/components/desktop/DesktopCashbackDetailModal.vue create mode 100644 apps/player/src/components/desktop/DesktopDetailModalShell.vue create mode 100644 apps/player/src/components/desktop/DesktopRechargeDetailModal.vue create mode 100644 apps/player/src/components/desktop/DesktopTxDetailModal.vue create mode 100644 apps/player/src/utils/depositOrderLookup.ts diff --git a/apps/player/src/components/FloatingMailbox.vue b/apps/player/src/components/FloatingMailbox.vue index 978cf53..7c8075d 100644 --- a/apps/player/src/components/FloatingMailbox.vue +++ b/apps/player/src/components/FloatingMailbox.vue @@ -216,9 +216,7 @@ onMounted(() => { position: absolute; bottom: 64px; right: 0; - background: rgba(22, 22, 22, 0.95); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); + background: #1c3742; border: 1px solid rgba(244, 162, 97, 0.25); border-radius: 8px; padding: 4px; @@ -244,7 +242,7 @@ onMounted(() => { bottom: -6px; right: 22px; border-width: 6px 6px 0 6px; - border-color: rgba(22, 22, 22, 0.95) transparent transparent transparent; + border-color: #1c3742 transparent transparent transparent; z-index: 2; } @@ -367,10 +365,10 @@ onMounted(() => { width: 380px; height: 600px; max-height: calc(100vh - 120px); - background: var(--bg-card, var(--bg-elevated)); - border: 1px solid var(--border); + background: #1a323c; + border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55); display: flex; flex-direction: column; overflow: hidden; @@ -382,9 +380,10 @@ onMounted(() => { align-items: center; justify-content: space-between; padding: 0 12px; - border-bottom: 1px solid var(--border); - background: rgba(255, 255, 255, 0.02); + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + background: #162d36; height: 48px; + flex-shrink: 0; } .popup-title { @@ -440,15 +439,18 @@ onMounted(() => { } .popup-body { - height: calc(100% - 48px); - position: relative; - background: #0f0f0f; + flex: 1; + min-height: 0; + background: #1a323c; overflow-y: auto; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; } .panel-content { display: flex; flex-direction: column; + min-height: 100%; } /* Transitions */ diff --git a/apps/player/src/components/MessageListPanel.vue b/apps/player/src/components/MessageListPanel.vue index 36818ab..1d96af0 100644 --- a/apps/player/src/components/MessageListPanel.vue +++ b/apps/player/src/components/MessageListPanel.vue @@ -9,6 +9,10 @@ import { useAuthStore } from '../stores/auth'; import { stripHtml } from '../utils/html'; import { usePlayerMessages, type DepositMessagePayload, type PlayerMessage } from '../composables/usePlayerMessages'; +const emit = defineEmits<{ + 'click-message': [id: string]; +}>(); + const router = useRouter(); const { t, locale } = useI18n(); const auth = useAuthStore(); @@ -50,7 +54,7 @@ function messagePreview(item: PlayerMessage) { } function openDetail(id: string) { - router.push(`/messages/${id}`); + emit('click-message', id); } async function fetchPage(nextPage: number, append = false) { @@ -205,6 +209,7 @@ onActivated(tryLoad); .list { display: flex; flex-direction: column; + padding: 0 12px; } .list-row { @@ -220,7 +225,7 @@ onActivated(tryLoad); align-items: center; gap: 10px; min-width: 0; - padding: 14px 0; + padding: 14px 4px 14px 0; border: none; background: none; text-align: left; diff --git a/apps/player/src/components/desktop/DesktopBetDetailModal.vue b/apps/player/src/components/desktop/DesktopBetDetailModal.vue new file mode 100644 index 0000000..da32043 --- /dev/null +++ b/apps/player/src/components/desktop/DesktopBetDetailModal.vue @@ -0,0 +1,298 @@ + + + + + + + + + + {{ t('common.load_failed') }} + + {{ t('common.retry') }} + + + + + + {{ detail.betNo }} + {{ statusLabel(detail.status) }} + + + {{ t('bet.stake') }} + {{ formatMoney(detail.stake, locale) }} + + + {{ t('bet.potential_payout') }} + {{ detail.potentialReturn ? formatMoney(detail.potentialReturn, locale) : '-' }} + + + {{ t('bet.placed_at') }} + {{ detail.placedAt ? new Date(detail.placedAt).toLocaleString() : '-' }} + + + + + + {{ t('bet.selections') }} + + {{ leg.matchTitle || t('bet.match') }} + + {{ leg.marketLabel || '' }} + {{ translateSel(leg.selectionName || '') }} + @{{ leg.odds }} + ({{ t('history.ft') }}: {{ leg.score.ft }}) + + + + + + {{ t('common.not_found') }} + + + + diff --git a/apps/player/src/components/desktop/DesktopCashbackDetailModal.vue b/apps/player/src/components/desktop/DesktopCashbackDetailModal.vue new file mode 100644 index 0000000..5a49696 --- /dev/null +++ b/apps/player/src/components/desktop/DesktopCashbackDetailModal.vue @@ -0,0 +1,147 @@ + + + + + + + {{ formatMoney(record.amount, locale) }} + {{ record.batchNo }} + + + + + {{ t('cashback.period') }} + {{ formatPeriod(record.periodStart, record.periodEnd) }} + + + {{ t('cashback.effective_stake') }} + {{ formatMoneyCompact(record.effectiveStake, locale) }} + + + {{ t('cashback.rate') }} + {{ formatRate(record.rate) }} + + + {{ t('wallet.time') }} + {{ formatTime(record.confirmedAt ?? record.createdAt) }} + + + + + {{ t('common.not_found') }} + + + + diff --git a/apps/player/src/components/desktop/DesktopDetailModalShell.vue b/apps/player/src/components/desktop/DesktopDetailModalShell.vue new file mode 100644 index 0000000..c940f6c --- /dev/null +++ b/apps/player/src/components/desktop/DesktopDetailModalShell.vue @@ -0,0 +1,141 @@ + + + + + + + + + {{ title }} + + ✕ + + + + + + + + + + + + diff --git a/apps/player/src/components/desktop/DesktopRechargeDetailModal.vue b/apps/player/src/components/desktop/DesktopRechargeDetailModal.vue new file mode 100644 index 0000000..ed32388 --- /dev/null +++ b/apps/player/src/components/desktop/DesktopRechargeDetailModal.vue @@ -0,0 +1,392 @@ + + + + + + + {{ detail.orderNo }} + {{ statusLabel(detail.status) }} + + + {{ t('wallet.amount') }} + {{ formatMoney(detail.amount, locale) }} + + + {{ t('recharge.credited') }} + {{ formatMoney(detail.approvedAmount, locale) }} + + + {{ t('recharge.method') }} + {{ methodLabel(detail) }} + + + {{ t('recharge.apply_time') }} + {{ new Date(detail.createdAt).toLocaleString() }} + + + {{ t('recharge.review_time') }} + {{ new Date(detail.reviewedAt).toLocaleString() }} + + + + {{ orderNoteLine(detail) }} + + + {{ t('recharge.reapply') }} + + + + + {{ t('recharge.audit_title') }} + + + + + + + + + {{ auditActionLabel(entry.log.action) }} + {{ formatAuditTime(entry.log.createdAt) }} + + {{ entry.actor }} + + {{ t('recharge.audit_credited') }} {{ formatMoney(entry.log.approvedAmount, locale) }} + + + {{ t('recharge.reject_reason') }} + {{ entry.remark.text }} + + + {{ auditNoteDisplayText(entry.remark) }} + + + + + + + + {{ t('common.not_found') }} + + + + diff --git a/apps/player/src/components/desktop/DesktopTxDetailModal.vue b/apps/player/src/components/desktop/DesktopTxDetailModal.vue new file mode 100644 index 0000000..13ac312 --- /dev/null +++ b/apps/player/src/components/desktop/DesktopTxDetailModal.vue @@ -0,0 +1,292 @@ + + + + + + + + + + {{ t('common.load_failed') }} + + {{ t('common.retry') }} + + + + + + + {{ formatMoney(detail.amount, locale) }} + + {{ txLabel(detail) }} + + + + + {{ t('wallet.note') }} + {{ txSummaryLabel(detail, t) || '-' }} + + + {{ t('wallet.balance_before') }} + {{ formatMoney(detail.balanceBefore, locale) }} + + + {{ t('wallet.balance_after') }} + {{ formatMoney(detail.balanceAfter, locale) }} + + + {{ t('wallet.frozen_before') }} + {{ formatMoney(detail.frozenBefore, locale) }} + + + {{ t('wallet.frozen_after') }} + {{ formatMoney(detail.frozenAfter, locale) }} + + + {{ t('wallet.time') }} + {{ new Date(detail.createdAt).toLocaleString() }} + + + {{ t('wallet.transaction_id') }} + {{ detail.transactionId }} + + + + + + {{ t('wallet.detail_bet_link') }} · {{ betNo }} + + + {{ t('wallet.detail_cashback_link') }} · {{ cashbackBatchNo }} + + + + + {{ t('common.not_found') }} + + + + diff --git a/apps/player/src/styles/desktop/records.css b/apps/player/src/styles/desktop/records.css index c29a3a4..7abbfab 100644 --- a/apps/player/src/styles/desktop/records.css +++ b/apps/player/src/styles/desktop/records.css @@ -19,8 +19,11 @@ gap: 20px 32px; flex-wrap: wrap; flex-shrink: 0; - padding-bottom: 14px; - border-bottom: 1px solid var(--border); + padding: 14px 18px; + background: var(--desktop-surface-elevated); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + box-shadow: var(--shadow); } .desktop-records-header-main { @@ -155,11 +158,10 @@ flex-direction: column; flex: 1; min-height: 0; - background: var(--bg-card); - backdrop-filter: blur(16px); - -webkit-backdrop-filter: blur(16px); + background: var(--desktop-surface-solid); border: 1px solid var(--border); border-radius: var(--radius); + box-shadow: var(--shadow); overflow: hidden; } @@ -184,7 +186,7 @@ font-size: 11px; font-weight: 800; color: var(--text-muted); - background: rgba(22, 45, 54, 0.4); border: 1px solid var(--border); + background: var(--desktop-surface-header); text-transform: uppercase; letter-spacing: 0.06em; border-bottom: 1px solid var(--border); @@ -242,8 +244,8 @@ .desktop-records-pagination { flex-shrink: 0; padding: 12px 16px; - border-top: 1px solid rgba(255, 255, 255, 0.06); - background: rgba(10, 10, 10, 0.35); + border-top: 1px solid var(--border); + background: var(--desktop-surface-header); } .desktop-records-loading, diff --git a/apps/player/src/styles/desktop/tokens.css b/apps/player/src/styles/desktop/tokens.css index f1dbc67..677cb05 100644 --- a/apps/player/src/styles/desktop/tokens.css +++ b/apps/player/src/styles/desktop/tokens.css @@ -1,3 +1,11 @@ +/* Teleport 弹窗挂在 body 下,须用 :root 暴露实心色,不能只在 .desktop-shell 内定义 */ +:root { + --desktop-surface-solid: #1a323c; + --desktop-surface-elevated: #1c3742; + --desktop-surface-header: #162d36; + --desktop-border: rgba(255, 255, 255, 0.08); +} + .desktop-shell { /* Color Palette overrides (theme-3 Dusk Coral style) */ --primary: #F4A261; @@ -37,6 +45,9 @@ --desktop-border: rgba(255, 255, 255, 0.08); --desktop-sidebar-bg: rgba(22, 45, 54, 0.82); --desktop-sidebar-panel-bg: linear-gradient(135deg, rgba(22, 45, 54, 0.95), rgba(15, 32, 39, 0.98)); + --desktop-surface-solid: #1a323c; + --desktop-surface-elevated: #1c3742; + --desktop-surface-header: #162d36; --gradient-hero: linear-gradient(135deg, #0F2027, #203A43, #0F2027); /* Reset typography inside desktop */ diff --git a/apps/player/src/utils/depositOrderLookup.ts b/apps/player/src/utils/depositOrderLookup.ts new file mode 100644 index 0000000..0b1d1d6 --- /dev/null +++ b/apps/player/src/utils/depositOrderLookup.ts @@ -0,0 +1,63 @@ +import api from '../api'; + +export type DepositAuditLog = { + id: string; + action: string; + actorType: string; + statusBefore: string | null; + statusAfter: string; + amount: string | null; + approvedAmount: string | null; + remark: string | null; + createdAt: string; +}; + +export type PlayerDepositOrder = { + id: string; + orderNo: string; + paymentMethodId?: string; + methodType: string; + amount: string; + status: string; + approvedAmount: string | null; + rejectReason: string | null; + remark: string | null; + createdAt: string; + reviewedAt: string | null; + paymentMethodName: string | null; + bankName?: string | null; + auditLogs?: DepositAuditLog[]; +}; + +export async function fetchDepositOrderAuditLogs(orderId: string): Promise { + try { + const { data } = await api.get(`/player/deposit-orders/${orderId}/audit-logs`); + const items = data.data?.items ?? data.data ?? []; + return Array.isArray(items) ? (items as DepositAuditLog[]) : []; + } catch { + return []; + } +} + +export async function enrichDepositOrder(order: PlayerDepositOrder): Promise { + if (order.auditLogs?.length) return order; + const auditLogs = await fetchDepositOrderAuditLogs(order.id); + return auditLogs.length ? { ...order, auditLogs } : order; +} + +export async function findDepositOrderById(orderId: string): Promise { + let page = 1; + const pageSize = 20; + + while (true) { + const { data } = await api.get('/player/deposit-orders', { params: { page, pageSize } }); + const result = data.data ?? { items: [], total: 0, pageSize }; + const items = (result.items ?? []) as PlayerDepositOrder[]; + const found = items.find((order) => order.id === orderId); + if (found) return enrichDepositOrder(found); + + const total = result.total ?? 0; + if (!items.length || page * pageSize >= total) return null; + page += 1; + } +} diff --git a/apps/player/src/views/BetDetailView.vue b/apps/player/src/views/BetDetailView.vue index 436662d..6cab81c 100644 --- a/apps/player/src/views/BetDetailView.vue +++ b/apps/player/src/views/BetDetailView.vue @@ -1,9 +1,23 @@ + diff --git a/apps/player/src/views/MobileInboxHubView.vue b/apps/player/src/views/MobileInboxHubView.vue index e9b10b3..3a4f33e 100644 --- a/apps/player/src/views/MobileInboxHubView.vue +++ b/apps/player/src/views/MobileInboxHubView.vue @@ -159,7 +159,11 @@ onActivated(() => { - + router.push(`/messages/${id}`)" + /> -import { ref, onMounted, onUnmounted } from 'vue'; -import { useRouter } from 'vue-router'; +import { ref, onMounted, onUnmounted, watch } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; import { useI18n } from 'vue-i18n'; import api from '../api'; import GoldSpinner from '../components/GoldSpinner.vue'; import { usePullToRefresh } from '../composables/usePullToRefresh'; import { formatMoney } from '../utils/localeDisplay'; +import { enrichDepositOrder, findDepositOrderById } from '../utils/depositOrderLookup'; import { auditActionTone, auditActorSecondary, @@ -14,6 +15,7 @@ import { } from '../utils/depositAuditDisplay'; const router = useRouter(); +const route = useRoute(); const { t, locale } = useI18n(); interface DepositAuditLog { @@ -85,7 +87,7 @@ const { pullDistance, spinning, progress } = usePullToRefresh({ }); onMounted(() => { - fetchOrders(1); + void fetchOrders(1).then(() => openDetailFromQuery()); observer = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting && hasMore.value && !loading.value) { @@ -97,6 +99,10 @@ onMounted(() => { if (sentinel.value) observer.observe(sentinel.value); }); +watch(() => route.query.orderId, () => { + void openDetailFromQuery(); +}); + onUnmounted(() => { observer?.disconnect(); }); @@ -121,14 +127,24 @@ function goRecharge() { router.push('/wallet/recharge'); } -function openDetail(order: DepositOrder) { - selectedOrder.value = order; +async function openDetail(order: DepositOrder) { + selectedOrder.value = await enrichDepositOrder(order); } function closeDetail() { selectedOrder.value = null; } +async function openDetailFromQuery() { + const orderId = route.query.orderId; + if (typeof orderId !== 'string' || !orderId) return; + const existing = items.value.find((order) => order.id === orderId); + const order = existing ?? await findDepositOrderById(orderId); + if (order) await openDetail(order); + const { orderId: _removed, ...rest } = route.query; + void router.replace({ path: route.path, query: rest }); +} + function reapply(order: DepositOrder) { const query: Record = { orderId: order.id, diff --git a/apps/player/src/views/RechargeDetailView.vue b/apps/player/src/views/RechargeDetailView.vue index 92f4b5d..d0021cd 100644 --- a/apps/player/src/views/RechargeDetailView.vue +++ b/apps/player/src/views/RechargeDetailView.vue @@ -1,9 +1,24 @@ diff --git a/apps/player/src/views/WalletTransactionDetailView.vue b/apps/player/src/views/WalletTransactionDetailView.vue index d2616df..4233a6f 100644 --- a/apps/player/src/views/WalletTransactionDetailView.vue +++ b/apps/player/src/views/WalletTransactionDetailView.vue @@ -1,9 +1,26 @@ + diff --git a/apps/player/src/views/desktop/DesktopCashbackRecordsView.vue b/apps/player/src/views/desktop/DesktopCashbackRecordsView.vue index 88dd9a5..a80ba70 100644 --- a/apps/player/src/views/desktop/DesktopCashbackRecordsView.vue +++ b/apps/player/src/views/desktop/DesktopCashbackRecordsView.vue @@ -1,22 +1,50 @@ @@ -113,7 +147,12 @@ onActivated(loadData); - + {{ formatPeriod(row.periodStart, row.periodEnd) }} {{ formatMoneyCompact(row.effectiveStake, locale) }} {{ formatRate(row.rate) }} @@ -140,6 +179,8 @@ onActivated(loadData); /> + + diff --git a/apps/player/src/views/desktop/DesktopMyBetsView.vue b/apps/player/src/views/desktop/DesktopMyBetsView.vue index 67a7c8a..a3a2188 100644 --- a/apps/player/src/views/desktop/DesktopMyBetsView.vue +++ b/apps/player/src/views/desktop/DesktopMyBetsView.vue @@ -1,18 +1,42 @@ @@ -94,7 +124,7 @@ onActivated(() => loadPage(1)); v-for="tx in items" :key="tx.transactionId" class="hover-row clickable-row" - @click="router.push(`/wallet/transactions/${tx.transactionId}`)" + @click="openDetail(tx.transactionId)" > {{ txLabel(tx) }} {{ txSummaryLabel(tx, t) || '-' }} @@ -118,6 +148,11 @@ onActivated(() => loadPage(1)); + + @@ -146,10 +181,10 @@ onActivated(() => loadPage(1)); flex-direction: column; flex: 0 1 auto; min-height: 0; - background: var(--bg-card); - backdrop-filter: blur(12px); - border: 1px solid rgba(255, 255, 255, 0.08); + background: var(--desktop-surface-solid); + border: 1px solid var(--border); border-radius: 8px; + box-shadow: var(--shadow); overflow: hidden; } .table-wrap { flex: 1; overflow-x: auto; overflow-y: auto; } @@ -163,7 +198,7 @@ onActivated(() => loadPage(1)); font-size: 11px; font-weight: 700; color: var(--text-muted); - background: var(--bg-elevated); + background: var(--desktop-surface-header); text-transform: uppercase; letter-spacing: 0.06em; border-bottom: 1px solid var(--desktop-border); diff --git a/apps/player/src/views/desktop/DesktopWalletView.vue b/apps/player/src/views/desktop/DesktopWalletView.vue index cd1ee4a..ae42429 100644 --- a/apps/player/src/views/desktop/DesktopWalletView.vue +++ b/apps/player/src/views/desktop/DesktopWalletView.vue @@ -1,17 +1,25 @@
{{ t('common.load_failed') }}
{{ entry.actor }}
+ {{ t('recharge.audit_credited') }} {{ formatMoney(entry.log.approvedAmount, locale) }} +
+ {{ auditNoteDisplayText(entry.remark) }} +