fix(player): 优化桌面快速下注 hover 并修复充值 API 重复方法
删除 deposit.service 中重复的 getPlayerDepositOrder,避免 API 编译失败引发 500;快速下注弹层按卡片实例激活,同场赛事不再多处联动,移入快速下注区域时保持 VS 动画;记录列表改为整行可点,编号统一中性色样式。
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { ref, computed, getCurrentInstance } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { teamFlagUrl } from '../utils/teamFlag';
|
||||
@@ -82,10 +82,15 @@ const liveScoreText = computed(() => {
|
||||
const router = useRouter();
|
||||
const slip = useBetSlipStore();
|
||||
const auth = useAuthStore();
|
||||
const { openAt, visible: popoverVisible, pendingItem, cancelClose, scheduleClose } = useDesktopBetPopover();
|
||||
const { openAt, visible: popoverVisible, pendingItem, cancelClose, scheduleClose, isActiveForCard } = useDesktopBetPopover();
|
||||
|
||||
const cardRootId = `bet-card-${props.match.id}-${getCurrentInstance()?.uid ?? 0}`;
|
||||
|
||||
const isCardEngaged = computed(() => isActiveForCard(cardRootId));
|
||||
|
||||
function getHoveredSide() {
|
||||
if (!popoverVisible.value || !pendingItem.value) return '';
|
||||
if (!isActiveForCard(cardRootId)) return '';
|
||||
if (String(pendingItem.value.matchId) !== String(props.match.id)) return '';
|
||||
|
||||
const selId = pendingItem.value.selectionId;
|
||||
@@ -199,8 +204,15 @@ function goMatchDetail() {
|
||||
<template>
|
||||
<article
|
||||
class="match-card"
|
||||
:class="{ 'match-card--phase': phase !== 'open', 'no-quick-bet': noQuickBet }"
|
||||
:data-bet-card-root="cardRootId"
|
||||
:class="{
|
||||
'match-card--phase': phase !== 'open',
|
||||
'no-quick-bet': noQuickBet,
|
||||
'match-card--engaged': isCardEngaged,
|
||||
}"
|
||||
@click="emit('bet', match.id)"
|
||||
@mouseenter="cancelClose"
|
||||
@mouseleave="scheduleClose()"
|
||||
>
|
||||
<span v-if="phase === 'open'" class="status-tag status-tag--open">{{ t('bet.status_open') }}</span>
|
||||
<span v-else-if="phase === 'settled'" class="status-tag status-tag--settled">{{ phaseLabel }}</span>
|
||||
@@ -250,7 +262,7 @@ function goMatchDetail() {
|
||||
</button>
|
||||
|
||||
<!-- Morphing Quick Bet panel (Desktop Only, disabled when noQuickBet=true) -->
|
||||
<div v-if="!noQuickBet" class="card-quick-bet" @click.stop @mouseenter="cancelClose" @mouseleave="scheduleClose()">
|
||||
<div v-if="!noQuickBet" class="card-quick-bet" @click.stop>
|
||||
<div class="quick-bet-tabs" v-if="getAvailableMarketsForMatch(match).length">
|
||||
<button
|
||||
v-for="m in getAvailableMarketsForMatch(match)"
|
||||
@@ -486,36 +498,36 @@ function goMatchDetail() {
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.match-card:not(.no-quick-bet):hover {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) {
|
||||
border-color: var(--border-gold);
|
||||
box-shadow: var(--shadow-gold);
|
||||
}
|
||||
|
||||
/* 整行保持原位,间距自然 */
|
||||
.match-card:not(.no-quick-bet):hover .teams-row {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .teams-row {
|
||||
transform: translateY(0);
|
||||
padding: 0 40px;
|
||||
}
|
||||
|
||||
/* .team 取消自身 translateY */
|
||||
.match-card:not(.no-quick-bet):hover .team {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .team {
|
||||
transform: translateY(0);
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
/* 旗帜缩小到 40×28 */
|
||||
.match-card:not(.no-quick-bet):hover .team-flag {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .team-flag {
|
||||
width: 40px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.match-card:not(.no-quick-bet):hover .team-flag.flag-logo {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .team-flag.flag-logo {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
/* 队名缩小并禁止换行 */
|
||||
.match-card:not(.no-quick-bet):hover .team-name {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .team-name {
|
||||
font-size: 10px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
@@ -524,7 +536,7 @@ function goMatchDetail() {
|
||||
}
|
||||
|
||||
/* 隐藏开赛时间 */
|
||||
.match-card:not(.no-quick-bet):hover .kickoff {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .kickoff {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
margin: 0;
|
||||
@@ -533,19 +545,19 @@ function goMatchDetail() {
|
||||
}
|
||||
|
||||
/* VS / 比分 */
|
||||
.match-card:not(.no-quick-bet):hover .vs,
|
||||
.match-card:not(.no-quick-bet):hover .live-score {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .vs,
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .live-score {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* 下注按钮淡出(保留布局空间避免高度抖动) */
|
||||
.match-card:not(.no-quick-bet):hover .bet-btn {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .bet-btn {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 快速下注面板淡入 */
|
||||
.match-card:not(.no-quick-bet):hover .card-quick-bet {
|
||||
.match-card:not(.no-quick-bet):is(:hover, .match-card--engaged) .card-quick-bet {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transform: translateY(0);
|
||||
|
||||
@@ -26,7 +26,7 @@ const emit = defineEmits<{
|
||||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
const { scheduleClose, cancelClose } = useDesktopBetPopover();
|
||||
const { cancelClose } = useDesktopBetPopover();
|
||||
|
||||
const columns = computed(() =>
|
||||
groupCorrectScoreSelections(
|
||||
@@ -51,14 +51,18 @@ function formatOdds(odds: string) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="cs-panel" :class="{ 'cs-panel--locked': locked, 'cs-panel--dense': dense }">
|
||||
<div
|
||||
class="cs-panel"
|
||||
:class="{ 'cs-panel--locked': locked, 'cs-panel--dense': dense }"
|
||||
@mouseenter="cancelClose"
|
||||
>
|
||||
<div class="cols-head">
|
||||
<span>{{ t('bet.col_home') }}</span>
|
||||
<span>{{ t('bet.col_draw') }}</span>
|
||||
<span>{{ t('bet.col_away') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="cols-grid" @mouseenter="cancelClose" @mouseleave="scheduleClose()">
|
||||
<div class="cols-grid">
|
||||
<div v-for="colKey in ['home', 'draw', 'away'] as const" :key="colKey" class="col">
|
||||
<button
|
||||
v-for="sel in columns[colKey]"
|
||||
|
||||
@@ -25,7 +25,7 @@ const props = defineProps<{
|
||||
|
||||
const emit = defineEmits<{ pick: [id: string, event?: MouseEvent] }>();
|
||||
const { t } = useI18n();
|
||||
const { scheduleClose, cancelClose } = useDesktopBetPopover();
|
||||
const { cancelClose } = useDesktopBetPopover();
|
||||
|
||||
function label(sel: (typeof props.selections)[number]) {
|
||||
if (sel.selectionDisplayName?.trim()) return sel.selectionDisplayName;
|
||||
@@ -56,7 +56,7 @@ const panelStyle = computed(() =>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="wrap" :class="{ compact, horizontal, desktopCard, locked }" @mouseenter="cancelClose" @mouseleave="scheduleClose()">
|
||||
<div class="wrap" :class="{ compact, horizontal, desktopCard, locked }" @mouseenter="cancelClose">
|
||||
<div
|
||||
class="panel"
|
||||
:class="{ horizontal, 'desktop-card': desktopCard }"
|
||||
|
||||
Reference in New Issue
Block a user