/** * [MOCK-002] 证书数据源抽象层 * 通过环境变量自动切换Mock/真实API * AI注意: 这是唯一入口,业务代码必须调用此层 * * @module services/certificateDataSource * @author AI-Frontend-Team * @created 2026-03-19 */ import { Certificate } from '@/types/certificate'; import { IDataSource, CertificateQueryParams } from '@/types/datasource'; // ============================================ // 真实API实现 // ============================================ /** * 证书API数据源 * 调用真实后端API */ class ApiCertificateDataSource implements IDataSource { private baseUrl = '/api/v1/certificate'; async list(params?: CertificateQueryParams): Promise { const query = new URLSearchParams(); if (params?.status) query.append('status', params.status); if (params?.type) query.append('type', params.type); if (params?.keyword) query.append('keyword', params.keyword); if (params?.page) query.append('page', params.page.toString()); if (params?.pageSize) query.append('pageSize', params.pageSize.toString()); const response = await fetch(`${this.baseUrl}/certificates?${query.toString()}`, { 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}/certificates/${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}/certificates`, { 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}/certificates/${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}/certificates/${id}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json', }, }); if (!response.ok) { throw new Error(`API Error: ${response.status}`); } } /** * 更新证书状态(审核) * @param id 证书ID * @param status 新状态 * @param approvedBy 审核人 */ async updateStatus(id: string, status: string, approvedBy?: string): Promise { const response = await fetch(`${this.baseUrl}/certificates/${id}/status`, { method: 'PUT', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ status, approvedBy }), }); 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; } } // ============================================ // Mock实现 (完全独立文件) // ============================================ /** * [MOCK] 证书Mock数据源 * AI注意: 这是Mock实现,不是真实业务逻辑 * 仅在REACT_APP_USE_MOCK=true时启用 */ class MockCertificateDataSource implements IDataSource { /** Mock标记 */ readonly __MOCK__ = true as const; /** Mock数据源名称 */ readonly __MOCK_NAME__ = 'MockCertificateDataSource'; private mockData: Certificate[] = [ { id: '1', name: 'CE认证证书', type: 'PRODUCT_CERT', status: 'APPROVED', fileUrl: '/files/ce-cert.pdf', fileName: 'CE-Certificate-2026.pdf', uploadDate: '2026-03-15', expiryDate: '2027-03-15', approvedBy: 'admin', approvedDate: '2026-03-16', productId: 'P001', productName: '工业温度传感器', notes: '欧盟市场准入认证', }, { id: '2', name: '营业执照', type: 'BUSINESS_LICENSE', status: 'APPROVED', fileUrl: '/files/business-license.pdf', fileName: 'Business-License-2026.pdf', uploadDate: '2026-01-10', expiryDate: '2027-01-10', approvedBy: 'admin', approvedDate: '2026-01-11', notes: '企业营业执照', }, { id: '3', name: 'FCC认证', type: 'SAFETY_CERT', status: 'PENDING', fileUrl: '/files/fcc-cert.pdf', fileName: 'FCC-Certificate.pdf', uploadDate: '2026-03-18', expiryDate: '2027-03-18', productId: 'P002', productName: 'PLC控制器', notes: '美国FCC认证', }, { id: '4', name: 'ISO9001', type: 'QUALITY_CERT', status: 'EXPIRED', fileUrl: '/files/iso9001.pdf', fileName: 'ISO9001-2025.pdf', uploadDate: '2025-01-01', expiryDate: '2026-01-01', approvedBy: 'admin', approvedDate: '2025-01-02', notes: '质量管理体系认证,已过期需要更新', }, { id: '5', name: 'RoHS认证', type: 'PRODUCT_CERT', status: 'APPROVED', fileUrl: '/files/rohs-cert.pdf', fileName: 'RoHS-Certificate.pdf', uploadDate: '2026-02-20', expiryDate: '2027-02-20', approvedBy: 'admin', approvedDate: '2026-02-21', productId: 'P003', productName: '环保型传感器', notes: '欧盟RoHS环保认证', }, { id: '6', name: 'UL认证', type: 'SAFETY_CERT', status: 'PENDING', fileUrl: '/files/ul-cert.pdf', fileName: 'UL-Certificate.pdf', uploadDate: '2026-03-19', expiryDate: '2027-03-19', productId: 'P004', productName: '工业电源模块', notes: '美国UL安全认证', }, ]; private delay(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); } async list(params?: CertificateQueryParams): Promise { // 模拟网络延迟 await this.delay(300); let result = [...this.mockData]; // 状态筛选 if (params?.status) { result = result.filter(item => item.status === params.status); } // 类型筛选 if (params?.type) { result = result.filter(item => item.type === params.type); } // 关键词搜索 if (params?.keyword) { const keyword = params.keyword.toLowerCase(); result = result.filter( item => item.name.toLowerCase().includes(keyword) || item.productName?.toLowerCase().includes(keyword) || item.notes?.toLowerCase().includes(keyword) ); } // 分页 const page = params?.page || 1; const pageSize = params?.pageSize || 10; const start = (page - 1) * pageSize; const end = start + pageSize; return result.slice(start, end); } async detail(id: string): Promise { await this.delay(200); return this.mockData.find(item => item.id === id) || null; } async create(data: Partial): Promise { await this.delay(500); const newCert: Certificate = { id: `${Date.now()}`, name: data.name || '', type: data.type || 'OTHER', status: 'PENDING', fileUrl: data.fileUrl || '/files/uploaded.pdf', fileName: data.fileName || 'uploaded.pdf', uploadDate: new Date().toISOString().split('T')[0], expiryDate: data.expiryDate || '', productId: data.productId, productName: data.productName, notes: data.notes, }; this.mockData.unshift(newCert); return newCert; } async update(id: string, data: Partial): Promise { await this.delay(300); const index = this.mockData.findIndex(item => item.id === id); if (index === -1) { throw new Error('Certificate 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.id !== id); } async updateStatus(id: string, status: string, approvedBy?: string): Promise { await this.delay(300); const index = this.mockData.findIndex(item => item.id === id); if (index === -1) { throw new Error('Certificate not found'); } const updates: Partial = { status: status as any, }; if (status === 'APPROVED') { updates.approvedBy = approvedBy || 'admin'; updates.approvedDate = new Date().toISOString().split('T')[0]; } this.mockData[index] = { ...this.mockData[index], ...updates }; return this.mockData[index]; } } // ============================================ // 导出数据源实例 (环境变量控制) // ============================================ const useMock = process.env.REACT_APP_USE_MOCK === 'true'; /** * 证书数据源实例 * 根据环境变量自动切换Mock/真实API * * 使用示例: * ```typescript * import { certificateDataSource } from '@/services/certificateDataSource'; * * // 查询列表 * const certificates = await certificateDataSource.list({ status: 'APPROVED' }); * * // 获取详情 * const cert = await certificateDataSource.detail('1'); * * // 创建 * const newCert = await certificateDataSource.create({ name: '新证书', ... }); * ``` */ export const certificateDataSource: IDataSource & { updateStatus?(id: string, status: string, approvedBy?: string): Promise; } = useMock ? new MockCertificateDataSource() : new ApiCertificateDataSource(); /** * Mock状态标记 * 用于调试和开发环境识别 */ export const __MOCK__ = useMock; /** * 当前数据源类型 */ export const __DATA_SOURCE_TYPE__ = useMock ? 'mock' : 'api';