2026-03-19 01:39:34 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* [MOCK] 排行榜数据源
|
|
|
|
|
|
* AI注意: 这是Mock实现,不是真实业务逻辑
|
|
|
|
|
|
* 仅在USE_MOCK=true时启用
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
import { BaseDataSource, BaseMockDataSource, DataSourceFactory } from './dataSourceFactory';
|
|
|
|
|
|
|
2026-03-19 01:39:34 +08:00
|
|
|
|
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>;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
class ApiLeaderboardDataSource extends BaseDataSource<any, any> implements ILeaderboardDataSource {
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
super('/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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class MockLeaderboardDataSource extends BaseMockDataSource<any, any> implements ILeaderboardDataSource {
|
|
|
|
|
|
/** Mock数据源名称 */
|
|
|
|
|
|
readonly __MOCK_NAME__ = 'MockLeaderboardDataSource';
|
|
|
|
|
|
|
|
|
|
|
|
/** Mock数据 */
|
|
|
|
|
|
protected mockData: any[] = [];
|
|
|
|
|
|
|
2026-03-19 01:39:34 +08:00
|
|
|
|
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> {
|
2026-03-19 14:19:01 +08:00
|
|
|
|
await this.delay(500);
|
2026-03-19 01:39:34 +08:00
|
|
|
|
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> {
|
2026-03-19 14:19:01 +08:00
|
|
|
|
await this.delay(300);
|
2026-03-19 01:39:34 +08:00
|
|
|
|
return {
|
|
|
|
|
|
revenue: { rank: 15, percentile: 85 },
|
|
|
|
|
|
roi: { rank: 8, percentile: 92 },
|
|
|
|
|
|
growth: { rank: 22, percentile: 78 },
|
|
|
|
|
|
period,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
export const leaderboardDataSource = DataSourceFactory.createWithMethods<
|
|
|
|
|
|
any,
|
|
|
|
|
|
any,
|
|
|
|
|
|
ILeaderboardDataSource
|
|
|
|
|
|
>({
|
|
|
|
|
|
apiDataSource: ApiLeaderboardDataSource,
|
|
|
|
|
|
mockDataSource: MockLeaderboardDataSource,
|
|
|
|
|
|
});
|
2026-03-19 01:39:34 +08:00
|
|
|
|
|
2026-03-19 14:19:01 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* Mock状态标记
|
|
|
|
|
|
* 用于调试和开发环境识别
|
|
|
|
|
|
*/
|
|
|
|
|
|
export { __MOCK__, __DATA_SOURCE_TYPE__ } from './dataSourceFactory';
|