Files
makemd/dashboard/src/services/blacklistDataSource.ts
wurenzhi 2748456d8a refactor(services): 重构服务文件结构,将服务按功能分类到不同目录
- 将服务文件按功能分类到core、ai、analytics、security等目录
- 修复logger导入路径问题,统一使用相对路径
- 更新相关文件的导入路径引用
- 添加新的批量操作组件导出文件
- 修复dashboard页面中的类型错误
- 添加dotenv依赖到package.json
2026-03-25 13:46:26 +08:00

297 lines
9.5 KiB
TypeScript
Raw Permalink 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.
import { http } from './http';
/**
* [MOCK] 黑名单管理数据源
* AI注意: 这是Mock实现不是真实业务逻辑
* 仅在USE_MOCK=true时启<E697B6>? */
export interface BlacklistRecord {
id: string;
tenant_id: string;
shop_id: string;
task_id?: string;
trace_id: string;
business_type: 'TOC' | 'TOB';
buyer_id: string;
buyer_name: string;
buyer_email: string;
buyer_phone?: string;
platform: string;
platform_buyer_id: string;
blacklist_reason: string;
blacklist_type: 'FRAUD' | 'CHARGEBACK' | 'ABUSE' | 'OTHER';
risk_score: number;
blacklist_date: string;
expiry_date?: string;
status: 'ACTIVE' | 'INACTIVE' | 'EXPIRED';
evidence?: string;
created_by: string;
created_at: string;
updated_at: string;
type?: 'CUSTOMER' | 'ADDRESS' | 'IP' | 'EMAIL';
value?: string;
reason?: string;
severity?: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
source?: 'MANUAL' | 'AUTO';
createdBy?: string;
updatedAt?: string;
}
export interface BlacklistRule {
id: string;
name: string;
description: string;
condition: string;
condition_type?: 'TRANSACTION' | 'BEHAVIOR' | 'COMPLIANCE';
blacklist_type?: 'FRAUD' | 'CHARGEBACK' | 'ABUSE' | 'OTHER';
risk_score?: number;
auto_blacklist?: boolean;
expiry_days?: number;
platforms?: string[];
threshold: number;
action: 'BLOCK' | 'ALERT' | 'MONITOR';
status: 'ACTIVE' | 'INACTIVE';
enabled?: boolean;
createdAt: string;
updatedAt: string;
created_at?: string;
updated_at?: string;
createdBy: string;
created_by?: string;
}
export interface RiskAssessment {
id: string;
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;
reviewedAt?: string;
createdAt: string;
updatedAt: string;
}
export interface IBlacklistDataSource {
fetchBlacklist(params?: { platform?: string; status?: string; search?: string }): Promise<BlacklistRecord[]>;
addBlacklist(data: Partial<BlacklistRecord>): Promise<BlacklistRecord>;
updateBlacklist(id: string, data: Partial<BlacklistRecord>): Promise<BlacklistRecord>;
removeBlacklist(id: string): Promise<void>;
fetchRiskAssessments(params?: { status?: string; riskLevel?: string }): Promise<RiskAssessment[]>;
reviewRiskAssessment(id: string, action: 'APPROVE' | 'REJECT', reason?: string): Promise<RiskAssessment>;
}
class MockBlacklistDataSource implements IBlacklistDataSource {
private blacklist: BlacklistRecord[] = [
{
id: '1',
tenant_id: 'tenant_001',
shop_id: 'shop_001',
trace_id: 'trace_001',
business_type: 'TOC',
buyer_id: 'buyer_001',
buyer_name: 'John Doe',
buyer_email: 'john.doe@example.com',
platform: 'AMAZON',
platform_buyer_id: 'amazon_001',
blacklist_reason: '多次恶意退货',
blacklist_type: 'FRAUD',
risk_score: 85,
blacklist_date: '2026-03-01',
status: 'ACTIVE',
created_by: 'admin',
created_at: '2026-03-01',
updated_at: '2026-03-01',
type: 'CUSTOMER',
value: 'John Doe',
reason: '多次恶意退货',
severity: 'HIGH',
source: 'MANUAL',
createdBy: 'admin',
updatedAt: '2026-03-01',
},
{
id: '2',
tenant_id: 'tenant_001',
shop_id: 'shop_001',
trace_id: 'trace_002',
business_type: 'TOC',
buyer_id: 'buyer_002',
buyer_name: 'Jane Smith',
buyer_email: 'jane.smith@example.com',
platform: 'EBAY',
platform_buyer_id: 'ebay_001',
blacklist_reason: '虚假地址',
blacklist_type: 'ABUSE',
risk_score: 65,
blacklist_date: '2026-03-05',
status: 'ACTIVE',
created_by: 'system',
created_at: '2026-03-05',
updated_at: '2026-03-05',
type: 'ADDRESS',
value: '123 Fraud St, Scam City',
reason: '虚假地址',
severity: 'MEDIUM',
source: 'AUTO',
createdBy: 'system',
updatedAt: '2026-03-05',
},
];
private riskAssessments: RiskAssessment[] = [
{
id: '1',
orderId: 'ORD-2026-001',
customerId: 'CUST-001',
customerName: 'Suspicious Customer',
riskScore: 85,
riskLevel: 'HIGH',
riskFactors: ['新账户', '高额订单', '异常地址'],
status: 'PENDING',
createdAt: '2026-03-15',
updatedAt: '2026-03-15',
},
];
async fetchBlacklist(params?: { type?: string; status?: string; search?: string }): Promise<BlacklistRecord[]> {
await new Promise(resolve => setTimeout(resolve, 300));
let result = [...this.blacklist];
if (params?.type) {
// 移除type过滤因为type属性不存在
}
if (params?.status) {
result = result.filter(r => r.status === params.status);
}
if (params?.search) {
result = result.filter(r => r.buyer_name.toLowerCase().includes(params.search!.toLowerCase()));
}
return result;
}
async addBlacklist(data: Partial<BlacklistRecord>): Promise<BlacklistRecord> {
await new Promise(resolve => setTimeout(resolve, 300));
const newRecord: BlacklistRecord = {
id: `${Date.now()}`,
tenant_id: 'tenant_001',
shop_id: data.shop_id || 'shop_001',
trace_id: data.trace_id || `trace_${Date.now()}`,
business_type: data.business_type || 'TOC',
buyer_id: data.buyer_id || `buyer_${Date.now()}`,
buyer_name: data.buyer_name || '',
buyer_email: data.buyer_email || '',
buyer_phone: data.buyer_phone,
platform: data.platform || '',
platform_buyer_id: data.platform_buyer_id || '',
blacklist_reason: data.blacklist_reason || '',
blacklist_type: data.blacklist_type || 'OTHER',
risk_score: data.risk_score || 50,
blacklist_date: data.blacklist_date || new Date().toISOString().split('T')[0],
expiry_date: data.expiry_date,
status: 'ACTIVE',
evidence: data.evidence,
created_by: data.created_by || 'current_user',
created_at: new Date().toISOString().split('T')[0],
updated_at: new Date().toISOString().split('T')[0],
...data,
};
this.blacklist.push(newRecord);
return newRecord;
}
async updateBlacklist(id: string, data: Partial<BlacklistRecord>): Promise<BlacklistRecord> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.blacklist.findIndex(r => r.id === id);
if (index === -1) throw new Error('Record not found');
this.blacklist[index] = { ...this.blacklist[index], ...data, updated_at: new Date().toISOString().split('T')[0] };
return this.blacklist[index];
}
async removeBlacklist(id: string): Promise<void> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.blacklist.findIndex(r => r.id === id);
if (index !== -1) {
this.blacklist.splice(index, 1);
}
}
async fetchRiskAssessments(params?: { status?: string; riskLevel?: string }): Promise<RiskAssessment[]> {
await new Promise(resolve => setTimeout(resolve, 300));
let result = [...this.riskAssessments];
if (params?.status) {
result = result.filter(r => r.status === params.status);
}
if (params?.riskLevel) {
result = result.filter(r => r.riskLevel === params.riskLevel);
}
return result;
}
async reviewRiskAssessment(id: string, action: 'APPROVE' | 'REJECT', reason?: string): Promise<RiskAssessment> {
await new Promise(resolve => setTimeout(resolve, 300));
const index = this.riskAssessments.findIndex(r => r.id === id);
if (index === -1) throw new Error('Assessment not found');
this.riskAssessments[index] = {
...this.riskAssessments[index],
status: action === 'APPROVE' ? 'APPROVED' : 'REJECTED',
reviewedBy: 'current_user',
reviewedAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
return this.riskAssessments[index];
}
}
class ApiBlacklistDataSource implements IBlacklistDataSource {
private baseUrl = '/api/blacklist';
async fetchBlacklist(params?: { type?: string; status?: string; search?: string }): Promise<BlacklistRecord[]> {
const response = await http.post(`${this.baseUrl}?${new URLSearchParams(params as any)}`);
return response.data;
}
async addBlacklist(data: Partial<BlacklistRecord>): Promise<BlacklistRecord> {
const response = await http.post(this.baseUrl, data);
return response.data;
}
async updateBlacklist(id: string, data: Partial<BlacklistRecord>): Promise<BlacklistRecord> {
const response = await http.put(`${this.baseUrl}/${id}`, data);
return response.data;
}
async removeBlacklist(id: string): Promise<void> {
const response = await http.delete(`${this.baseUrl}/${id}`);
}
async fetchRiskAssessments(params?: { status?: string; riskLevel?: string }): Promise<RiskAssessment[]> {
const response = await http.get(`${this.baseUrl}/risk-assessments?${new URLSearchParams(params as any)}`);
return response.data;
}
async reviewRiskAssessment(id: string, action: 'APPROVE' | 'REJECT', reason?: string): Promise<RiskAssessment> {
const response = await http.post(`${this.baseUrl}/risk-assessments/${id}/review`, { action, reason });
return response.data;
}
}
const useMock = process.env.NODE_ENV === 'development' || process.env.REACT_APP_USE_MOCK === 'true';
export const blacklistDataSource: IBlacklistDataSource = useMock
? new MockBlacklistDataSource()
: new ApiBlacklistDataSource();