Files
thebet365/apps/player/src/components/LeagueAccordionItem.vue
Mars f34fe54489 fix(player): ????????????????
?????????????????+??+?????????????????????????????????/???????????????

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 16:25:27 +08:00

202 lines
4.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import MatchBetCard from './MatchBetCard.vue';
import saishiImg from '../assets/images/saishi.webp';
import cardBg from '../assets/images/card-bg.webp';
const matchCardBg = `url(${cardBg})`;
const props = defineProps<{
leagueId: string;
leagueName: string;
leagueLogoUrl?: string | null;
expanded: boolean;
matches: {
id: string;
homeTeamName: string;
awayTeamName: string;
homeTeamCode?: string;
awayTeamCode?: string;
homeTeamLogoUrl?: string | null;
awayTeamLogoUrl?: string | null;
startTime: string;
bettingOpen?: boolean;
matchPhase?: import('../utils/matchPhase').MatchPhase;
score?: {
htHome: number | null;
htAway: number | null;
ftHome: number | null;
ftAway: number | null;
homeCorners?: number | null;
awayCorners?: number | null;
homeYellowCards?: number | null;
awayYellowCards?: number | null;
homeRedCards?: number | null;
awayRedCards?: number | null;
homeCards?: number | null;
awayCards?: number | null;
} | null;
}[];
}>();
const emit = defineEmits<{ toggle: []; bet: [id: string] }>();
const { t } = useI18n();
const totalCount = computed(() => props.matches.length);
const liveCount = computed(() => props.matches.filter(m => m.matchPhase === 'closed_pending').length);
const openCount = computed(() => props.matches.filter(m => m.matchPhase === 'open').length);
</script>
<template>
<section class="league-block">
<button type="button" class="league-row" :aria-expanded="expanded" @click="emit('toggle')">
<span class="toggle-icon" :class="{ open: expanded }" aria-hidden="true">
<span class="toggle-mark">{{ expanded ? '' : '+' }}</span>
</span>
<span class="league-info">
<span class="league-title">*{{ leagueName }}</span>
<span class="league-stats">
<span class="stat-item">{{ totalCount }} {{ t('bet.match_unit') }}</span>
<span v-if="liveCount > 0" class="stat-item stat-live">{{ liveCount }} {{ t('bet.status_live') }}</span>
<span v-if="openCount > 0" class="stat-item stat-open">{{ openCount }} {{ t('bet.status_open') }}</span>
</span>
</span>
<img
:src="leagueLogoUrl || saishiImg"
alt=""
class="league-saishi"
loading="lazy"
decoding="async"
/>
</button>
<div v-show="expanded" class="match-panel">
<div class="match-grid">
<MatchBetCard
v-for="match in matches"
:key="match.id"
:match="match"
@bet="emit('bet', $event)"
/>
</div>
</div>
</section>
</template>
<style scoped>
.league-block {
position: relative;
isolation: isolate;
margin-bottom: 12px;
border: 1px solid var(--border);
border-radius: var(--radius);
background: var(--bg-card);
overflow: hidden;
}
.league-row {
position: relative;
z-index: 1;
width: 100%;
display: flex;
align-items: center;
gap: 10px;
padding: 12px 16px;
background: none;
border: none;
border-radius: 0;
text-align: left;
cursor: pointer;
}
.league-row::before {
content: '';
position: absolute;
inset: 0;
background: v-bind(matchCardBg) center / 100% 100% no-repeat;
opacity: 0.25;
z-index: -1;
pointer-events: none;
}
.league-row:active {
opacity: 0.92;
}
.toggle-icon {
flex-shrink: 0;
width: 26px;
height: 26px;
border-radius: 50%;
background: #141414;
border: 1px solid var(--border-gold-soft);
display: flex;
align-items: center;
justify-content: center;
}
.toggle-mark {
color: var(--primary-light);
font-size: 17px;
font-weight: 900;
line-height: 1;
margin-top: -1px;
}
.league-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.league-title {
font-size: 13px;
font-weight: 800;
color: #fff;
line-height: 1.35;
min-width: 0;
}
.league-stats {
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
color: #ccc;
line-height: 1.2;
}
.stat-live {
color: #3db865;
}
.stat-open {
color: #c8a84e;
}
.league-saishi {
flex-shrink: 0;
height: 44px;
width: auto;
max-width: 40px;
object-fit: contain;
margin-left: 4px;
padding-left: 10px;
border-left: 1px solid #2a2a2a;
}
.match-panel {
padding: 10px 0 4px;
}
.match-grid {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
gap: 8px;
padding: 0 4px;
}
</style>