feat(player): 注册账号、登录双模式与移动端性能优化
注册必填 7-32 位账号,手机号区号/本地号分存;登录默认账号模式并支持切换手机号登录;Player i18n 拆包与赛事接口优化。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import api from '../../api';
|
||||
import { useBetSlipStore } from '../../stores/betSlip';
|
||||
import { usePlayerMatches, type ParlayMatch } from '../../composables/usePlayerMatches';
|
||||
import { useAuthStore } from '../../stores/auth';
|
||||
import { PARLAY_MAX_LEGS, canSelectForParlay } from '@thebet365/shared';
|
||||
import { PARLAY_MARKET_TYPES, PARLAY_SELECTION_KEYS, PARLAY_MARKET_GROUPS } from '../../utils/parlayColumns';
|
||||
@@ -33,28 +33,6 @@ interface Market {
|
||||
selections: Selection[];
|
||||
}
|
||||
|
||||
interface ParlayMatch {
|
||||
id: string;
|
||||
leagueName: string;
|
||||
leagueId?: string;
|
||||
homeTeamName: string;
|
||||
awayTeamName: string;
|
||||
homeTeamCode?: string;
|
||||
awayTeamCode?: string;
|
||||
homeTeamLogoUrl?: string | null;
|
||||
awayTeamLogoUrl?: string | null;
|
||||
startTime: string;
|
||||
bettingOpen?: boolean;
|
||||
matchPhase?: MatchPhase;
|
||||
score?: {
|
||||
htHome: number;
|
||||
htAway: number;
|
||||
ftHome: number;
|
||||
ftAway: number;
|
||||
} | null;
|
||||
markets: Market[];
|
||||
}
|
||||
|
||||
const { t, locale } = useI18n();
|
||||
const slip = useBetSlipStore();
|
||||
const auth = useAuthStore();
|
||||
@@ -63,8 +41,9 @@ function goLogin() {
|
||||
auth.showLoginPrompt('/bet');
|
||||
}
|
||||
|
||||
const loading = ref(true);
|
||||
const matches = ref<ParlayMatch[]>([]);
|
||||
const { parlayMatches, parlayLoading, loadParlay } = usePlayerMatches();
|
||||
const matches = parlayMatches;
|
||||
const loading = parlayLoading;
|
||||
const timeFilter = ref<TimeFilter>('all');
|
||||
const leagueFilter = ref('');
|
||||
const showClosed = ref(false);
|
||||
@@ -72,25 +51,6 @@ const collapsed = ref<Set<string>>(new Set());
|
||||
|
||||
const parlayMarketKeys = PARLAY_MARKET_TYPES.map((c) => c.key);
|
||||
|
||||
async function loadParlayMatches() {
|
||||
const hadData = matches.value.length > 0;
|
||||
if (!hadData) loading.value = true;
|
||||
try {
|
||||
const { data } = await api.get('/player/matches');
|
||||
const fresh = (data.data ?? []).filter(
|
||||
(m: ParlayMatch) => m.markets?.length && hasParlayMarkets(m),
|
||||
);
|
||||
if (!hadData) {
|
||||
matches.value = fresh;
|
||||
syncCollapsedAfterLoad();
|
||||
} else {
|
||||
mergeOddsOnly(fresh);
|
||||
}
|
||||
} finally {
|
||||
if (!hadData) loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function syncCollapsedAfterLoad() {
|
||||
const ids = matches.value.map((m) => m.id);
|
||||
// 只保留仍然存在的 id
|
||||
@@ -107,32 +67,10 @@ function syncCollapsedAfterLoad() {
|
||||
}
|
||||
}
|
||||
|
||||
function mergeOddsOnly(fresh: ParlayMatch[]) {
|
||||
const matchMap = new Map<string, ParlayMatch>();
|
||||
for (const m of fresh) matchMap.set(m.id, m);
|
||||
|
||||
for (const match of matches.value) {
|
||||
const freshMatch = matchMap.get(match.id);
|
||||
if (!freshMatch) continue;
|
||||
const marketMap = new Map<string, Market>();
|
||||
for (const mk of freshMatch.markets) marketMap.set(mk.id, mk);
|
||||
for (const market of match.markets) {
|
||||
const freshMarket = marketMap.get(market.id);
|
||||
if (!freshMarket) continue;
|
||||
const selMap = new Map<string, Selection>();
|
||||
for (const s of freshMarket.selections) selMap.set(s.id, s);
|
||||
for (const sel of market.selections) {
|
||||
const fs = selMap.get(sel.id);
|
||||
if (fs) {
|
||||
sel.odds = fs.odds;
|
||||
sel.oddsVersion = fs.oddsVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useOnLocaleChange(loadParlayMatches);
|
||||
useOnLocaleChange(async () => {
|
||||
await loadParlay(true);
|
||||
syncCollapsedAfterLoad();
|
||||
});
|
||||
|
||||
const leagues = computed(() => {
|
||||
const seen = new Set<string>();
|
||||
@@ -583,7 +521,7 @@ function toggleCollapse(id: string) {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: v-bind(matchCardBg) center top / 100% auto no-repeat;
|
||||
background: v-bind(matchCardBg) center / 100% 100% no-repeat;
|
||||
opacity: 0.25;
|
||||
z-index: -1;
|
||||
pointer-events: none;
|
||||
@@ -600,6 +538,13 @@ function toggleCollapse(id: string) {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.match-head-teams {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.toggle-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user