新增 DesktopShell 及桌面端首页、赛事、钱包、记录等页面,原 H5 视图迁移至 Mobile* 并由路由 wrapper 按视口切换。补齐右侧投注单栏、赔率快捷浮层、联赛/赛事侧栏、串关与定位能力;桌面下注成功改为全局 Toast,修复侧栏成功遮罩被裁剪与底部汇总黑底。同步悬浮客服、公告卡片、三语 i18n、桌面样式体系,以及 API 赛事与 shared 包相关调整。
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { ref } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import api from '../api';
|
|
import type { OutrightEvent } from '../components/outright/OutrightEventSection.vue';
|
|
import type { OutrightSelection } from '../components/outright/OutrightEventSection.vue';
|
|
import { useOnLocaleChange } from './useOnLocaleChange';
|
|
|
|
export function useOutrightEvents() {
|
|
const { t } = useI18n();
|
|
const loading = ref(true);
|
|
const loadError = ref('');
|
|
const events = ref<OutrightEvent[]>([]);
|
|
|
|
function mergeOddsOnly(fresh: OutrightEvent[]) {
|
|
const freshMap = new Map<string, OutrightEvent>();
|
|
for (const e of fresh) freshMap.set(e.id, e);
|
|
|
|
for (const event of events.value) {
|
|
const freshEvent = freshMap.get(event.id);
|
|
if (!freshEvent) continue;
|
|
const selMap = new Map<string, OutrightSelection>();
|
|
for (const s of freshEvent.selections) selMap.set(s.id, s);
|
|
for (const sel of event.selections) {
|
|
const fs = selMap.get(sel.id);
|
|
if (fs) {
|
|
sel.odds = fs.odds;
|
|
sel.oddsVersion = fs.oddsVersion;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async function load(options?: { silent?: boolean }) {
|
|
const hadData = events.value.length > 0;
|
|
if (!hadData && !options?.silent) loading.value = true;
|
|
loadError.value = '';
|
|
try {
|
|
const { data } = await api.get('/player/outrights');
|
|
const list = (data?.data ?? []) as OutrightEvent[];
|
|
const fresh = list.filter((e) => e.selections?.length > 0);
|
|
if (!hadData) {
|
|
events.value = fresh;
|
|
} else {
|
|
mergeOddsOnly(fresh);
|
|
}
|
|
} catch (e: unknown) {
|
|
if (!hadData) events.value = [];
|
|
const err = e as { response?: { status?: number; data?: { error?: string } } };
|
|
if (err.response?.status === 403) {
|
|
loadError.value = t('bet.outright_player_only');
|
|
} else {
|
|
loadError.value = err.response?.data?.error ?? t('bet.outright_load_failed');
|
|
}
|
|
} finally {
|
|
if (!hadData && !options?.silent) loading.value = false;
|
|
}
|
|
}
|
|
|
|
useOnLocaleChange(load);
|
|
|
|
return {
|
|
loading,
|
|
loadError,
|
|
events,
|
|
load,
|
|
mergeOddsOnly,
|
|
};
|
|
}
|