refactor(types): 重构类型系统,统一共享类型定义
feat(types): 新增共享类型中心,包含用户、产品、订单等核心领域类型 fix(types): 修复类型定义错误,统一各模块类型引用 style(types): 优化类型文件格式和注释 docs(types): 更新类型文档和变更日志 test(types): 添加类型测试用例 build(types): 配置类型共享路径 chore(types): 清理重复类型定义文件
This commit is contained in:
@@ -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' },
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -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> = [
|
||||
|
||||
@@ -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 /> },
|
||||
|
||||
@@ -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: '非活跃',
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
</>
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user