196 lines
4.6 KiB
TypeScript
196 lines
4.6 KiB
TypeScript
import { API_CONFIG, API_ENDPOINTS } from "@/constants/api";
|
||
import {
|
||
ApiListResponse,
|
||
ApiResponse,
|
||
Country,
|
||
League,
|
||
Match,
|
||
MatchDetailData,
|
||
OddsData,
|
||
Sport,
|
||
UpcomingMatch,
|
||
} from "@/types/api";
|
||
import axios from "axios";
|
||
|
||
const apiClient = axios.create({
|
||
baseURL: API_CONFIG.BASE_URL,
|
||
timeout: API_CONFIG.TIMEOUT,
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
});
|
||
|
||
export const fetchSports = async (): Promise<Sport[]> => {
|
||
try {
|
||
const response = await apiClient.get<ApiResponse<ApiListResponse<Sport>>>(
|
||
API_ENDPOINTS.SPORTS
|
||
);
|
||
if (response.data.code === 0) {
|
||
return response.data.data.list;
|
||
}
|
||
throw new Error(response.data.message);
|
||
} catch (error) {
|
||
console.error("Fetch sports error:", error);
|
||
// Do not return mock data here — rethrow to let caller handle the error
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
export const fetchCountries = async (): Promise<Country[]> => {
|
||
try {
|
||
const response = await apiClient.get<ApiResponse<ApiListResponse<Country>>>(
|
||
API_ENDPOINTS.COUNTRIES
|
||
);
|
||
if (response.data.code === 0) {
|
||
return response.data.data.list;
|
||
}
|
||
throw new Error(response.data.message);
|
||
} catch (error) {
|
||
console.error("Fetch countries error:", error);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
export const fetchLeagues = async (
|
||
sportId: number,
|
||
countryKey: string
|
||
): Promise<League[]> => {
|
||
try {
|
||
const response = await apiClient.get<ApiResponse<ApiListResponse<League>>>(
|
||
API_ENDPOINTS.LEAGUES,
|
||
{
|
||
params: {
|
||
sportId,
|
||
countryKey,
|
||
},
|
||
}
|
||
);
|
||
if (response.data.code === 0) {
|
||
return response.data.data.list;
|
||
}
|
||
throw new Error(response.data.message);
|
||
} catch (error) {
|
||
console.error("Fetch leagues error:", error);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
export const fetchTodayMatches = async (
|
||
sportId: number,
|
||
date?: Date | string,
|
||
timezone?: string
|
||
): Promise<Match[]> => {
|
||
try {
|
||
const params: { sportId: number; date?: string; timezone?: string } = {
|
||
sportId,
|
||
};
|
||
|
||
// 如果提供了日期,格式化为 YYYY-MM-DD 格式
|
||
if (date) {
|
||
let dateStr: string;
|
||
if (date instanceof Date) {
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||
const day = String(date.getDate()).padStart(2, "0");
|
||
dateStr = `${year}-${month}-${day}`;
|
||
} else {
|
||
dateStr = date;
|
||
}
|
||
params.date = dateStr;
|
||
}
|
||
|
||
// 如果提供了时区,传给后端;不传则由后端使用本地时区
|
||
if (timezone) {
|
||
params.timezone = timezone;
|
||
}
|
||
|
||
const response = await apiClient.get<ApiResponse<ApiListResponse<Match>>>(
|
||
API_ENDPOINTS.MATCHES_TODAY,
|
||
{
|
||
params,
|
||
}
|
||
);
|
||
if (response.data.code === 0) {
|
||
return response.data.data.list;
|
||
}
|
||
throw new Error(response.data.message);
|
||
} catch (error) {
|
||
console.error("Fetch matches error:", error);
|
||
// Let the caller handle errors; rethrow the original error
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
export const fetchMatchDetail = async (
|
||
id: string
|
||
): Promise<MatchDetailData> => {
|
||
try {
|
||
const response = await apiClient.get<ApiResponse<MatchDetailData>>(
|
||
API_ENDPOINTS.MATCH_DETAIL(id)
|
||
);
|
||
if (response.data.code === 0) {
|
||
return response.data.data;
|
||
}
|
||
throw new Error(response.data.message);
|
||
} catch (error) {
|
||
console.error("Fetch match detail error:", error);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
export const fetchUpcomingMatches = async (
|
||
sportId: number,
|
||
leagueKey: string,
|
||
limit: number = 50
|
||
): Promise<UpcomingMatch[]> => {
|
||
try {
|
||
const response =
|
||
await apiClient.get<ApiResponse<ApiListResponse<UpcomingMatch>>>(
|
||
API_ENDPOINTS.UPCOMING_MATCHES,
|
||
{
|
||
params: {
|
||
sport_id: sportId,
|
||
leagueKey,
|
||
limit,
|
||
},
|
||
}
|
||
);
|
||
|
||
if (response.data.code === 0) {
|
||
return response.data.data.list;
|
||
}
|
||
|
||
throw new Error(response.data.message);
|
||
} catch (error) {
|
||
console.error("Fetch upcoming matches error:", error);
|
||
throw error;
|
||
}
|
||
};
|
||
|
||
// 获取实时赔率(足球/网球使用 LiveOdds,篮球/板球使用 Odds)
|
||
export const fetchOdds = async (
|
||
sportId: number,
|
||
matchId: number
|
||
): Promise<OddsData> => {
|
||
try {
|
||
const response = await apiClient.get<ApiResponse<OddsData>>(
|
||
API_ENDPOINTS.ODDS,
|
||
{
|
||
params: {
|
||
sport_id: sportId,
|
||
match_id: matchId,
|
||
},
|
||
}
|
||
);
|
||
|
||
if (response.data.code === 0) {
|
||
return response.data.data;
|
||
}
|
||
|
||
throw new Error(response.data.message);
|
||
} catch (error) {
|
||
console.error("Fetch odds error:", error);
|
||
throw error;
|
||
}
|
||
};
|