refactor: 重构项目结构并优化类型定义

- 移除extension模块,将功能迁移至node-agent
- 修复类型导出问题,使用export type明确类型导出
- 统一数据库连接方式,从直接导入改为使用config/database
- 更新文档中的项目结构描述
- 添加多个服务的实用方法,如getForecast、getBalances等
- 修复类型错误和TS1205警告
- 优化RedisService调用方式
- 添加新的实体类型定义
- 更新审计日志格式,统一字段命名
This commit is contained in:
2026-03-21 15:04:06 +08:00
parent 888d3844f3
commit 15ee1758f5
286 changed files with 9110 additions and 21453 deletions

View File

@@ -35,6 +35,62 @@ export interface ReturnApplication {
updatedAt: string;
}
export interface CustomerServiceTicket {
id: string;
ticketId: string;
orderId: string;
customerId: string;
customerName: string;
customerEmail: string;
subject: string;
category: string;
priority: 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT';
status: 'OPEN' | 'IN_PROGRESS' | 'WAITING_CUSTOMER' | 'RESOLVED' | 'CLOSED';
assignedTo?: string;
platform?: string;
lastMessage?: string;
messageCount?: number;
createdAt: string;
updatedAt: string;
messages?: CustomerServiceMessage[];
}
export interface CustomerServiceMessage {
id: string;
ticketId: string;
sender: 'customer' | 'agent';
content: string;
createdAt: string;
}
export interface RefundRecord {
id: string;
orderId: string;
refundId: string;
customerId: string;
customerName: string;
amount: number;
currency: string;
reason: string;
status: 'PENDING' | 'APPROVED' | 'REJECTED' | 'PROCESSING' | 'COMPLETED' | 'FAILED';
createdAt: string;
updatedAt: string;
platform: string;
refundMethod: string;
transactionId?: string;
processedBy?: string;
remark?: string;
}
export interface ReturnFormData {
orderId: string;
returnReason: string;
returnDescription: string;
returnItems: string[];
images: string[];
contactPhone: string;
}
export interface AfterSalesQueryParams {
orderId?: string;
status?: string;
@@ -49,9 +105,12 @@ export interface AfterSalesQueryParams {
export interface IAfterSalesDataSource {
fetchOrderItems(orderId: string): Promise<OrderItem[]>;
submitReturn(data: Partial<ReturnApplication>): Promise<ReturnApplication>;
submitReturnApply(data: ReturnFormData): Promise<ReturnApplication>;
fetchReturnApplications(params?: AfterSalesQueryParams): Promise<ReturnApplication[]>;
fetchReturnDetail(id: string): Promise<ReturnApplication | null>;
updateReturnStatus(id: string, status: string): Promise<ReturnApplication>;
fetchCustomerServiceTickets(params?: AfterSalesQueryParams): Promise<CustomerServiceTicket[]>;
fetchRefundRecords(params?: AfterSalesQueryParams): Promise<RefundRecord[]>;
}
// ============================================
@@ -75,8 +134,18 @@ class ApiAfterSalesDataSource implements IAfterSalesDataSource {
return result.data;
}
async submitReturnApply(data: ReturnFormData): Promise<ReturnApplication> {
const response = await fetch('/api/v1/returns/apply', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();
return result.data;
}
async fetchReturnApplications(params?: AfterSalesQueryParams): Promise<ReturnApplication[]> {
const query = new URLSearchParams(params as any).toString();
const query = new URLSearchParams(params as Record<string, string>).toString();
const response = await fetch(`/api/v1/returns?${query}`);
const result = await response.json();
return result.data;
@@ -97,6 +166,20 @@ class ApiAfterSalesDataSource implements IAfterSalesDataSource {
const result = await response.json();
return result.data;
}
async fetchCustomerServiceTickets(params?: AfterSalesQueryParams): Promise<CustomerServiceTicket[]> {
const query = new URLSearchParams(params as Record<string, string>).toString();
const response = await fetch(`/api/v1/customer-service/tickets?${query}`);
const result = await response.json();
return result.data;
}
async fetchRefundRecords(params?: AfterSalesQueryParams): Promise<RefundRecord[]> {
const query = new URLSearchParams(params as Record<string, string>).toString();
const response = await fetch(`/api/v1/refunds?${query}`);
const result = await response.json();
return result.data;
}
}
// ============================================
@@ -190,6 +273,64 @@ class MockAfterSalesDataSource implements IAfterSalesDataSource {
return this.mockReturns[index];
}
async submitReturnApply(data: ReturnFormData): Promise<ReturnApplication> {
await this.simulateDelay(1000);
const newReturn: ReturnApplication = {
id: `RET-${Date.now()}`,
orderId: data.orderId,
returnReason: data.returnReason,
returnDescription: data.returnDescription,
returnItems: data.returnItems,
images: data.images,
contactPhone: data.contactPhone,
status: 'PENDING',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
this.mockReturns.push(newReturn);
return newReturn;
}
async fetchCustomerServiceTickets(params?: AfterSalesQueryParams): Promise<CustomerServiceTicket[]> {
await this.simulateDelay(300);
return [
{
id: 'TICKET-001',
orderId: 'order-001',
customerId: 'C001',
customerName: 'John Doe',
customerEmail: 'john@example.com',
subject: 'Product not received',
category: 'delivery',
priority: 'HIGH',
status: 'OPEN',
createdAt: '2026-03-18T10:00:00Z',
updatedAt: '2026-03-18T10:00:00Z',
},
];
}
async fetchRefundRecords(params?: AfterSalesQueryParams): Promise<RefundRecord[]> {
await this.simulateDelay(300);
return [
{
id: 'REFUND-001',
orderId: 'order-001',
refundId: 'RF-001',
customerId: 'C001',
customerName: 'John Doe',
amount: 59.98,
currency: 'USD',
reason: 'Defective product',
status: 'PENDING',
createdAt: '2026-03-18T10:00:00Z',
updatedAt: '2026-03-18T10:00:00Z',
platform: 'Amazon',
refundMethod: 'Original Payment',
},
];
}
private simulateDelay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}

View File

@@ -36,10 +36,12 @@ export interface BatchOrder {
totalItems: number;
totalAmount: number;
currency: string;
status: 'DRAFT' | 'PENDING_REVIEW' | 'CONFIRMED' | 'PROCESSING' | 'COMPLETED' | 'CANCELLED';
status: 'DRAFT' | 'PENDING_REVIEW' | 'CONFIRMED' | 'PROCESSING' | 'COMPLETED' | 'CANCELLED' | 'SUBMITTED';
createdAt: string;
validItems: number;
invalidItems: number;
items?: BatchOrderItem[];
estimatedDelivery?: string;
}
export interface Customer {
@@ -47,6 +49,7 @@ export interface Customer {
name: string;
company: string;
tier: 'BASIC' | 'PRO' | 'ENTERPRISE';
email?: string;
}
export interface BatchOrderQueryParams {
@@ -64,6 +67,37 @@ export interface BatchOrderStats {
totalAmount: number;
}
export interface Contract {
id: string;
contractId: string;
contractNumber?: string;
customerId: string;
customerName: string;
type: 'PURCHASE' | 'SALES' | 'SERVICE' | 'DISTRIBUTION' | 'OEM' | 'NDA';
title: string;
startDate: string;
endDate: string;
totalAmount: number;
totalValue?: number;
currency: string;
status: 'DRAFT' | 'PENDING_REVIEW' | 'ACTIVE' | 'EXPIRED' | 'TERMINATED' | 'RENEWED';
signedDate?: string;
signedBy?: string;
attachments?: string[];
terms?: string;
remark?: string;
createdAt: string;
updatedAt: string;
}
export interface ContractQueryParams {
customerId?: string;
status?: string;
type?: string;
startDate?: string;
endDate?: string;
}
// ============================================
// B2B Trade专用接口
// ============================================
@@ -77,6 +111,10 @@ export interface IB2BTradeDataSource {
approveBatchOrder(batchId: string): Promise<BatchOrder>;
validateItems(items: BatchOrderItem[]): Promise<BatchOrderItem[]>;
parseUploadFile(file: File, customerId: string): Promise<BatchOrderItem[]>;
fetchContracts(params?: ContractQueryParams): Promise<Contract[]>;
fetchContractDetail(contractId: string): Promise<Contract | null>;
createContract(data: Partial<Contract>): Promise<Contract>;
updateContract(contractId: string, data: Partial<Contract>): Promise<Contract>;
}
// ============================================
@@ -148,6 +186,39 @@ class ApiB2BTradeDataSource implements IB2BTradeDataSource {
const result = await response.json();
return result.data;
}
async fetchContracts(params?: ContractQueryParams): Promise<Contract[]> {
const query = new URLSearchParams(params as Record<string, string>).toString();
const response = await fetch(`/api/v1/b2b/contracts?${query}`);
const result = await response.json();
return result.data;
}
async fetchContractDetail(contractId: string): Promise<Contract | null> {
const response = await fetch(`/api/v1/b2b/contracts/${contractId}`);
const result = await response.json();
return result.data;
}
async createContract(data: Partial<Contract>): Promise<Contract> {
const response = await fetch('/api/v1/b2b/contracts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();
return result.data;
}
async updateContract(contractId: string, data: Partial<Contract>): Promise<Contract> {
const response = await fetch(`/api/v1/b2b/contracts/${contractId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await response.json();
return result.data;
}
}
// ============================================
@@ -291,6 +362,60 @@ class MockB2BTradeDataSource implements IB2BTradeDataSource {
];
}
async fetchContracts(params?: ContractQueryParams): Promise<Contract[]> {
await this.simulateDelay(400);
return [
{
id: '1',
contractId: 'CON-2026-001',
customerId: 'CUST_001',
customerName: 'ABC Trading Co.',
type: 'PURCHASE',
title: 'Annual Purchase Agreement',
startDate: '2026-01-01',
endDate: '2026-12-31',
totalAmount: 500000,
currency: 'USD',
status: 'ACTIVE',
createdAt: '2026-01-01',
updatedAt: '2026-01-01',
},
];
}
async fetchContractDetail(contractId: string): Promise<Contract | null> {
await this.simulateDelay(300);
const contracts = await this.fetchContracts();
return contracts.find(c => c.contractId === contractId) || null;
}
async createContract(data: Partial<Contract>): Promise<Contract> {
await this.simulateDelay(500);
const newContract: Contract = {
id: `${Date.now()}`,
contractId: `CON-${Date.now()}`,
customerId: data.customerId || '',
customerName: data.customerName || '',
type: data.type || 'PURCHASE',
title: data.title || '',
startDate: data.startDate || '',
endDate: data.endDate || '',
totalAmount: data.totalAmount || 0,
currency: data.currency || 'USD',
status: 'DRAFT',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
return newContract;
}
async updateContract(contractId: string, data: Partial<Contract>): Promise<Contract> {
await this.simulateDelay(300);
const contract = await this.fetchContractDetail(contractId);
if (!contract) throw new Error('Contract not found');
return { ...contract, ...data, updatedAt: new Date().toISOString() };
}
private simulateDelay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}

View File

@@ -41,8 +41,13 @@ export interface RiskAssessment {
orderId: string;
customerId: string;
customerName: string;
platform?: string;
platform_buyer_id?: string;
riskScore: number;
risk_score?: number;
riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
risk_level?: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
assessment_date?: string;
riskFactors: string[];
status: 'PENDING' | 'REVIEWING' | 'APPROVED' | 'REJECTED';
reviewedBy?: string;