feat(player): 充值订单详情与审核记录,优化桌面端交互与记录列表样式

新增充值详情页及单条订单 API,修复桌面充值提交路径;充值/注单记录编号改为中性色,并包含桌面首页与投注相关 UI 改进。
This commit is contained in:
2026-07-02 10:47:46 +08:00
parent 49eb3cb7e0
commit 66ac69c7a7
31 changed files with 2251 additions and 905 deletions

View File

@@ -82,7 +82,40 @@ const liveScoreText = computed(() => {
const router = useRouter();
const slip = useBetSlipStore();
const auth = useAuthStore();
const { openAt } = useDesktopBetPopover();
const { openAt, visible: popoverVisible, pendingItem, cancelClose, scheduleClose } = useDesktopBetPopover();
function getHoveredSide() {
if (!popoverVisible.value || !pendingItem.value) return '';
if (String(pendingItem.value.matchId) !== String(props.match.id)) return '';
const selId = pendingItem.value.selectionId;
// Scan all markets to find the selection and get its code
for (const market of props.match.markets ?? []) {
const sel = market.selections?.find((s: any) => s.id === selId);
if (!sel) continue;
const code = (sel.selectionCode || '').toUpperCase();
if (code === 'HOME') return 'home';
if (code === 'AWAY') return 'away';
if (code === 'DRAW') return 'draw';
// Over/Under: over = home side, under = away side (for visual cue)
if (code === 'OVER') return 'home';
if (code === 'UNDER') return 'away';
// Odd/Even: highlight both
if (code === 'ODD' || code === 'EVEN') return 'draw';
// Fallback: use selection index
const selIndex = market.selections?.findIndex((s: any) => s.id === selId) ?? -1;
if (selIndex === -1) continue;
if (market.marketType === 'FT_1X2') {
if (selIndex === 0) return 'home';
if (selIndex === 1) return 'draw';
if (selIndex === 2) return 'away';
} else {
if (selIndex === 0) return 'home';
if (selIndex === 1) return 'away';
}
}
return '';
}
const activeMarketType = ref<string>('');
@@ -173,7 +206,7 @@ function goMatchDetail() {
<span v-else-if="phase === 'settled'" class="status-tag status-tag--settled">{{ phaseLabel }}</span>
<span v-else class="status-tag status-tag--pending">{{ phaseLabel }}</span>
<div class="teams-row">
<div class="teams-row" :class="getHoveredSide()">
<div class="team">
<span class="team-name">{{ match.homeTeamName }}</span>
<img
@@ -217,7 +250,7 @@ function goMatchDetail() {
</button>
<!-- Morphing Quick Bet panel (Desktop Only, disabled when noQuickBet=true) -->
<div v-if="!noQuickBet" class="card-quick-bet" @click.stop>
<div v-if="!noQuickBet" class="card-quick-bet" @click.stop @mouseenter="cancelClose" @mouseleave="scheduleClose()">
<div class="quick-bet-tabs" v-if="getAvailableMarketsForMatch(match).length">
<button
v-for="m in getAvailableMarketsForMatch(match)"
@@ -379,7 +412,7 @@ function goMatchDetail() {
letter-spacing: 0.08em;
line-height: 1;
text-shadow: 0 1px 4px rgba(0, 0, 0, 0.9);
transition: font-size 0.25s ease;
transition: font-size 0.25s ease, transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), text-shadow 0.3s ease;
}
.status-tag {
@@ -593,4 +626,35 @@ function goMatchDetail() {
font-size: 10px;
color: var(--text-muted);
}
/* --- VS Selection Highlight: scale selected team, no VS animation --- */
.teams-row .team {
transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease, filter 0.3s ease;
}
.teams-row.home .team:first-child {
transform: scale(1.08);
filter: brightness(1.3) saturate(1.2);
z-index: 2;
}
.teams-row.home .team:last-child {
opacity: 0.35 !important;
transform: scale(0.94);
filter: grayscale(0.6) brightness(0.7);
}
.teams-row.away .team:last-child {
transform: scale(1.08);
filter: brightness(1.3) saturate(1.2);
z-index: 2;
}
.teams-row.away .team:first-child {
opacity: 0.35 !important;
transform: scale(0.94);
filter: grayscale(0.6) brightness(0.7);
}
.teams-row.draw .team {
transform: scale(1.05);
filter: brightness(1.15) saturate(1.1);
}
</style>