/** * 统一 DataSource 工厂模式 * 消除前端数据源重复代码,提供统一的创建和管理机制 */ import { IDataSource } from '@/types/datasource'; // 环境变量判断 const useMock = process.env.REACT_APP_USE_MOCK === 'true'; /** * 基础 DataSource 抽象类 * 提供通用的 CRUD 方法实现 */ export abstract class BaseDataSource implements IDataSource { protected baseUrl: string; constructor(baseUrl: string) { this.baseUrl = baseUrl; } async list(params?: P): Promise { const query = this.buildQueryParams(params); const response = await fetch(`${this.baseUrl}?${query}`, { headers: { 'Content-Type': 'application/json', }, }); if (!response.ok) { throw new Error(`API Error: ${response.status}`); } const result = await response.json(); return result.data || []; } async detail(id: string): Promise { const response = await fetch(`${this.baseUrl}/${id}`, { headers: { 'Content-Type': 'application/json', }, }); if (!response.ok) { if (response.status === 404) return null; throw new Error(`API Error: ${response.status}`); } const result = await response.json(); return result.data || null; } async create(data: Partial): Promise { const response = await fetch(this.baseUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); if (!response.ok) { throw new Error(`API Error: ${response.status}`); } const result = await response.json(); // 创建成功后获取完整数据 if (result.data?.id) { const created = await this.detail(result.data.id); if (created) return created; } return result.data; } async update(id: string, data: Partial): Promise { const response = await fetch(`${this.baseUrl}/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); if (!response.ok) { throw new Error(`API Error: ${response.status}`); } const result = await response.json(); // 更新成功后获取完整数据 const updated = await this.detail(id); if (updated) return updated; return result.data; } async delete(id: string): Promise { const response = await fetch(`${this.baseUrl}/${id}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', }, }); if (!response.ok) { throw new Error(`API Error: ${response.status}`); } } /** * 构建查询参数 */ protected buildQueryParams(params?: P): string { const query = new URLSearchParams(); if (params) { Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null) { query.append(key, String(value)); } }); } return query.toString(); } /** * 模拟延迟(用于 Mock 实现) */ protected delay(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } } /** * 基础 Mock DataSource 类 */ export abstract class BaseMockDataSource implements IDataSource { /** Mock标记 */ readonly __MOCK__ = true as const; /** Mock数据源名称 */ abstract readonly __MOCK_NAME__: string; /** Mock数据 */ protected abstract mockData: T[]; async list(params?: P): Promise { await this.delay(200); return this.mockData; } async detail(id: string): Promise { await this.delay(100); return this.mockData.find(item => (item as any).id === id) || null; } async create(data: Partial): Promise { await this.delay(300); const newItem = { id: `${Date.now()}`, ...data, } as T; this.mockData.unshift(newItem); return newItem; } async update(id: string, data: Partial): Promise { await this.delay(300); const index = this.mockData.findIndex(item => (item as any).id === id); if (index === -1) { throw new Error('Item not found'); } this.mockData[index] = { ...this.mockData[index], ...data }; return this.mockData[index]; } async delete(id: string): Promise { await this.delay(200); this.mockData = this.mockData.filter(item => (item as any).id !== id); } /** * 模拟延迟 */ protected delay(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } } /** * DataSource 工厂类 * 负责根据环境变量创建相应的 DataSource 实例 */ export class DataSourceFactory { /** * 创建 DataSource 实例 * @param apiDataSource API实现类 * @param mockDataSource Mock实现类 * @returns DataSource 实例 */ static create( apiDataSource: new () => IDataSource, mockDataSource: new () => IDataSource ): IDataSource { return useMock ? new mockDataSource() : new apiDataSource(); } /** * 创建带有自定义方法的 DataSource 实例 * @param apiDataSource API实现类 * @param mockDataSource Mock实现类 * @returns DataSource 实例 */ static createWithMethods>({ apiDataSource, mockDataSource, }: { apiDataSource: new () => IDataSource & M; mockDataSource: new () => IDataSource & M; }): IDataSource & M { return useMock ? new mockDataSource() : new apiDataSource(); } } /** * Mock状态标记 * 用于调试和开发环境识别 */ export const __MOCK__ = useMock; /** * 当前数据源类型 */ export const __DATA_SOURCE_TYPE__ = useMock ? 'mock' : 'api';