feat(player): 合并 main 桌面快算能力并完善 theme-2 球赛/首页体验

- 恢复桌面首页焦点大卡布局、悬停下注、VS 高亮与注单动画,移除焦点卡背景图
- 对齐主分支快算弹层上下定位与卡片 engaged 状态;详情页补充 cancelClose/高亮
- 球赛/优胜冠军页恢复 MatchBetCard、冠军卡悬停快算与 OutrightBetModal
- 首页 hotMatches 接口返回 markets,修复卡片切换玩法误显暂无盘口
- 补充 i18n:bet.all、no_market_odds、quick_bet、outright_view_all 等;移除 Tab 表情符号
This commit is contained in:
2026-07-03 11:44:09 +08:00
parent 9daf919d88
commit 3908e5539d
15 changed files with 2231 additions and 722 deletions

View File

@@ -23,7 +23,7 @@ const router = useRouter();
const { t, locale } = useI18n();
const slip = useBetSlipStore();
const auth = useAuthStore();
const { openAt, visible: popoverVisible, pendingItem: popoverItem } = useDesktopBetPopover();
const { openAt, visible: popoverVisible, pendingItem: popoverItem, cancelClose, scheduleClose } = useDesktopBetPopover();
const { pendingLocate, clearLocate } = useDesktopBetLocate();
function goBack() {
@@ -299,6 +299,35 @@ function toggleSelection(sel: Selection, market: Market, event?: MouseEvent) {
if (!item || !event) return;
openAt(event, item);
}
function getHoveredSide() {
if (!match.value || !popoverVisible.value || !popoverItem.value) return '';
if (String(popoverItem.value.matchId) !== String(match.value.id)) return '';
const selId = popoverItem.value.selectionId;
for (const market of allMarkets.value) {
const sel = market.selections?.find((s) => 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';
if (code === 'OVER') return 'home';
if (code === 'UNDER') return 'away';
if (code === 'ODD' || code === 'EVEN') return 'draw';
const selIndex = market.selections?.findIndex((s) => 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 '';
}
</script>
<template>
@@ -318,7 +347,12 @@ function toggleSelection(sel: Selection, market: Market, event?: MouseEvent) {
<template v-else-if="match">
<!-- High Density Score Band -->
<div class="match-score-band" :class="{ 'phase-settled': matchPhase === 'settled' }">
<div
class="match-score-band"
:class="[{ 'phase-settled': matchPhase === 'settled' }, getHoveredSide()]"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="team-side home">
<TeamEmblem size="xl" :team-code="match.homeTeamCode" :team-name="match.homeTeamName" :logo-url="match.homeTeamLogoUrl" />
<span class="name">{{ match.homeTeamName }}</span>
@@ -382,6 +416,8 @@ function toggleSelection(sel: Selection, market: Market, event?: MouseEvent) {
:key="market.id"
class="market-card"
:class="{ locked: isMarketLocked(market) }"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="market-hdr">
<span class="market-title">{{ marketLabel(market) }}</span>
@@ -410,6 +446,8 @@ function toggleSelection(sel: Selection, market: Market, event?: MouseEvent) {
:key="market.id"
class="score-block"
:class="{ locked: isMarketLocked(market) }"
@mouseenter="cancelClose"
@mouseleave="scheduleClose()"
>
<div class="score-block-hdr">
<span>{{ marketLabel(market) }}</span>
@@ -768,4 +806,35 @@ function toggleSelection(sel: Selection, market: Market, event?: MouseEvent) {
font-weight: 700;
white-space: nowrap;
}
.team-side {
transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease, filter 0.3s ease;
}
.match-score-band.home .team-side.home {
transform: scale(1.06);
filter: brightness(1.08) saturate(1.15);
}
.match-score-band.home .team-side.away {
opacity: 0.35;
transform: scale(0.94);
filter: grayscale(0.6) brightness(0.7);
}
.match-score-band.away .team-side.away {
transform: scale(1.06);
filter: brightness(1.08) saturate(1.15);
}
.match-score-band.away .team-side.home {
opacity: 0.35;
transform: scale(0.94);
filter: grayscale(0.6) brightness(0.7);
}
.match-score-band.draw .team-side {
transform: scale(1.04);
filter: brightness(1.08) saturate(1.1);
}
</style>