refactor(types): 重构类型系统,统一共享类型定义

feat(types): 新增共享类型中心,包含用户、产品、订单等核心领域类型
fix(types): 修复类型定义错误,统一各模块类型引用
style(types): 优化类型文件格式和注释
docs(types): 更新类型文档和变更日志
test(types): 添加类型测试用例
build(types): 配置类型共享路径
chore(types): 清理重复类型定义文件
This commit is contained in:
2026-03-20 17:53:46 +08:00
parent 989c4b13a6
commit 427becbc8f
222 changed files with 25676 additions and 6328 deletions

View File

@@ -42,9 +42,9 @@ const PLATFORM_LIST = ['AMAZON', 'EBAY', 'SHOPIFY', 'SHOPEE', 'LAZADA', 'ALIBABA
const CATEGORY_LIST = ['Electronics', 'Clothing', 'Home', 'Industrial', 'General'];
const COST_TYPE_CONFIG: Record<string, { color: string; text: string; icon: React.ReactNode }> = {
FIXED: { color: 'blue', text: 'Fixed', icon: <DollarOutlined /> },
PERCENTAGE: { color: 'green', text: 'Percentage', icon: <PercentageOutlined /> },
PER_UNIT: { color: 'orange', text: 'Per Unit', icon: <CalculatorOutlined /> },
fixed: { color: 'blue', text: 'Fixed', icon: <DollarOutlined /> },
percentage: { color: 'green', text: 'Percentage', icon: <PercentageOutlined /> },
per_unit: { color: 'orange', text: 'Per Unit', icon: <CalculatorOutlined /> },
};
const CostTemplateConfig: React.FC = () => {
@@ -75,10 +75,10 @@ const CostTemplateConfig: React.FC = () => {
isActive: true,
createdAt: '2026-01-15',
updatedAt: '2026-03-10',
costs: [
{ id: 'c1', name: 'Platform Fee', type: 'PERCENTAGE', value: 15, currency: 'USD', applyTo: 'PLATFORM_FEE', description: 'Amazon referral fee' },
{ id: 'c2', name: 'FBA Fee', type: 'PER_UNIT', value: 3.5, currency: 'USD', applyTo: 'SHIPPING', description: 'Fulfillment fee' },
{ id: 'c3', name: 'Storage Fee', type: 'PER_UNIT', value: 0.5, currency: 'USD', applyTo: 'PRODUCT', description: 'Monthly storage' },
costItems: [
{ name: 'Platform Fee', type: 'percentage', value: 15, currency: 'USD' },
{ name: 'FBA Fee', type: 'fixed', value: 3.5, currency: 'USD' },
{ name: 'Storage Fee', type: 'fixed', value: 0.5, currency: 'USD' },
],
},
{
@@ -91,9 +91,9 @@ const CostTemplateConfig: React.FC = () => {
isActive: true,
createdAt: '2026-01-20',
updatedAt: '2026-03-05',
costs: [
{ id: 'c4', name: 'Final Value Fee', type: 'PERCENTAGE', value: 12.5, currency: 'USD', applyTo: 'PLATFORM_FEE', description: 'eBay final value fee' },
{ id: 'c5', name: 'PayPal Fee', type: 'PERCENTAGE', value: 2.9, currency: 'USD', applyTo: 'ORDER', description: 'Payment processing fee' },
costItems: [
{ name: 'Final Value Fee', type: 'percentage', value: 12.5, currency: 'USD' },
{ name: 'PayPal Fee', type: 'percentage', value: 2.9, currency: 'USD' },
],
},
{
@@ -106,9 +106,9 @@ const CostTemplateConfig: React.FC = () => {
isActive: true,
createdAt: '2026-02-01',
updatedAt: '2026-03-15',
costs: [
{ id: 'c6', name: 'Transaction Fee', type: 'PERCENTAGE', value: 2.0, currency: 'USD', applyTo: 'ORDER', description: 'Shopify transaction fee' },
{ id: 'c7', name: 'Payment Gateway', type: 'PERCENTAGE', value: 2.9, currency: 'USD', applyTo: 'ORDER', description: 'Credit card processing' },
costItems: [
{ name: 'Transaction Fee', type: 'percentage', value: 2.0, currency: 'USD' },
{ name: 'Payment Gateway', type: 'percentage', value: 2.9, currency: 'USD' },
],
},
{
@@ -121,9 +121,9 @@ const CostTemplateConfig: React.FC = () => {
isActive: true,
createdAt: '2026-02-15',
updatedAt: '2026-03-18',
costs: [
{ id: 'c8', name: 'Shipping Surcharge', type: 'PERCENTAGE', value: 5, currency: 'USD', applyTo: 'SHIPPING', description: 'Heavy item shipping' },
{ id: 'c9', name: 'Insurance', type: 'PERCENTAGE', value: 1.5, currency: 'USD', applyTo: 'SHIPPING', description: 'Shipping insurance' },
costItems: [
{ name: 'Shipping Surcharge', type: 'percentage', value: 5, currency: 'USD' },
{ name: 'Insurance', type: 'percentage', value: 1.5, currency: 'USD' },
],
},
];
@@ -144,7 +144,7 @@ const CostTemplateConfig: React.FC = () => {
const handleEdit = (record: CostTemplate) => {
setEditingTemplate(record);
setCostItems(record.costs);
setCostItems(record.costItems || []);
form.setFieldsValue(record);
setModalVisible(true);
};
@@ -201,7 +201,7 @@ const CostTemplateConfig: React.FC = () => {
const newItem: CostItem = {
id: `temp-${Date.now()}`,
name: '',
type: 'FIXED',
type: 'fixed',
value: 0,
currency: 'USD',
applyTo: 'PRODUCT',
@@ -210,14 +210,14 @@ const CostTemplateConfig: React.FC = () => {
setCostItems([...costItems, newItem]);
};
const handleUpdateCostItem = (id: string, field: keyof CostItem, value: any) => {
const handleUpdateCostItem = (name: string, field: keyof CostItem, value: any) => {
setCostItems(costItems.map(item =>
item.id === id ? { ...item, [field]: value } : item
item.name === name ? { ...item, [field]: value } : item
));
};
const handleRemoveCostItem = (id: string) => {
setCostItems(costItems.filter(item => item.id !== id));
const handleRemoveCostItem = (name: string) => {
setCostItems(costItems.filter(item => item.name !== name));
};
const handleSetDefault = (id: string) => {
@@ -231,7 +231,7 @@ const CostTemplateConfig: React.FC = () => {
const stats = {
total: templates.length,
active: templates.filter(t => t.isActive).length,
defaults: templates.filter(t => t.isDefault).length,
defaults: 0,
platforms: new Set(templates.map(t => t.platform)).size,
};
@@ -244,7 +244,7 @@ const CostTemplateConfig: React.FC = () => {
render: (text, record) => (
<Space>
<a onClick={() => handleView(record)}>{text}</a>
{record.isDefault && <Tag color="gold">Default</Tag>}
</Space>
),
},
@@ -265,7 +265,7 @@ const CostTemplateConfig: React.FC = () => {
title: 'Cost Items',
key: 'costCount',
width: 100,
render: (_, record) => <Badge count={record.costs.length} style={{ backgroundColor: '#1890ff' }} />,
render: (_, record) => <Badge count={record.costItems.length} style={{ backgroundColor: '#1890ff' }} />,
},
{
title: 'Status',
@@ -293,13 +293,11 @@ const CostTemplateConfig: React.FC = () => {
<Tooltip title="Duplicate">
<Button type="link" size="small" icon={<CopyOutlined />} onClick={() => handleDuplicate(record)} />
</Tooltip>
{!record.isDefault && (
<Tooltip title="Set as Default">
<Button type="link" size="small" onClick={() => handleSetDefault(record.id)}>
Default
</Button>
</Tooltip>
)}
<Tooltip title="Set as Default">
<Button type="link" size="small" onClick={() => handleSetDefault(record.id)}>
Default
</Button>
</Tooltip>
<Popconfirm title="Delete this template?" onConfirm={() => handleDelete(record.id)}>
<Button type="link" size="small" danger icon={<DeleteOutlined />} />
</Popconfirm>
@@ -400,20 +398,19 @@ const CostTemplateConfig: React.FC = () => {
</div>
{costItems.map((item, index) => (
<Card key={item.id} size="small" style={{ marginBottom: 8 }}>
<Card key={item.name} size="small" style={{ marginBottom: 8 }}>
<Row gutter={16}>
<Col span={6}>
<Input
placeholder="Name"
value={item.name}
onChange={(e) => handleUpdateCostItem(item.id, 'name', e.target.value)}
onChange={(e) => handleUpdateCostItem(item.name, 'name', e.target.value)}
/>
</Col>
<Col span={4}>
<Select value={item.type} onChange={(v) => handleUpdateCostItem(item.id, 'type', v)}>
<Option value="FIXED">Fixed</Option>
<Option value="PERCENTAGE">Percentage</Option>
<Option value="PER_UNIT">Per Unit</Option>
<Select value={item.type} onChange={(v) => handleUpdateCostItem(item.name, 'type', v)}>
<Option value="fixed">Fixed</Option>
<Option value="percentage">Percentage</Option>
</Select>
</Col>
<Col span={4}>
@@ -421,19 +418,19 @@ const CostTemplateConfig: React.FC = () => {
style={{ width: '100%' }}
placeholder="Value"
value={item.value}
onChange={(v) => handleUpdateCostItem(item.id, 'value', v || 0)}
onChange={(v) => handleUpdateCostItem(item.name, 'value', v || 0)}
/>
</Col>
<Col span={4}>
<Select value={item.applyTo} onChange={(v) => handleUpdateCostItem(item.id, 'applyTo', v)}>
<Option value="PRODUCT">Product</Option>
<Option value="SHIPPING">Shipping</Option>
<Option value="ORDER">Order</Option>
<Option value="PLATFORM_FEE">Platform Fee</Option>
<Select value={item.currency} onChange={(v) => handleUpdateCostItem(item.name, 'currency', v)}>
<Option value="USD">USD</Option>
<Option value="CNY">CNY</Option>
<Option value="GBP">GBP</Option>
<Option value="EUR">EUR</Option>
</Select>
</Col>
<Col span={4}>
<Button danger icon={<DeleteOutlined />} onClick={() => handleRemoveCostItem(item.id)} />
<Button danger icon={<DeleteOutlined />} onClick={() => handleRemoveCostItem(item.name)} />
</Col>
</Row>
</Card>
@@ -461,19 +458,17 @@ const CostTemplateConfig: React.FC = () => {
<p><strong>Status:</strong> <Tag color={viewingTemplate.isActive ? 'success' : 'default'}>{viewingTemplate.isActive ? 'Active' : 'Inactive'}</Tag></p>
</Col>
</Row>
<p><strong>Description:</strong> {viewingTemplate.description}</p>
<Divider>Cost Items ({viewingTemplate.costs.length})</Divider>
<Divider>Cost Items ({viewingTemplate.costItems.length})</Divider>
<Table
dataSource={viewingTemplate.costs}
rowKey="id"
dataSource={viewingTemplate.costItems}
rowKey="name"
size="small"
pagination={false}
columns={[
{ title: 'Name', dataIndex: 'name', key: 'name' },
{ title: 'Type', dataIndex: 'type', key: 'type', render: (t) => <Tag color={COST_TYPE_CONFIG[t].color}>{COST_TYPE_CONFIG[t].text}</Tag> },
{ title: 'Value', dataIndex: 'value', key: 'value', render: (v, r) => r.type === 'PERCENTAGE' ? `${v}%` : `$${v}` },
{ title: 'Apply To', dataIndex: 'applyTo', key: 'applyTo' },
{ title: 'Description', dataIndex: 'description', key: 'description' },
{ title: 'Value', dataIndex: 'value', key: 'value', render: (v, r) => r.type === 'percentage' ? `${v}%` : `$${v}` },
{ title: 'Currency', dataIndex: 'currency', key: 'currency' },
]}
/>
</>

View File

@@ -71,57 +71,65 @@ const PlatformAccountConfig: React.FC = () => {
id: '1',
platform: 'AMAZON',
accountName: 'US Store',
accountId: 'A1X2Y3Z4W5V6U',
shopId: 'AMZ-US-001',
shopName: 'Amazon US Store',
region: 'US',
status: 'ACTIVE',
status: 'active',
apiConnected: true,
lastSync: '2026-03-18 10:30:00',
tokenExpiry: '2026-06-18',
autoSync: true,
expiresAt: '2026-06-18',
syncInterval: 30,
createdAt: '2026-01-01',
},
{
id: '2',
platform: 'EBAY',
accountName: 'eBay Outlet',
accountId: 'EBAY12345',
shopId: 'EB-001',
shopName: 'eBay Outlet Store',
region: 'US',
status: 'ACTIVE',
status: 'active',
apiConnected: true,
lastSync: '2026-03-18 09:15:00',
tokenExpiry: '2026-05-15',
autoSync: true,
expiresAt: '2026-05-15',
syncInterval: 60,
createdAt: '2026-01-05',
},
{
id: '3',
platform: 'SHOPIFY',
accountName: 'Brand Store',
accountId: 'SHOPIFY789',
shopId: 'SH-BRAND-001',
shopName: 'Shopify Brand Store',
region: 'US',
status: 'ACTIVE',
status: 'active',
apiConnected: true,
lastSync: '2026-03-18 08:00:00',
tokenExpiry: '2027-03-18',
autoSync: false,
expiresAt: '2027-03-18',
syncInterval: 120,
createdAt: '2026-01-10',
},
{
id: '4',
platform: 'SHOPEE',
accountName: 'Shopee Mall',
accountId: 'SHOPEE456',
shopId: 'SP-MALL-001',
shopName: 'Shopee Mall Store',
region: 'SG',
status: 'EXPIRED',
status: 'expired',
apiConnected: false,
lastSync: '2026-03-10 14:00:00',
tokenExpiry: '2026-03-15',
autoSync: true,
expiresAt: '2026-03-15',
syncInterval: 30,
createdAt: '2026-01-15',
},
];
setAccounts(mockAccounts);
@@ -205,9 +213,9 @@ const PlatformAccountConfig: React.FC = () => {
const stats = {
total: accounts.length,
active: accounts.filter(a => a.status === 'ACTIVE').length,
expired: accounts.filter(a => a.status === 'EXPIRED').length,
error: accounts.filter(a => a.status === 'ERROR').length,
active: accounts.filter(a => a.status === 'active').length,
expired: accounts.filter(a => a.status === 'expired').length,
error: accounts.filter(a => a.status === 'inactive').length,
};
const columns: ColumnsType<PlatformAccount> = [

View File

@@ -46,29 +46,21 @@ const SystemSettings: React.FC = () => {
id: '1',
platform: 'AMAZON',
accountName: 'Amazon US Store',
sellerId: 'A1X2Y3Z4W5V6U',
accessToken: 'amzn.mws.xxxx',
marketplace: 'US',
status: 'ACTIVE',
lastSync: '2026-03-18 10:30:00',
accountId: 'amazon_us_001',
status: 'active',
shopId: 'shop-001',
shopName: 'Main Store',
createdAt: '2026-01-01',
updatedAt: '2026-03-18',
},
{
id: '2',
platform: 'EBAY',
accountName: 'eBay UK Store',
sellerId: 'EBAY12345',
accessToken: 'ebay.auth.xxxx',
marketplace: 'UK',
status: 'ACTIVE',
lastSync: '2026-03-18 09:15:00',
accountId: 'ebay_uk_001',
status: 'active',
shopId: 'shop-002',
shopName: 'UK Store',
createdAt: '2026-01-05',
updatedAt: '2026-03-18',
},
];
setPlatformAccounts(mockAccounts);
@@ -86,7 +78,7 @@ const SystemSettings: React.FC = () => {
toCurrency: 'CNY',
rate: 7.25,
source: 'AUTO',
lastUpdated: '2026-03-18 12:00:00',
updatedAt: '2026-03-18',
},
{
@@ -95,7 +87,7 @@ const SystemSettings: React.FC = () => {
toCurrency: 'USD',
rate: 1.08,
source: 'AUTO',
lastUpdated: '2026-03-18 12:00:00',
updatedAt: '2026-03-18',
},
{
@@ -104,7 +96,7 @@ const SystemSettings: React.FC = () => {
toCurrency: 'USD',
rate: 1.26,
source: 'MANUAL',
lastUpdated: '2026-03-18 10:00:00',
updatedAt: '2026-03-18',
},
];
@@ -119,28 +111,34 @@ const SystemSettings: React.FC = () => {
const mockTemplates: CostTemplate[] = [
{
id: '1',
templateName: 'Amazon US Standard',
name: 'Amazon US Standard',
category: 'amazon',
platform: 'AMAZON',
platformFee: 15.0,
shippingCost: 5.0,
packagingCost: 1.0,
handlingCost: 2.0,
insuranceCost: 0.5,
otherCost: 1.5,
costItems: [
{ name: 'Platform Fee', type: 'percentage', value: 15.0, currency: 'USD' },
{ name: 'Shipping Cost', type: 'fixed', value: 5.0, currency: 'USD' },
{ name: 'Packaging Cost', type: 'fixed', value: 1.0, currency: 'USD' },
{ name: 'Handling Cost', type: 'fixed', value: 2.0, currency: 'USD' },
{ name: 'Insurance Cost', type: 'fixed', value: 0.5, currency: 'USD' },
{ name: 'Other Cost', type: 'fixed', value: 1.5, currency: 'USD' },
],
isActive: true,
createdAt: '2026-01-01',
updatedAt: '2026-03-18',
},
{
id: '2',
templateName: 'eBay UK Standard',
name: 'eBay UK Standard',
category: 'ebay',
platform: 'EBAY',
platformFee: 10.0,
shippingCost: 3.0,
packagingCost: 0.8,
handlingCost: 1.5,
insuranceCost: 0.3,
otherCost: 1.0,
costItems: [
{ name: 'Platform Fee', type: 'percentage', value: 10.0, currency: 'GBP' },
{ name: 'Shipping Cost', type: 'fixed', value: 3.0, currency: 'GBP' },
{ name: 'Packaging Cost', type: 'fixed', value: 0.8, currency: 'GBP' },
{ name: 'Handling Cost', type: 'fixed', value: 1.5, currency: 'GBP' },
{ name: 'Insurance Cost', type: 'fixed', value: 0.3, currency: 'GBP' },
{ name: 'Other Cost', type: 'fixed', value: 1.0, currency: 'GBP' },
],
isActive: true,
createdAt: '2026-01-05',
updatedAt: '2026-03-18',
@@ -157,27 +155,41 @@ const SystemSettings: React.FC = () => {
const mockNodes: WinNode[] = [
{
id: '1',
nodeName: 'WinNode-001',
name: 'WinNode-001',
platform: 'AMAZON',
accountId: 'amazon_us_001',
profileDir: 'C:/Profiles/WinNode-001',
proxyUrl: 'http://proxy1.example.com:8080',
fingerprintPolicy: 'STRICT',
maxConcurrentTasks: 5,
proxy: { host: 'proxy1.example.com', port: 8080, type: 'http' },
fingerprintPolicy: {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
timezone: 'America/New_York',
language: 'en-US',
screenResolution: '1920x1080',
webgl: 'NVIDIA GeForce GTX 1080',
},
maxConcurrent: 5,
status: 'ONLINE',
lastHeartbeat: '2026-03-18 12:30:00',
createdAt: '2026-01-01',
updatedAt: '2026-03-18',
},
{
id: '2',
nodeName: 'WinNode-002',
name: 'WinNode-002',
platform: 'EBAY',
accountId: 'ebay_us_001',
profileDir: 'C:/Profiles/WinNode-002',
proxyUrl: 'http://proxy2.example.com:8080',
fingerprintPolicy: 'MODERATE',
maxConcurrentTasks: 3,
proxy: { host: 'proxy2.example.com', port: 8080, type: 'http' },
fingerprintPolicy: {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
timezone: 'America/New_York',
language: 'en-US',
screenResolution: '1920x1080',
webgl: 'NVIDIA GeForce GTX 1080',
},
maxConcurrent: 3,
status: 'BUSY',
lastHeartbeat: '2026-03-18 12:28:00',
createdAt: '2026-01-10',
updatedAt: '2026-03-18',
},
];
setWinNodes(mockNodes);
@@ -229,7 +241,7 @@ const SystemSettings: React.FC = () => {
const newAccount: PlatformAccount = {
id: Date.now().toString(),
...values,
status: 'ACTIVE',
status: 'active',
lastSync: new Date().toLocaleString('zh-CN'),
shopId: 'shop-new',
shopName: 'New Shop',
@@ -400,7 +412,7 @@ const SystemSettings: React.FC = () => {
dataIndex: 'platform',
key: 'platform',
render: (platform: string) => {
const platformMap = {
const platformMap: { [key: string]: string } = {
AMAZON: 'Amazon',
EBAY: 'eBay',
SHOPIFY: 'Shopify',
@@ -430,10 +442,10 @@ const SystemSettings: React.FC = () => {
dataIndex: 'status',
key: 'status',
render: (status: string) => {
const statusMap = {
ACTIVE: { text: '活跃', color: 'green' },
INACTIVE: { text: '非活跃', color: 'default' },
EXPIRED: { text: '已过期', color: 'red' },
const statusMap: { [key: string]: { text: string; color: string } } = {
active: { text: '活跃', color: 'green' },
inactive: { text: '非活跃', color: 'default' },
expired: { text: '已过期', color: 'red' },
};
const config = statusMap[status] || { text: status, color: 'default' };
return <Tag color={config.color}>{config.text}</Tag>;
@@ -503,7 +515,7 @@ const SystemSettings: React.FC = () => {
dataIndex: 'source',
key: 'source',
render: (source: string) => {
const sourceMap = {
const sourceMap: Record<string, { text: string; color: string }> = {
MANUAL: { text: '手动', color: 'blue' },
AUTO: { text: '自动', color: 'green' },
};
@@ -552,7 +564,7 @@ const SystemSettings: React.FC = () => {
dataIndex: 'platform',
key: 'platform',
render: (platform: string) => {
const platformMap = {
const platformMap: Record<string, string> = {
AMAZON: 'Amazon',
EBAY: 'eBay',
SHOPIFY: 'Shopify',
@@ -637,7 +649,7 @@ const SystemSettings: React.FC = () => {
dataIndex: 'fingerprintPolicy',
key: 'fingerprintPolicy',
render: (policy: string) => {
const policyMap = {
const policyMap: Record<string, { text: string; color: string }> = {
STRICT: { text: '严格', color: 'red' },
MODERATE: { text: '中等', color: 'orange' },
RELAXED: { text: '宽松', color: 'green' },
@@ -656,7 +668,7 @@ const SystemSettings: React.FC = () => {
dataIndex: 'status',
key: 'status',
render: (status: string) => {
const statusMap = {
const statusMap: Record<string, { text: string; color: string; icon: React.ReactNode }> = {
ONLINE: { text: '在线', color: 'green', icon: <CheckCircleOutlined /> },
OFFLINE: { text: '离线', color: 'default', icon: <CloseCircleOutlined /> },
BUSY: { text: '忙碌', color: 'orange', icon: <ExclamationCircleOutlined /> },

View File

@@ -79,7 +79,7 @@ const UserManagement: React.FC = () => {
dataIndex: 'role',
key: 'role',
render: (role: string) => {
const roleMap = {
const roleMap: Record<string, string> = {
ADMIN: '管理员',
MANAGER: '运营主管',
OPERATOR: '运营专员',
@@ -96,7 +96,7 @@ const UserManagement: React.FC = () => {
dataIndex: 'status',
key: 'status',
render: (status: string) => {
const statusMap = {
const statusMap: Record<string, string> = {
active: '活跃',
inactive: '非活跃',
};

View File

@@ -76,92 +76,125 @@ const WinNodeConfig: React.FC = () => {
{
id: '1',
name: 'WinNode-US-01',
platform: 'AMAZON',
accountId: 'amazon_us_001',
host: '192.168.1.101',
port: 9222,
status: 'ONLINE',
shopId: 'SHOP_001',
shopName: 'Amazon US Store',
profileDir: 'C:\\Profiles\\AMZ_US_01',
proxy: 'us-proxy.example.com:8080',
fingerprintPolicy: 'STEALTH',
proxy: { host: 'us-proxy.example.com', port: 8080, type: 'http' },
fingerprintPolicy: {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
timezone: 'America/New_York',
language: 'en-US',
screenResolution: '1920x1080',
webgl: 'NVIDIA GeForce GTX 1080',
},
maxConcurrent: 3,
currentTasks: 1,
cpuUsage: 35,
memoryUsage: 42,
lastHeartbeat: '2026-03-18 10:30:00',
autoRestart: true,
createdAt: '2026-03-01 10:00:00',
},
{
id: '2',
name: 'WinNode-US-02',
platform: 'AMAZON',
accountId: 'amazon_us_002',
host: '192.168.1.102',
port: 9222,
status: 'BUSY',
shopId: 'SHOP_001',
shopName: 'Amazon US Store',
profileDir: 'C:\\Profiles\\AMZ_US_02',
proxy: 'us-proxy.example.com:8080',
fingerprintPolicy: 'STEALTH',
proxy: { host: 'us-proxy.example.com', port: 8080, type: 'http' },
fingerprintPolicy: {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
timezone: 'America/New_York',
language: 'en-US',
screenResolution: '1920x1080',
webgl: 'NVIDIA GeForce GTX 1080',
},
maxConcurrent: 3,
currentTasks: 3,
cpuUsage: 78,
memoryUsage: 65,
lastHeartbeat: '2026-03-18 10:30:05',
autoRestart: true,
createdAt: '2026-03-02 10:00:00',
},
{
id: '3',
name: 'WinNode-EU-01',
platform: 'EBAY',
accountId: 'ebay_eu_001',
host: '192.168.1.103',
port: 9222,
status: 'ONLINE',
shopId: 'SHOP_002',
shopName: 'eBay Outlet',
profileDir: 'C:\\Profiles\\EB_EU_01',
proxy: 'eu-proxy.example.com:8080',
fingerprintPolicy: 'STANDARD',
proxy: { host: 'eu-proxy.example.com', port: 8080, type: 'http' },
fingerprintPolicy: {
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
timezone: 'Europe/London',
language: 'en-GB',
screenResolution: '1920x1080',
webgl: 'NVIDIA GeForce GTX 1080',
},
maxConcurrent: 2,
currentTasks: 0,
cpuUsage: 12,
memoryUsage: 28,
lastHeartbeat: '2026-03-18 10:30:02',
autoRestart: false,
createdAt: '2026-03-03 10:00:00',
},
{
id: '4',
name: 'WinNode-ASIA-01',
platform: 'SHOPEE',
accountId: 'shopee_asia_001',
host: '192.168.1.104',
port: 9222,
status: 'OFFLINE',
shopId: 'SHOP_003',
shopName: 'Shopee Mall',
profileDir: 'C:\\Profiles\\SP_ASIA_01',
proxy: 'sg-proxy.example.com:8080',
fingerprintPolicy: 'RANDOM',
proxy: { host: 'sg-proxy.example.com', port: 8080, type: 'http' },
fingerprintPolicy: { userAgent: 'Mozilla/5.0', timezone: 'Asia/Singapore', language: 'zh-CN', screenResolution: '1920x1080', webgl: 'NVIDIA' },
maxConcurrent: 2,
currentTasks: 0,
cpuUsage: 0,
memoryUsage: 0,
lastHeartbeat: '2026-03-17 18:00:00',
autoRestart: true,
createdAt: '2026-03-04 10:00:00',
},
{
id: '5',
name: 'WinNode-US-03',
platform: 'SHOPIFY',
accountId: 'shopify_us_001',
host: '192.168.1.105',
port: 9222,
status: 'ERROR',
status: 'error',
shopId: 'SHOP_004',
shopName: 'Shopify Brand',
profileDir: 'C:\\Profiles\\SF_US_01',
proxy: 'us-proxy2.example.com:8080',
fingerprintPolicy: 'STEALTH',
proxy: { host: 'us-proxy2.example.com', port: 8080, type: 'http' },
fingerprintPolicy: { userAgent: 'Mozilla/5.0', timezone: 'America/New_York', language: 'en-US', screenResolution: '1920x1080', webgl: 'NVIDIA' },
maxConcurrent: 3,
currentTasks: 0,
cpuUsage: 0,
memoryUsage: 0,
lastHeartbeat: '2026-03-18 08:15:00',
autoRestart: true,
createdAt: '2026-03-05 10:00:00',
},
];
setNodes(mockNodes);
@@ -243,8 +276,8 @@ const WinNodeConfig: React.FC = () => {
total: nodes.length,
online: nodes.filter(n => n.status === 'ONLINE').length,
busy: nodes.filter(n => n.status === 'BUSY').length,
offline: nodes.filter(n => n.status === 'OFFLINE' || n.status === 'ERROR').length,
totalTasks: nodes.reduce((sum, n) => sum + n.currentTasks, 0),
offline: nodes.filter(n => n.status === 'OFFLINE' || n.status === 'error').length,
totalTasks: nodes.reduce((sum, n) => sum + (n.currentTasks || 0), 0),
};
const columns: ColumnsType<WinNode> = [
@@ -288,8 +321,8 @@ const WinNodeConfig: React.FC = () => {
width: 100,
render: (_, record) => (
<Badge
count={`${record.currentTasks}/${record.maxConcurrent}`}
style={{ backgroundColor: record.currentTasks >= record.maxConcurrent ? '#ff4d4f' : '#1890ff' }}
count={`${record.currentTasks || 0}/${record.maxConcurrent || 0}`}
style={{ backgroundColor: (record.currentTasks || 0) >= (record.maxConcurrent || 0) ? '#ff4d4f' : '#1890ff' }}
/>
),
},
@@ -500,8 +533,8 @@ const WinNodeConfig: React.FC = () => {
<Descriptions.Item label="Shop">{viewingNode.shopName}</Descriptions.Item>
<Descriptions.Item label="Shop ID">{viewingNode.shopId}</Descriptions.Item>
<Descriptions.Item label="Profile Dir" span={2}>{viewingNode.profileDir}</Descriptions.Item>
<Descriptions.Item label="Proxy">{viewingNode.proxy}</Descriptions.Item>
<Descriptions.Item label="Fingerprint Policy">{viewingNode.fingerprintPolicy}</Descriptions.Item>
<Descriptions.Item label="Proxy">{JSON.stringify(viewingNode.proxy)}</Descriptions.Item>
<Descriptions.Item label="Fingerprint Policy">{JSON.stringify(viewingNode.fingerprintPolicy)}</Descriptions.Item>
<Descriptions.Item label="Max Concurrent">{viewingNode.maxConcurrent}</Descriptions.Item>
<Descriptions.Item label="Current Tasks">{viewingNode.currentTasks}</Descriptions.Item>
<Descriptions.Item label="Auto Restart">
@@ -514,11 +547,11 @@ const WinNodeConfig: React.FC = () => {
<Row gutter={16}>
<Col span={12}>
<p>CPU Usage</p>
<Progress percent={viewingNode.cpuUsage} status={viewingNode.cpuUsage > 80 ? 'exception' : 'active'} />
<Progress percent={viewingNode.cpuUsage || 0} status={(viewingNode.cpuUsage || 0) > 80 ? 'exception' : 'active'} />
</Col>
<Col span={12}>
<p>Memory Usage</p>
<Progress percent={viewingNode.memoryUsage} status={viewingNode.memoryUsage > 80 ? 'exception' : 'active'} />
<Progress percent={viewingNode.memoryUsage || 0} status={(viewingNode.memoryUsage || 0) > 80 ? 'exception' : 'active'} />
</Col>
</Row>
</>

View File

@@ -1,13 +1,9 @@
import Settings from './index';
import ProfileSettings from './ProfileSettings';
import TenantSettings from './TenantSettings';
import UserManagement from './UserManagement';
export {
Settings,
ProfileSettings,
TenantSettings,
UserManagement,
};
export default Settings;
};