feat: 添加MSW模拟服务和数据源集成

refactor: 重构页面组件移除冗余Layout组件

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

feat: 添加队列和调度系统

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

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

chore: 更新依赖项配置

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

ci: 配置ESLint边界检查规则

build: 添加Redis和WebSocket依赖

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

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

fix: 修复类型定义和状态管理问题
This commit is contained in:
2026-03-19 01:39:34 +08:00
parent cd55097dbf
commit 0dac26d781
176 changed files with 47075 additions and 8404 deletions

View File

@@ -0,0 +1,371 @@
/**
* [MOCK] 商户管理数据源
* AI注意: 这是Mock实现不是真实业务逻辑
* 仅在USE_MOCK=true时启用
*/
export interface Merchant {
id: string;
tenantId: string;
companyName: string;
businessLicense: string;
contactEmail: string;
contactPhone: string;
status: 'PENDING' | 'ACTIVE' | 'SUSPENDED' | 'TERMINATED';
tier: 'BASIC' | 'PRO' | 'ENTERPRISE';
traceId: string;
createdAt: string;
updatedAt: string;
}
export interface MerchantShop {
id: string;
merchantId: string;
shopName: string;
platform: string;
shopUrl: string;
status: 'ACTIVE' | 'INACTIVE' | 'SUSPENDED';
createdAt: string;
updatedAt: string;
}
export interface MerchantOrder {
id: string;
merchantId: string;
orderId: string;
totalAmount: number;
status: string;
createdAt: string;
}
export interface MerchantSettlement {
id: string;
merchantId: string;
merchantName: string;
periodStart: string;
periodEnd: string;
totalAmount: number;
status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED';
createdAt: string;
updatedAt: string;
}
export interface IMerchantDataSource {
fetchMerchants(params?: { status?: string; tier?: string; search?: string }): Promise<Merchant[]>;
createMerchant(data: Partial<Merchant>): Promise<Merchant>;
updateMerchant(id: string, data: Partial<Merchant>): Promise<Merchant>;
deleteMerchant(id: string): Promise<void>;
fetchShops(params?: { merchantId?: string; platform?: string; status?: string }): Promise<MerchantShop[]>;
createShop(data: Partial<MerchantShop>): Promise<MerchantShop>;
updateShop(id: string, data: Partial<MerchantShop>): Promise<MerchantShop>;
deleteShop(id: string): Promise<void>;
fetchMerchantOrders(merchantId: string, params?: { status?: string }): Promise<MerchantOrder[]>;
fetchSettlements(params?: { merchantId?: string; status?: string }): Promise<MerchantSettlement[]>;
processSettlement(id: string, action: 'APPROVE' | 'REJECT'): Promise<MerchantSettlement>;
}
class MockMerchantDataSource implements IMerchantDataSource {
private merchants: Merchant[] = [
{
id: '1',
tenantId: 'tenant_001',
companyName: 'Test Company A',
businessLicense: 'BL-001',
contactEmail: 'contact@company-a.com',
contactPhone: '+1 (123) 456-7890',
status: 'ACTIVE',
tier: 'ENTERPRISE',
traceId: 'trace_001',
createdAt: '2026-03-01',
updatedAt: '2026-03-01',
},
{
id: '2',
tenantId: 'tenant_002',
companyName: 'Test Company B',
businessLicense: 'BL-002',
contactEmail: 'contact@company-b.com',
contactPhone: '+1 (234) 567-8901',
status: 'ACTIVE',
tier: 'PRO',
traceId: 'trace_002',
createdAt: '2026-03-05',
updatedAt: '2026-03-05',
},
];
private shops: MerchantShop[] = [
{
id: '1',
merchantId: '1',
shopName: 'Shop A - Amazon',
platform: 'Amazon',
shopUrl: 'https://amazon.com/shop-a',
status: 'ACTIVE',
createdAt: '2026-03-01',
updatedAt: '2026-03-01',
},
{
id: '2',
merchantId: '1',
shopName: 'Shop A - Shopify',
platform: 'Shopify',
shopUrl: 'https://shop-a.myshopify.com',
status: 'ACTIVE',
createdAt: '2026-03-02',
updatedAt: '2026-03-02',
},
];
private orders: MerchantOrder[] = [
{
id: '1',
merchantId: '1',
orderId: 'ORD-2026-001',
totalAmount: 1500.00,
status: 'COMPLETED',
createdAt: '2026-03-15',
},
];
async fetchMerchants(params?: { status?: string; tier?: string; search?: string }): Promise<Merchant[]> {
await new Promise(resolve => setTimeout(resolve, 300));
let result = [...this.merchants];
if (params?.status) {
result = result.filter(m => m.status === params.status);
}
if (params?.tier) {
result = result.filter(m => m.tier === params.tier);
}
if (params?.search) {
result = result.filter(m => m.companyName.toLowerCase().includes(params.search!.toLowerCase()));
}
return result;
}
async createMerchant(data: Partial<Merchant>): Promise<Merchant> {
await new Promise(resolve => setTimeout(resolve, 300));
const newMerchant: Merchant = {
id: `${Date.now()}`,
tenantId: `tenant_${Date.now()}`,
companyName: data.companyName || '',
businessLicense: data.businessLicense || '',
contactEmail: data.contactEmail || '',
contactPhone: data.contactPhone || '',
status: 'PENDING',
tier: 'BASIC',
traceId: `trace_${Date.now()}`,
createdAt: new Date().toISOString().split('T')[0],
updatedAt: new Date().toISOString().split('T')[0],
...data,
};
this.merchants.push(newMerchant);
return newMerchant;
}
async updateMerchant(id: string, data: Partial<Merchant>): Promise<Merchant> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.merchants.findIndex(m => m.id === id);
if (index === -1) throw new Error('Merchant not found');
this.merchants[index] = { ...this.merchants[index], ...data, updatedAt: new Date().toISOString().split('T')[0] };
return this.merchants[index];
}
async deleteMerchant(id: string): Promise<void> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.merchants.findIndex(m => m.id === id);
if (index !== -1) {
this.merchants.splice(index, 1);
}
}
async fetchShops(params?: { merchantId?: string; platform?: string; status?: string }): Promise<MerchantShop[]> {
await new Promise(resolve => setTimeout(resolve, 300));
let result = [...this.shops];
if (params?.merchantId) {
result = result.filter(s => s.merchantId === params.merchantId);
}
if (params?.platform) {
result = result.filter(s => s.platform === params.platform);
}
if (params?.status) {
result = result.filter(s => s.status === params.status);
}
return result;
}
async createShop(data: Partial<MerchantShop>): Promise<MerchantShop> {
await new Promise(resolve => setTimeout(resolve, 300));
const newShop: MerchantShop = {
id: `${Date.now()}`,
merchantId: data.merchantId || '',
shopName: data.shopName || '',
platform: data.platform || '',
shopUrl: data.shopUrl || '',
status: 'ACTIVE',
createdAt: new Date().toISOString().split('T')[0],
updatedAt: new Date().toISOString().split('T')[0],
...data,
};
this.shops.push(newShop);
return newShop;
}
async updateShop(id: string, data: Partial<MerchantShop>): Promise<MerchantShop> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.shops.findIndex(s => s.id === id);
if (index === -1) throw new Error('Shop not found');
this.shops[index] = { ...this.shops[index], ...data, updatedAt: new Date().toISOString().split('T')[0] };
return this.shops[index];
}
async deleteShop(id: string): Promise<void> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.shops.findIndex(s => s.id === id);
if (index !== -1) {
this.shops.splice(index, 1);
}
}
async fetchMerchantOrders(merchantId: string, params?: { status?: string }): Promise<MerchantOrder[]> {
await new Promise(resolve => setTimeout(resolve, 300));
let result = this.orders.filter(o => o.merchantId === merchantId);
if (params?.status) {
result = result.filter(o => o.status === params.status);
}
return result;
}
private settlements: MerchantSettlement[] = [
{
id: '1',
merchantId: '1',
merchantName: 'Test Company A',
periodStart: '2026-03-01',
periodEnd: '2026-03-15',
totalAmount: 25000.00,
status: 'PENDING',
createdAt: '2026-03-16',
updatedAt: '2026-03-16',
},
];
async fetchSettlements(params?: { merchantId?: string; status?: string }): Promise<MerchantSettlement[]> {
await new Promise(resolve => setTimeout(resolve, 300));
let result = [...this.settlements];
if (params?.merchantId) {
result = result.filter(s => s.merchantId === params.merchantId);
}
if (params?.status) {
result = result.filter(s => s.status === params.status);
}
return result;
}
async processSettlement(id: string, action: 'APPROVE' | 'REJECT'): Promise<MerchantSettlement> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.settlements.findIndex(s => s.id === id);
if (index === -1) throw new Error('Settlement not found');
this.settlements[index] = {
...this.settlements[index],
status: action === 'APPROVE' ? 'COMPLETED' : 'FAILED',
updatedAt: new Date().toISOString().split('T')[0],
};
return this.settlements[index];
}
}
class ApiMerchantDataSource implements IMerchantDataSource {
private baseUrl = '/api/merchants';
async fetchMerchants(params?: { status?: string; tier?: string; search?: string }): Promise<Merchant[]> {
const response = await fetch(`${this.baseUrl}?${new URLSearchParams(params as any)}`);
if (!response.ok) throw new Error('Failed to fetch merchants');
return response.json();
}
async createMerchant(data: Partial<Merchant>): Promise<Merchant> {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to create merchant');
return response.json();
}
async updateMerchant(id: string, data: Partial<Merchant>): Promise<Merchant> {
const response = await fetch(`${this.baseUrl}/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to update merchant');
return response.json();
}
async deleteMerchant(id: string): Promise<void> {
const response = await fetch(`${this.baseUrl}/${id}`, { method: 'DELETE' });
if (!response.ok) throw new Error('Failed to delete merchant');
}
async fetchShops(params?: { merchantId?: string; platform?: string; status?: string }): Promise<MerchantShop[]> {
const response = await fetch(`${this.baseUrl}/shops?${new URLSearchParams(params as any)}`);
if (!response.ok) throw new Error('Failed to fetch shops');
return response.json();
}
async createShop(data: Partial<MerchantShop>): Promise<MerchantShop> {
const response = await fetch(`${this.baseUrl}/shops`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to create shop');
return response.json();
}
async updateShop(id: string, data: Partial<MerchantShop>): Promise<MerchantShop> {
const response = await fetch(`${this.baseUrl}/shops/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error('Failed to update shop');
return response.json();
}
async deleteShop(id: string): Promise<void> {
const response = await fetch(`${this.baseUrl}/shops/${id}`, { method: 'DELETE' });
if (!response.ok) throw new Error('Failed to delete shop');
}
async fetchMerchantOrders(merchantId: string, params?: { status?: string }): Promise<MerchantOrder[]> {
const response = await fetch(`${this.baseUrl}/${merchantId}/orders?${new URLSearchParams(params as any)}`);
if (!response.ok) throw new Error('Failed to fetch merchant orders');
return response.json();
}
async fetchSettlements(params?: { merchantId?: string; status?: string }): Promise<MerchantSettlement[]> {
const response = await fetch(`${this.baseUrl}/settlements?${new URLSearchParams(params as any)}`);
if (!response.ok) throw new Error('Failed to fetch settlements');
return response.json();
}
async processSettlement(id: string, action: 'APPROVE' | 'REJECT'): Promise<MerchantSettlement> {
const response = await fetch(`${this.baseUrl}/settlements/${id}/process`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action }),
});
if (!response.ok) throw new Error('Failed to process settlement');
return response.json();
}
}
const useMock = process.env.REACT_APP_USE_MOCK === 'true';
export const merchantDataSource: IMerchantDataSource = useMock
? new MockMerchantDataSource()
: new ApiMerchantDataSource();