Files
makemd/dashboard/src/services/logisticsDataSource.ts
wurenzhi 0dac26d781 feat: 添加MSW模拟服务和数据源集成
refactor: 重构页面组件移除冗余Layout组件

feat: 实现WebSocket和事件总线系统

feat: 添加队列和调度系统

docs: 更新架构文档和服务映射

style: 清理重复接口定义使用数据源

chore: 更新依赖项配置

feat: 添加运行时系统和领域引导

ci: 配置ESLint边界检查规则

build: 添加Redis和WebSocket依赖

test: 添加MSW浏览器环境入口

perf: 优化数据获取逻辑使用统一数据源

fix: 修复类型定义和状态管理问题
2026-03-19 01:39:34 +08:00

252 lines
9.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* [MOCK] 物流管理数据源
* AI注意: 这是Mock实现不是真实业务逻辑
* 仅在USE_MOCK=true时启用
*/
export interface LogisticsProvider {
id: string;
name: string;
code: string;
status: 'ACTIVE' | 'INACTIVE';
apiEndpoint?: string;
createdAt: string;
updatedAt: string;
}
export interface Shipment {
id: string;
orderId: string;
trackingNumber: string;
provider: string;
status: 'PENDING' | 'PICKED_UP' | 'IN_TRANSIT' | 'OUT_FOR_DELIVERY' | 'DELIVERED' | 'FAILED';
origin: string;
destination: string;
estimatedDelivery: string;
actualDelivery?: string;
createdAt: string;
updatedAt: string;
}
export interface TrackingEvent {
id: string;
shipmentId: string;
status: string;
location: string;
description: string;
timestamp: string;
}
export interface ILogisticsDataSource {
fetchProviders(): Promise<LogisticsProvider[]>;
createProvider(data: Partial<LogisticsProvider>): Promise<LogisticsProvider>;
updateProvider(id: string, data: Partial<LogisticsProvider>): Promise<LogisticsProvider>;
deleteProvider(id: string): Promise<void>;
fetchShipments(params?: { status?: string; provider?: string }): Promise<Shipment[]>;
createShipment(data: Partial<Shipment>): Promise<Shipment>;
updateShipment(id: string, data: Partial<Shipment>): Promise<Shipment>;
fetchTrackingEvents(shipmentId: string): Promise<TrackingEvent[]>;
calculateFreight(params: { origin: string; destination: string; weight: number; dimensions: { length: number; width: number; height: number } }): Promise<{ provider: string; cost: number; estimatedDays: number }[]>;
}
class MockLogisticsDataSource implements ILogisticsDataSource {
private providers: LogisticsProvider[] = [
{ id: '1', name: 'FedEx', code: 'FEDEX', status: 'ACTIVE', createdAt: '2026-03-01', updatedAt: '2026-03-01' },
{ id: '2', name: 'UPS', code: 'UPS', status: 'ACTIVE', createdAt: '2026-03-01', updatedAt: '2026-03-01' },
{ id: '3', name: 'DHL', code: 'DHL', status: 'ACTIVE', createdAt: '2026-03-01', updatedAt: '2026-03-01' },
];
private shipments: Shipment[] = [
{
id: '1',
orderId: 'ORD-2026-001',
trackingNumber: 'FX123456789',
provider: 'FEDEX',
status: 'IN_TRANSIT',
origin: 'Los Angeles, CA',
destination: 'New York, NY',
estimatedDelivery: '2026-03-20',
createdAt: '2026-03-15',
updatedAt: '2026-03-16',
},
];
private trackingEvents: TrackingEvent[] = [
{ id: '1', shipmentId: '1', status: 'PICKED_UP', location: 'Los Angeles, CA', description: 'Package picked up', timestamp: '2026-03-15T10:00:00Z' },
{ id: '2', shipmentId: '1', status: 'IN_TRANSIT', location: 'Phoenix, AZ', description: 'In transit', timestamp: '2026-03-16T08:00:00Z' },
];
async fetchProviders(): Promise<LogisticsProvider[]> {
await new Promise(resolve => setTimeout(resolve, 300));
return [...this.providers];
}
async createProvider(data: Partial<LogisticsProvider>): Promise<LogisticsProvider> {
await new Promise(resolve => setTimeout(resolve, 300));
const newProvider: LogisticsProvider = {
id: `${Date.now()}`,
name: data.name || '',
code: data.code || '',
status: 'ACTIVE',
createdAt: new Date().toISOString().split('T')[0],
updatedAt: new Date().toISOString().split('T')[0],
...data,
};
this.providers.push(newProvider);
return newProvider;
}
async updateProvider(id: string, data: Partial<LogisticsProvider>): Promise<LogisticsProvider> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.providers.findIndex(p => p.id === id);
if (index === -1) throw new Error('Provider not found');
this.providers[index] = { ...this.providers[index], ...data, updatedAt: new Date().toISOString().split('T')[0] };
return this.providers[index];
}
async deleteProvider(id: string): Promise<void> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.providers.findIndex(p => p.id === id);
if (index !== -1) {
this.providers.splice(index, 1);
}
}
async fetchShipments(params?: { status?: string; provider?: string }): Promise<Shipment[]> {
await new Promise(resolve => setTimeout(resolve, 300));
let result = [...this.shipments];
if (params?.status) {
result = result.filter(s => s.status === params.status);
}
if (params?.provider) {
result = result.filter(s => s.provider === params.provider);
}
return result;
}
async createShipment(data: Partial<Shipment>): Promise<Shipment> {
await new Promise(resolve => setTimeout(resolve, 300));
const newShipment: Shipment = {
id: `${Date.now()}`,
orderId: data.orderId || '',
trackingNumber: `FX${Date.now()}`,
provider: data.provider || 'FEDEX',
status: 'PENDING',
origin: data.origin || '',
destination: data.destination || '',
estimatedDelivery: data.estimatedDelivery || '',
createdAt: new Date().toISOString().split('T')[0],
updatedAt: new Date().toISOString().split('T')[0],
...data,
};
this.shipments.push(newShipment);
return newShipment;
}
async updateShipment(id: string, data: Partial<Shipment>): Promise<Shipment> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.shipments.findIndex(s => s.id === id);
if (index === -1) throw new Error('Shipment not found');
this.shipments[index] = { ...this.shipments[index], ...data, updatedAt: new Date().toISOString().split('T')[0] };
return this.shipments[index];
}
async fetchTrackingEvents(shipmentId: string): Promise<TrackingEvent[]> {
await new Promise(resolve => setTimeout(resolve, 300));
return this.trackingEvents.filter(e => e.shipmentId === shipmentId);
}
async calculateFreight(params: { origin: string; destination: string; weight: number; dimensions: { length: number; width: number; height: number } }): Promise<{ provider: string; cost: number; estimatedDays: number }[]> {
await new Promise(resolve => setTimeout(resolve, 500));
return [
{ provider: 'FEDEX', cost: 15.99, estimatedDays: 3 },
{ provider: 'UPS', cost: 18.50, estimatedDays: 2 },
{ provider: 'DHL', cost: 22.00, estimatedDays: 1 },
];
}
}
class ApiLogisticsDataSource implements ILogisticsDataSource {
private baseUrl = '/api/logistics';
async fetchProviders(): Promise<LogisticsProvider[]> {
const response = await fetch(`${this.baseUrl}/providers`);
if (!response.ok) throw new Error('Failed to fetch providers');
return response.json();
}
async createProvider(data: Partial<LogisticsProvider>): Promise<LogisticsProvider> {
const response = await fetch(`${this.baseUrl}/providers`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to create provider');
return response.json();
}
async updateProvider(id: string, data: Partial<LogisticsProvider>): Promise<LogisticsProvider> {
const response = await fetch(`${this.baseUrl}/providers/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to update provider');
return response.json();
}
async deleteProvider(id: string): Promise<void> {
const response = await fetch(`${this.baseUrl}/providers/${id}`, { method: 'DELETE' });
if (!response.ok) throw new Error('Failed to delete provider');
}
async fetchShipments(params?: { status?: string; provider?: string }): Promise<Shipment[]> {
const response = await fetch(`${this.baseUrl}/shipments?${new URLSearchParams(params as any)}`);
if (!response.ok) throw new Error('Failed to fetch shipments');
return response.json();
}
async createShipment(data: Partial<Shipment>): Promise<Shipment> {
const response = await fetch(`${this.baseUrl}/shipments`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to create shipment');
return response.json();
}
async updateShipment(id: string, data: Partial<Shipment>): Promise<Shipment> {
const response = await fetch(`${this.baseUrl}/shipments/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to update shipment');
return response.json();
}
async fetchTrackingEvents(shipmentId: string): Promise<TrackingEvent[]> {
const response = await fetch(`${this.baseUrl}/shipments/${shipmentId}/tracking`);
if (!response.ok) throw new Error('Failed to fetch tracking events');
return response.json();
}
async calculateFreight(params: { origin: string; destination: string; weight: number; dimensions: { length: number; width: number; height: number } }): Promise<{ provider: string; cost: number; estimatedDays: number }[]> {
const response = await fetch(`${this.baseUrl}/freight/calculate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params),
});
if (!response.ok) throw new Error('Failed to calculate freight');
return response.json();
}
}
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
export const logisticsDataSource: ILogisticsDataSource = useMock
? new MockLogisticsDataSource()
: new ApiLogisticsDataSource();