列表骨架屏
This commit is contained in:
@@ -1,93 +1,85 @@
|
||||
import { TennisMatch } from '../store/listStore'
|
||||
import { TennisMatch } from "../store/listStore";
|
||||
|
||||
// 模拟网络延迟
|
||||
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
|
||||
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
// 模拟API响应格式
|
||||
interface ApiResponse<T> {
|
||||
code: number
|
||||
message: string
|
||||
data: T
|
||||
timestamp: number
|
||||
code: number;
|
||||
message: string;
|
||||
data: T;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
|
||||
// 模拟网球比赛数据
|
||||
const mockTennisMatches: TennisMatch[] = [
|
||||
{
|
||||
id: '1',
|
||||
title: '周一晚场浦东新区单打约球',
|
||||
dateTime: '明天(周五)下午5点 2小时',
|
||||
location: '仁恒河滨花园网球场・室外',
|
||||
distance: '3.5km',
|
||||
id: "1",
|
||||
title: "周一晚场浦东新区单打约球",
|
||||
dateTime: "明天(周五)下午5点 2小时",
|
||||
location: "仁恒河滨花园网球场",
|
||||
distance: "3.5km",
|
||||
shinei: "室内",
|
||||
registeredCount: 3,
|
||||
maxCount: 4,
|
||||
skillLevel: '2.0 至 2.5',
|
||||
matchType: '双打',
|
||||
skillLevel: "2.0 至 2.5",
|
||||
matchType: "双打",
|
||||
images: [
|
||||
'https://images.unsplash.com/photo-1554068865-24cecd4e34b8?w=200&h=200&fit=crop&crop=center',
|
||||
'https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=200&h=200&fit=crop&crop=center',
|
||||
'https://images.unsplash.com/photo-1551698618-1dfe5d97d256?w=200&h=200&fit=crop&crop=center'
|
||||
]
|
||||
"https://images.unsplash.com/photo-1554068865-24cecd4e34b8?w=200&h=200&fit=crop&crop=center",
|
||||
"https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=200&h=200&fit=crop&crop=center",
|
||||
"https://images.unsplash.com/photo-1551698618-1dfe5d97d256?w=200&h=200&fit=crop&crop=center",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
title: '浦东新区单打约球',
|
||||
dateTime: '明天(周五)下午5点 2小时',
|
||||
location: '仁恒河滨花园网球场・室外',
|
||||
distance: '3.5km',
|
||||
id: "2",
|
||||
title: "浦东新区单打约球",
|
||||
dateTime: "明天(周五)下午5点 2小时",
|
||||
location: "仁恒河滨花园网球场",
|
||||
distance: "3.5km",
|
||||
shinei: "室外",
|
||||
registeredCount: 2,
|
||||
maxCount: 4,
|
||||
skillLevel: '2.0 至 2.5',
|
||||
matchType: '双打',
|
||||
skillLevel: "2.0 至 2.5",
|
||||
matchType: "双打",
|
||||
images: [
|
||||
'https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=200&h=200&fit=crop&crop=center',
|
||||
'https://images.unsplash.com/photo-1551698618-1dfe5d97d256?w=200&h=200&fit=crop&crop=center'
|
||||
]
|
||||
"https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=200&h=200&fit=crop&crop=center",
|
||||
"https://images.unsplash.com/photo-1551698618-1dfe5d97d256?w=200&h=200&fit=crop&crop=center",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
title: '黄浦区双打约球',
|
||||
dateTime: '7月20日(周日)下午6点 2小时',
|
||||
location: '仁恒河滨花园网球场・室外',
|
||||
distance: '3.5km',
|
||||
id: "3",
|
||||
title: "黄浦区双打约球",
|
||||
dateTime: "7月20日(周日)下午6点 2小时",
|
||||
location: "仁恒河滨花园网球场",
|
||||
distance: "3.5km",
|
||||
registeredCount: 3,
|
||||
maxCount: 4,
|
||||
skillLevel: '2.0 至 2.5',
|
||||
matchType: '双打',
|
||||
skillLevel: "2.0 至 2.5",
|
||||
matchType: "双打",
|
||||
images: [
|
||||
'https://images.unsplash.com/photo-1554068865-24cecd4e34b8?w=200&h=200&fit=crop&crop=center'
|
||||
]
|
||||
}
|
||||
]
|
||||
"https://images.unsplash.com/photo-1554068865-24cecd4e34b8?w=200&h=200&fit=crop&crop=center",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// 模拟数据变化
|
||||
const generateDynamicData = (): TennisMatch[] => {
|
||||
return mockTennisMatches.map(match => ({
|
||||
Promise.resolve((res) => {
|
||||
setTimeout(res, 3000);
|
||||
});
|
||||
return mockTennisMatches.map((match) => ({
|
||||
...match,
|
||||
// 随机更新注册人数
|
||||
registeredCount: Math.min(
|
||||
match.maxCount,
|
||||
match.maxCount,
|
||||
Math.max(0, match.registeredCount + Math.floor(Math.random() * 3) - 1)
|
||||
),
|
||||
// 随机更新距离
|
||||
distance: `${(Math.random() * 5 + 1).toFixed(1)}km`,
|
||||
// 随机更新时间
|
||||
dateTime: Math.random() > 0.5 ? match.dateTime : '今天下午3点 2小时'
|
||||
}))
|
||||
}
|
||||
|
||||
// 模拟网络错误
|
||||
const simulateNetworkError = (): boolean => {
|
||||
// 10% 概率模拟网络错误
|
||||
return Math.random() < 0.1
|
||||
}
|
||||
|
||||
// 模拟网络超时
|
||||
const simulateTimeout = (): boolean => {
|
||||
// 5% 概率模拟超时
|
||||
return Math.random() < 0.05
|
||||
}
|
||||
dateTime: Math.random() > 0.5 ? match.dateTime : "今天下午3点 2小时",
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取网球比赛列表
|
||||
@@ -95,59 +87,21 @@ const simulateTimeout = (): boolean => {
|
||||
* @returns Promise<TennisMatch[]>
|
||||
*/
|
||||
export const getTennisMatches = async (params?: {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
location?: string
|
||||
skillLevel?: string
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
location?: string;
|
||||
skillLevel?: string;
|
||||
}): Promise<TennisMatch[]> => {
|
||||
try {
|
||||
console.log('API调用: getTennisMatches', params)
|
||||
|
||||
// 模拟网络延迟 (800-1500ms)
|
||||
const delayTime = 800 + Math.random() * 700
|
||||
await delay(delayTime)
|
||||
|
||||
// 模拟网络错误
|
||||
if (simulateNetworkError()) {
|
||||
throw new Error('网络连接失败,请检查网络设置')
|
||||
}
|
||||
|
||||
// 模拟超时
|
||||
if (simulateTimeout()) {
|
||||
throw new Error('请求超时,请稍后重试')
|
||||
}
|
||||
|
||||
// 生成动态数据
|
||||
const matches = generateDynamicData()
|
||||
|
||||
// 模拟分页
|
||||
if (params?.page && params?.pageSize) {
|
||||
const start = (params.page - 1) * params.pageSize
|
||||
const end = start + params.pageSize
|
||||
return matches.slice(start, end)
|
||||
}
|
||||
|
||||
// 模拟筛选
|
||||
if (params?.location) {
|
||||
return matches.filter(match =>
|
||||
match.location.includes(params.location!)
|
||||
)
|
||||
}
|
||||
|
||||
if (params?.skillLevel) {
|
||||
return matches.filter(match =>
|
||||
match.skillLevel.includes(params.skillLevel!)
|
||||
)
|
||||
}
|
||||
|
||||
console.log('API响应成功:', matches.length, '条数据')
|
||||
return matches
|
||||
|
||||
const matches = generateDynamicData();
|
||||
|
||||
return matches;
|
||||
} catch (error) {
|
||||
console.error('API调用失败:', error)
|
||||
throw error
|
||||
console.error("API调用失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 刷新网球比赛数据
|
||||
@@ -155,60 +109,47 @@ export const getTennisMatches = async (params?: {
|
||||
*/
|
||||
export const refreshTennisMatches = async (): Promise<TennisMatch[]> => {
|
||||
try {
|
||||
console.log('API调用: refreshTennisMatches')
|
||||
|
||||
// 模拟刷新延迟 (500-1000ms)
|
||||
const delayTime = 500 + Math.random() * 500
|
||||
await delay(delayTime)
|
||||
|
||||
// 模拟网络错误
|
||||
if (simulateNetworkError()) {
|
||||
throw new Error('刷新失败,请稍后重试')
|
||||
}
|
||||
|
||||
// 生成新的动态数据
|
||||
const matches = generateDynamicData()
|
||||
|
||||
console.log('API刷新成功:', matches.length, '条数据')
|
||||
return matches
|
||||
|
||||
const matches = generateDynamicData();
|
||||
return matches;
|
||||
} catch (error) {
|
||||
console.error('API刷新失败:', error)
|
||||
throw error
|
||||
console.error("API刷新失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取比赛详情
|
||||
* @param id 比赛ID
|
||||
* @returns Promise<TennisMatch | null>
|
||||
*/
|
||||
export const getTennisMatchDetail = async (id: string): Promise<TennisMatch | null> => {
|
||||
export const getTennisMatchDetail = async (
|
||||
id: string
|
||||
): Promise<TennisMatch | null> => {
|
||||
try {
|
||||
console.log('API调用: getTennisMatchDetail', id)
|
||||
|
||||
console.log("API调用: getTennisMatchDetail", id);
|
||||
|
||||
// 模拟网络延迟
|
||||
await delay(600 + Math.random() * 400)
|
||||
|
||||
await delay(600 + Math.random() * 400);
|
||||
|
||||
// 模拟网络错误
|
||||
if (simulateNetworkError()) {
|
||||
throw new Error('获取详情失败,请稍后重试')
|
||||
throw new Error("获取详情失败,请稍后重试");
|
||||
}
|
||||
|
||||
const match = mockTennisMatches.find(m => m.id === id)
|
||||
|
||||
|
||||
const match = mockTennisMatches.find((m) => m.id === id);
|
||||
|
||||
if (!match) {
|
||||
throw new Error('比赛不存在')
|
||||
throw new Error("比赛不存在");
|
||||
}
|
||||
|
||||
console.log('API获取详情成功:', match.title)
|
||||
return match
|
||||
|
||||
|
||||
console.log("API获取详情成功:", match.title);
|
||||
return match;
|
||||
} catch (error) {
|
||||
console.error('API获取详情失败:', error)
|
||||
throw error
|
||||
console.error("API获取详情失败:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 模拟API统计信息
|
||||
@@ -218,6 +159,6 @@ export const getApiStats = () => {
|
||||
totalCalls: 0,
|
||||
successRate: 0.95,
|
||||
averageResponseTime: 800,
|
||||
lastCallTime: new Date().toISOString()
|
||||
}
|
||||
}
|
||||
lastCallTime: new Date().toISOString(),
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user