Files
makemd/dashboard/src/services/leaderboardDataSource.ts

98 lines
3.4 KiB
TypeScript
Raw Normal View History

/**
* [MOCK]
* AI注意: 这是Mock实现
* USE_MOCK=true时启用
*/
export interface LeaderboardEntry {
rank: number;
tenant_id: string;
tenant_name: string;
shop_id: string;
shop_name: string;
value: number;
tier: string;
is_verified: boolean;
growth_rate: number;
}
export interface LeaderboardData {
revenue: { rankings: LeaderboardEntry[]; total: number };
roi: { rankings: LeaderboardEntry[]; total: number };
growth: { rankings: LeaderboardEntry[]; total: number };
period: string;
updatedAt: string;
}
export interface MyRank {
revenue: { rank: number; percentile: number } | null;
roi: { rank: number; percentile: number } | null;
growth: { rank: number; percentile: number } | null;
period: string;
}
export interface ILeaderboardDataSource {
fetchLeaderboard(period: 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'ALL_TIME'): Promise<LeaderboardData>;
fetchMyRank(period: 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'ALL_TIME'): Promise<MyRank>;
}
class MockLeaderboardDataSource implements ILeaderboardDataSource {
private generateRankings(count: number, type: 'revenue' | 'roi' | 'growth'): LeaderboardEntry[] {
return Array.from({ length: count }, (_, i) => ({
rank: i + 1,
tenant_id: `tenant_${i + 1}`,
tenant_name: `Tenant ${i + 1}`,
shop_id: `shop_${i + 1}`,
shop_name: `Shop ${i + 1}`,
value: type === 'revenue' ? Math.floor(Math.random() * 100000) + 10000 :
type === 'roi' ? Math.floor(Math.random() * 100) + 20 :
Math.floor(Math.random() * 50) + 5,
tier: ['BASIC', 'PRO', 'ENTERPRISE'][Math.floor(Math.random() * 3)],
is_verified: Math.random() > 0.3,
growth_rate: Math.floor(Math.random() * 100) - 20,
}));
}
async fetchLeaderboard(period: 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'ALL_TIME'): Promise<LeaderboardData> {
await new Promise(resolve => setTimeout(resolve, 500));
return {
revenue: { rankings: this.generateRankings(10, 'revenue'), total: 100 },
roi: { rankings: this.generateRankings(10, 'roi'), total: 100 },
growth: { rankings: this.generateRankings(10, 'growth'), total: 100 },
period,
updatedAt: new Date().toISOString(),
};
}
async fetchMyRank(period: 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'ALL_TIME'): Promise<MyRank> {
await new Promise(resolve => setTimeout(resolve, 300));
return {
revenue: { rank: 15, percentile: 85 },
roi: { rank: 8, percentile: 92 },
growth: { rank: 22, percentile: 78 },
period,
};
}
}
class ApiLeaderboardDataSource implements ILeaderboardDataSource {
private baseUrl = '/api/leaderboard';
async fetchLeaderboard(period: 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'ALL_TIME'): Promise<LeaderboardData> {
const response = await fetch(`${this.baseUrl}?period=${period}`);
if (!response.ok) throw new Error('Failed to fetch leaderboard');
return response.json();
}
async fetchMyRank(period: 'DAILY' | 'WEEKLY' | 'MONTHLY' | 'ALL_TIME'): Promise<MyRank> {
const response = await fetch(`${this.baseUrl}/my-rank?period=${period}`);
if (!response.ok) throw new Error('Failed to fetch my rank');
return response.json();
}
}
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
export const leaderboardDataSource: ILeaderboardDataSource = useMock
? new MockLeaderboardDataSource()
: new ApiLeaderboardDataSource();