113 lines
4.4 KiB
TypeScript
113 lines
4.4 KiB
TypeScript
|
|
/**
|
||
|
|
* [MOCK-MARKETING] Marketing模块DataSource
|
||
|
|
*/
|
||
|
|
|
||
|
|
export interface Ad {
|
||
|
|
id: string;
|
||
|
|
name: string;
|
||
|
|
platform: string;
|
||
|
|
campaign: string;
|
||
|
|
status: 'active' | 'paused' | 'ended';
|
||
|
|
budget: number;
|
||
|
|
spent: number;
|
||
|
|
clicks: number;
|
||
|
|
impressions: number;
|
||
|
|
conversions: number;
|
||
|
|
ctr: number;
|
||
|
|
cpc: number;
|
||
|
|
roas: number;
|
||
|
|
startDate: string;
|
||
|
|
endDate?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface Competitor {
|
||
|
|
id: string;
|
||
|
|
name: string;
|
||
|
|
platform: string;
|
||
|
|
products: number;
|
||
|
|
avgPrice: number;
|
||
|
|
avgRating: number;
|
||
|
|
reviewCount: number;
|
||
|
|
lastUpdated: string;
|
||
|
|
trackedProducts: string[];
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface IMarketingDataSource {
|
||
|
|
fetchAds(params?: { platform?: string; status?: string }): Promise<Ad[]>;
|
||
|
|
updateAd(id: string, data: Partial<Ad>): Promise<Ad>;
|
||
|
|
|
||
|
|
fetchCompetitors(): Promise<Competitor[]>;
|
||
|
|
addCompetitor(data: Partial<Competitor>): Promise<Competitor>;
|
||
|
|
removeCompetitor(id: string): Promise<void>;
|
||
|
|
analyzeCompetitor(id: string): Promise<any>;
|
||
|
|
}
|
||
|
|
|
||
|
|
class MockMarketingDataSource implements IMarketingDataSource {
|
||
|
|
async fetchAds(params?: { platform?: string; status?: string }): Promise<Ad[]> {
|
||
|
|
return [
|
||
|
|
{ id: 'ad_001', name: 'Smart Watch Promo', platform: 'AMAZON', campaign: 'Spring Sale', status: 'active', budget: 500, spent: 325.50, clicks: 1250, impressions: 45000, conversions: 45, ctr: 2.78, cpc: 0.26, roas: 3.2, startDate: '2026-03-01' },
|
||
|
|
{ id: 'ad_002', name: 'Headphones Deal', platform: 'AMAZON', campaign: 'Spring Sale', status: 'active', budget: 300, spent: 180.25, clicks: 890, impressions: 32000, conversions: 32, ctr: 2.78, cpc: 0.20, roas: 2.8, startDate: '2026-03-05' },
|
||
|
|
{ id: 'ad_003', name: 'USB Cable Bundle', platform: 'EBAY', campaign: 'Clearance', status: 'paused', budget: 200, spent: 150.00, clicks: 600, impressions: 25000, conversions: 20, ctr: 2.40, cpc: 0.25, roas: 2.1, startDate: '2026-02-15', endDate: '2026-03-15' },
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
async updateAd(id: string, data: Partial<Ad>): Promise<Ad> {
|
||
|
|
return { id, ...data } as Ad;
|
||
|
|
}
|
||
|
|
|
||
|
|
async fetchCompetitors(): Promise<Competitor[]> {
|
||
|
|
return [
|
||
|
|
{ id: 'comp_001', name: 'TechGadget Pro', platform: 'AMAZON', products: 156, avgPrice: 45.99, avgRating: 4.3, reviewCount: 12500, lastUpdated: '2026-03-18', trackedProducts: ['SKU-001', 'SKU-002'] },
|
||
|
|
{ id: 'comp_002', name: 'ElectroMart', platform: 'AMAZON', products: 89, avgPrice: 38.50, avgRating: 4.1, reviewCount: 8900, lastUpdated: '2026-03-17', trackedProducts: ['SKU-003'] },
|
||
|
|
{ id: 'comp_003', name: 'GadgetWorld', platform: 'EBAY', products: 234, avgPrice: 32.00, avgRating: 4.5, reviewCount: 15600, lastUpdated: '2026-03-16', trackedProducts: [] },
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
async addCompetitor(data: Partial<Competitor>): Promise<Competitor> {
|
||
|
|
return { ...data, id: `comp_${Date.now()}`, lastUpdated: new Date().toISOString() } as Competitor;
|
||
|
|
}
|
||
|
|
|
||
|
|
async removeCompetitor(id: string): Promise<void> {}
|
||
|
|
|
||
|
|
async analyzeCompetitor(id: string): Promise<any> {
|
||
|
|
return { pricingTrend: 'stable', topProducts: [], marketShare: 15 };
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class ApiMarketingDataSource implements IMarketingDataSource {
|
||
|
|
private baseUrl = '/api/marketing';
|
||
|
|
|
||
|
|
async fetchAds(params?: { platform?: string; status?: string }): Promise<Ad[]> {
|
||
|
|
const query = new URLSearchParams(params as any).toString();
|
||
|
|
const res = await fetch(`${this.baseUrl}/ads?${query}`);
|
||
|
|
return res.json();
|
||
|
|
}
|
||
|
|
|
||
|
|
async updateAd(id: string, data: Partial<Ad>): Promise<Ad> {
|
||
|
|
const res = await fetch(`${this.baseUrl}/ads/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) });
|
||
|
|
return res.json();
|
||
|
|
}
|
||
|
|
|
||
|
|
async fetchCompetitors(): Promise<Competitor[]> {
|
||
|
|
const res = await fetch(`${this.baseUrl}/competitors`);
|
||
|
|
return res.json();
|
||
|
|
}
|
||
|
|
|
||
|
|
async addCompetitor(data: Partial<Competitor>): Promise<Competitor> {
|
||
|
|
const res = await fetch(`${this.baseUrl}/competitors`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) });
|
||
|
|
return res.json();
|
||
|
|
}
|
||
|
|
|
||
|
|
async removeCompetitor(id: string): Promise<void> {
|
||
|
|
await fetch(`${this.baseUrl}/competitors/${id}`, { method: 'DELETE' });
|
||
|
|
}
|
||
|
|
|
||
|
|
async analyzeCompetitor(id: string): Promise<any> {
|
||
|
|
const res = await fetch(`${this.baseUrl}/competitors/${id}/analyze`);
|
||
|
|
return res.json();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
|
||
|
|
export const marketingDataSource: IMarketingDataSource = useMock ? new MockMarketingDataSource() : new ApiMarketingDataSource();
|