refactor: 优化代码结构并修复类型问题

- 移除未使用的TabPane组件
- 修复类型定义和导入方式
- 优化mock数据源的环境变量判断逻辑
- 更新文档结构并归档旧文件
- 添加新的UI组件和Memo组件
- 调整API路径和响应处理
This commit is contained in:
2026-03-23 12:41:35 +08:00
parent a037843851
commit 2b86715c09
363 changed files with 39305 additions and 40622 deletions

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback } from 'react';
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import {
Card,
@@ -24,6 +24,8 @@ import {
Drawer,
Alert,
Spin,
Tabs,
Statistic,
} from 'antd';
import {
PlusOutlined,
@@ -44,7 +46,12 @@ import {
CheckCircleOutlined,
CloseCircleOutlined,
ExclamationCircleOutlined,
AmazonOutlined,
GlobalOutlined,
ShopOutlined,
AppstoreOutlined,
} from '@ant-design/icons';
import { LoadingState, EmptyState } from '../../components/ui';
import type { ColumnsType, TablePaginationConfig } from 'antd/es/table';
import type { FilterValue, SorterResult, TableCurrentDataSource } from 'antd/es/table/interface';
@@ -77,8 +84,13 @@ interface FilterState {
status: string[];
platform: string[];
category: string[];
priceRange: [number, number] | null;
stockRange: [number, number] | null;
roiRange: [number, number] | null;
dateRange: any;
minProfit: number | null;
minStock: number | null;
searchInDescription: boolean;
}
interface SortState {
@@ -96,9 +108,88 @@ const STATUS_CONFIG: Record<string, { color: string; text: string; icon: React.R
OFFLINE: { color: 'default', text: '已下架', icon: <ExclamationCircleOutlined /> },
};
const PLATFORMS = ['Amazon', 'eBay', 'Shopee', 'TikTok', 'Shopify'];
const PLATFORMS = [
// TikTok系列
'TikTok', 'TikTokFull',
// Shopee系列
'Shopee', 'ShopeeFull', 'ShopeeLight',
// Lazada系列
'Lazada', 'LazadaFull',
// Temu
'TemuFull',
// SHEIN系列
'Shein', 'SheinHalf',
// 其他平台
'Ozon', 'Yandex', 'AliExpress', 'AliExpressHalf', 'AliExpressPop',
'Coupang', 'Walmart', 'Wildberries', 'Allegro', 'MercadoLibre',
'Jumia', 'Joom', 'Amazon', 'Wish', 'Emag', 'Miravia',
'Daraz', 'Joybuy', 'Alibaba', 'Qoo10', 'Shopify', 'Shoplazza',
'ShopyyV1', 'ShopyyV2', 'Shopline', 'GreatBoss', 'Other',
// 原有平台
'eBay',
];
const CATEGORIES = ['工业自动化', '电子元器件', '工具设备', '仪器仪表', '安防设备'];
const PLATFORM_CONFIG: Record<string, { icon: React.ReactNode; color: string }> = {
// TikTok系列
TikTok: { icon: <GlobalOutlined />, color: '#000000' },
TikTokFull: { icon: <GlobalOutlined />, color: '#000000' },
// Shopee系列
Shopee: { icon: <ShopOutlined />, color: '#ee4d2d' },
ShopeeFull: { icon: <ShopOutlined />, color: '#ee4d2d' },
ShopeeLight: { icon: <ShopOutlined />, color: '#ee4d2d' },
// Lazada系列
Lazada: { icon: <ShopOutlined />, color: '#0F156D' },
LazadaFull: { icon: <ShopOutlined />, color: '#0F156D' },
// Temu
TemuFull: { icon: <ShopOutlined />, color: '#96bf48' },
// SHEIN系列
Shein: { icon: <ShopOutlined />, color: '#FF6B6B' },
SheinHalf: { icon: <ShopOutlined />, color: '#FF6B6B' },
// 其他平台
Ozon: { icon: <ShopOutlined />, color: '#FFD700' },
Yandex: { icon: <ShopOutlined />, color: '#FF0000' },
AliExpress: { icon: <ShopOutlined />, color: '#FF6A00' },
AliExpressHalf: { icon: <ShopOutlined />, color: '#FF6A00' },
AliExpressPop: { icon: <ShopOutlined />, color: '#FF6A00' },
Coupang: { icon: <ShopOutlined />, color: '#FF3B30' },
Walmart: { icon: <ShopOutlined />, color: '#007DC6' },
Wildberries: { icon: <ShopOutlined />, color: '#9370DB' },
Allegro: { icon: <ShopOutlined />, color: '#00A870' },
MercadoLibre: { icon: <ShopOutlined />, color: '#6C3483' },
Jumia: { icon: <ShopOutlined />, color: '#FF6B00' },
Joom: { icon: <ShopOutlined />, color: '#8A2BE2' },
Amazon: { icon: <AmazonOutlined />, color: '#ff9900' },
Wish: { icon: <ShopOutlined />, color: '#4A90E2' },
Emag: { icon: <ShopOutlined />, color: '#00B140' },
Miravia: { icon: <ShopOutlined />, color: '#FF69B4' },
Daraz: { icon: <ShopOutlined />, color: '#FF5722' },
Joybuy: { icon: <ShopOutlined />, color: '#E74C3C' },
Alibaba: { icon: <ShopOutlined />, color: '#FF6A00' },
Qoo10: { icon: <ShopOutlined />, color: '#FF4500' },
Shopify: { icon: <ShopOutlined />, color: '#96bf48' },
Shoplazza: { icon: <ShopOutlined />, color: '#3498DB' },
ShopyyV1: { icon: <ShopOutlined />, color: '#9370DB' },
ShopyyV2: { icon: <ShopOutlined />, color: '#9370DB' },
Shopline: { icon: <ShopOutlined />, color: '#27AE60' },
GreatBoss: { icon: <ShopOutlined />, color: '#3498DB' },
Other: { icon: <ShopOutlined />, color: '#999999' },
// 原有平台
eBay: { icon: <GlobalOutlined />, color: '#e53238' },
};
const MOCK_PRODUCTS: Product[] = [
{
id: '1',
@@ -222,22 +313,36 @@ export const ProductList: React.FC = () => {
const [filterVisible, setFilterVisible] = useState(false);
const [sortDrawerVisible, setSortDrawerVisible] = useState(false);
const [pricingModalVisible, setPricingModalVisible] = useState(false);
const [columnDrawerVisible, setColumnDrawerVisible] = useState(false);
const [currentProduct, setCurrentProduct] = useState<Product | null>(null);
const [syncLoading, setSyncLoading] = useState<Record<string, boolean>>({});
const [activePlatformTab, setActivePlatformTab] = useState<string>('all');
const [filters, setFilters] = useState<FilterState>({
keyword: '',
status: [],
platform: [],
category: [],
priceRange: null,
stockRange: null,
roiRange: null,
dateRange: null,
minProfit: null,
minStock: null,
searchInDescription: false,
});
const [sort, setSort] = useState<SortState>({
field: 'updatedAt',
order: 'descend',
});
const [visibleColumns, setVisibleColumns] = useState<string[]>([
'name', 'price', 'costPrice', 'profit', 'roi', 'stock', 'status', 'platformStatus', 'updatedAt', 'action'
]);
const [columnOrder, setColumnOrder] = useState<string[]>([
'name', 'price', 'costPrice', 'profit', 'roi', 'stock', 'status', 'platformStatus', 'updatedAt', 'action'
]);
useEffect(() => {
fetchProducts();
@@ -284,12 +389,29 @@ export const ProductList: React.FC = () => {
status: [],
platform: [],
category: [],
priceRange: null,
stockRange: null,
roiRange: null,
dateRange: null,
minProfit: null,
minStock: null,
searchInDescription: false,
});
message.success('筛选条件已重置');
};
const handleColumnVisibilityChange = (columnKey: string, visible: boolean) => {
if (visible) {
setVisibleColumns([...visibleColumns, columnKey]);
} else {
setVisibleColumns(visibleColumns.filter(key => key !== columnKey));
}
};
const handleColumnOrderChange = (newOrder: string[]) => {
setColumnOrder(newOrder);
};
const handleAddProduct = () => {
navigate('/dashboard/product/publish');
};
@@ -452,10 +574,31 @@ export const ProductList: React.FC = () => {
}, 500);
};
const handleBatchUpdate = () => {
if (selectedRows.length === 0) {
message.warning('请先选择要更新的商品');
return;
}
message.info(`批量更新功能:已选择 ${selectedRows.length} 个商品`);
// 这里可以打开批量更新模态框,实现批量更新商品信息
};
const handleBatchExport = () => {
if (selectedRows.length === 0) {
message.warning('请先选择要导出的商品');
return;
}
message.success(`成功导出 ${selectedRows.length} 个商品数据`);
// 这里可以实现导出商品数据为Excel或CSV文件
};
const filteredProducts = products.filter(product => {
if (filters.keyword && !product.name.toLowerCase().includes(filters.keyword.toLowerCase()) &&
!product.sku.toLowerCase().includes(filters.keyword.toLowerCase())) {
return false;
if (filters.keyword) {
const keywordLower = filters.keyword.toLowerCase();
if (!product.name.toLowerCase().includes(keywordLower) &&
!product.sku.toLowerCase().includes(keywordLower)) {
return false;
}
}
if (filters.status.length > 0 && !filters.status.includes(product.status)) {
return false;
@@ -463,9 +606,81 @@ export const ProductList: React.FC = () => {
if (filters.category.length > 0 && !filters.category.includes(product.category)) {
return false;
}
if (filters.priceRange) {
const [min, max] = filters.priceRange;
if (product.price < min || product.price > max) {
return false;
}
}
if (filters.stockRange) {
const [min, max] = filters.stockRange;
if (product.stock < min || product.stock > max) {
return false;
}
}
if (filters.roiRange) {
const [min, max] = filters.roiRange;
if (product.roi < min || product.roi > max) {
return false;
}
}
if (filters.minProfit !== null && product.profit < filters.minProfit) {
return false;
}
if (filters.minStock !== null && product.stock < filters.minStock) {
return false;
}
if (activePlatformTab !== 'all') {
if (activePlatformTab === 'unpublished') {
if (Object.keys(product.platformStatus).length > 0) {
return false;
}
} else {
if (!product.platformStatus[activePlatformTab]) {
return false;
}
}
}
return true;
});
const platformStats = useMemo(() => {
const stats: Record<string, { total: number; live: number; pending: number; failed: number }> = {
all: { total: products.length, live: 0, pending: 0, failed: 0 },
unpublished: { total: 0, live: 0, pending: 0, failed: 0 },
};
PLATFORMS.forEach(platform => {
stats[platform] = { total: 0, live: 0, pending: 0, failed: 0 };
});
products.forEach(product => {
const platforms = Object.keys(product.platformStatus);
if (platforms.length === 0) {
stats.unpublished.total++;
}
platforms.forEach(platform => {
if (!stats[platform]) {
stats[platform] = { total: 0, live: 0, pending: 0, failed: 0 };
}
stats[platform].total++;
const status = product.platformStatus[platform];
if (status === 'LIVE') {
stats[platform].live++;
stats.all.live++;
} else if (status === 'PENDING' || status === 'SYNCING' || status === 'LISTED') {
stats[platform].pending++;
stats.all.pending++;
} else if (status === 'FAILED' || status === 'SYNC_FAILED') {
stats[platform].failed++;
stats.all.failed++;
}
});
});
return stats;
}, [products]);
const sortedProducts = [...filteredProducts].sort((a, b) => {
const field = sort.field as keyof Product;
const aValue = a[field];
@@ -478,7 +693,7 @@ export const ProductList: React.FC = () => {
}
});
const columns: ColumnsType<Product> = [
const allColumns: ColumnsType<Product> = [
{
title: '商品信息',
dataIndex: 'name',
@@ -560,7 +775,6 @@ export const ProductList: React.FC = () => {
{Object.entries(record.platformStatus).map(([platform, status]) => (
<Tooltip key={platform} title={`${platform}: ${status}`}>
<Tag
color={status === 'LIVE' ? 'success' : status === 'FAILED' ? 'error' : 'processing'}
>
{platform.charAt(0)}
@@ -647,6 +861,11 @@ export const ProductList: React.FC = () => {
},
];
const columns = columnOrder
.filter(key => visibleColumns.includes(key))
.map(key => allColumns.find(col => col.key === key))
.filter(Boolean) as ColumnsType<Product>;
const rowSelection = {
selectedRowKeys: selectedRows.map(r => r.id),
onChange: (selectedRowKeys: React.Key[], selectedRows: Product[]) => {
@@ -670,24 +889,120 @@ export const ProductList: React.FC = () => {
showIcon
style={{ marginBottom: 16 }}
/>
<Tabs
activeKey={activePlatformTab}
onChange={setActivePlatformTab}
tabBarExtraContent={
<Space>
<Button icon={<FilterOutlined />} onClick={() => setFilterVisible(true)}>
</Button>
<Button icon={<SortAscendingOutlined />} onClick={() => setSortDrawerVisible(true)}>
</Button>
<Button icon={<AppstoreOutlined />} onClick={() => setColumnDrawerVisible(true)}>
</Button>
<Button type="primary" icon={<PlusOutlined />} onClick={handleAddProduct}>
</Button>
</Space>
}
>
<Tabs.TabPane
tab={
<span>
<AppstoreOutlined />
({platformStats.all?.total || 0})
</span>
}
key="all"
/>
{PLATFORMS.map(platform => {
const config = PLATFORM_CONFIG[platform];
const stat = platformStats[platform] || { total: 0, live: 0, pending: 0, failed: 0 };
return (
<Tabs.TabPane
tab={
<span>
{config.icon}
{platform} ({stat.total})
{stat.failed > 0 && (
<Badge count={stat.failed} size="small" style={{ marginLeft: 4 }} />
)}
</span>
}
key={platform}
/>
);
})}
<Tabs.TabPane
tab={
<span>
<ExclamationCircleOutlined />
({platformStats.unpublished?.total || 0})
</span>
}
key="unpublished"
/>
</Tabs>
{activePlatformTab !== 'all' && activePlatformTab !== 'unpublished' && (
<Row gutter={16} style={{ marginBottom: 16 }}>
<Col span={6}>
<Card size="small">
<Statistic
title="已在线"
value={platformStats[activePlatformTab]?.live || 0}
valueStyle={{ color: '#52c41a' }}
prefix={<CheckCircleOutlined />}
/>
</Card>
</Col>
<Col span={6}>
<Card size="small">
<Statistic
title="处理中"
value={platformStats[activePlatformTab]?.pending || 0}
valueStyle={{ color: '#1890ff' }}
prefix={<SyncOutlined spin />}
/>
</Card>
</Col>
<Col span={6}>
<Card size="small">
<Statistic
title="同步失败"
value={platformStats[activePlatformTab]?.failed || 0}
valueStyle={{ color: '#ff4d4f' }}
prefix={<CloseCircleOutlined />}
/>
</Card>
</Col>
<Col span={6}>
<Card size="small">
<Statistic
title="总计"
value={platformStats[activePlatformTab]?.total || 0}
prefix={<ShoppingOutlined />}
/>
</Card>
</Col>
</Row>
)}
<Row gutter={[16, 16]} style={{ marginBottom: 16 }}>
<Col span={24}>
<Space style={{ display: 'flex', justifyContent: 'space-between' }}>
<Space>
<Title level={4} style={{ margin: 0 }}></Title>
<Title level={4} style={{ margin: 0 }}>
{activePlatformTab === 'all' ? '全部商品' :
activePlatformTab === 'unpublished' ? '未发布商品' :
`${activePlatformTab} 商品`}
</Title>
<Badge count={sortedProducts.length} showZero style={{ backgroundColor: '#1890ff' }} />
</Space>
<Space>
<Button icon={<FilterOutlined />} onClick={() => setFilterVisible(true)}>
</Button>
<Button icon={<SortAscendingOutlined />} onClick={() => setSortDrawerVisible(true)}>
</Button>
<Button type="primary" icon={<PlusOutlined />} onClick={handleAddProduct}>
</Button>
</Space>
</Space>
</Col>
<Col span={24}>
@@ -717,6 +1032,12 @@ export const ProductList: React.FC = () => {
<Button size="small" onClick={handleBatchSync}>
</Button>
<Button size="small" onClick={handleBatchUpdate}>
</Button>
<Button size="small" onClick={handleBatchExport}>
</Button>
<Button size="small" danger onClick={handleBatchDelete}>
</Button>
@@ -726,22 +1047,34 @@ export const ProductList: React.FC = () => {
/>
)}
<Table
rowSelection={rowSelection}
columns={columns}
dataSource={sortedProducts}
loading={loading}
rowKey="id"
onChange={handleTableChange}
scroll={{ x: 1200 }}
pagination={{
total: sortedProducts.length,
pageSize: 10,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total) => `${total}`,
}}
/>
{loading ? (
<LoadingState tip="正在加载商品数据..." />
) : sortedProducts.length === 0 ? (
<EmptyState
title="暂无商品"
description="您还没有添加任何商品,点击下方按钮添加新商品"
showAddButton={true}
onAdd={handleAddProduct}
showReloadButton={true}
onReload={fetchProducts}
/>
) : (
<Table
rowSelection={rowSelection}
columns={columns}
dataSource={sortedProducts}
rowKey="id"
onChange={handleTableChange}
scroll={{ x: 1200 }}
pagination={{
total: sortedProducts.length,
pageSize: 10,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total) => `${total}`,
}}
/>
)}
<Drawer
title="筛选条件"
@@ -790,6 +1123,108 @@ export const ProductList: React.FC = () => {
))}
</Select>
</Form.Item>
<Form.Item label="价格范围">
<Row gutter={8}>
<Col span={11}>
<InputNumber
min={0}
placeholder="最小"
value={filters.priceRange?.[0] || undefined}
onChange={(value) => {
handleFilterChange('priceRange', filters.priceRange ? [value || 0, filters.priceRange[1]] : [value || 0, 999999]);
}}
style={{ width: '100%' }}
/>
</Col>
<Col span={2} style={{ textAlign: 'center' }}>-
</Col>
<Col span={11}>
<InputNumber
min={0}
placeholder="最大"
value={filters.priceRange?.[1] || undefined}
onChange={(value) => {
handleFilterChange('priceRange', filters.priceRange ? [filters.priceRange[0], value || 999999] : [0, value || 999999]);
}}
style={{ width: '100%' }}
/>
</Col>
</Row>
</Form.Item>
<Form.Item label="库存范围">
<Row gutter={8}>
<Col span={11}>
<InputNumber
min={0}
placeholder="最小"
value={filters.stockRange?.[0] || undefined}
onChange={(value) => {
handleFilterChange('stockRange', filters.stockRange ? [value || 0, filters.stockRange[1]] : [value || 0, 999999]);
}}
style={{ width: '100%' }}
/>
</Col>
<Col span={2} style={{ textAlign: 'center' }}>-
</Col>
<Col span={11}>
<InputNumber
min={0}
placeholder="最大"
value={filters.stockRange?.[1] || undefined}
onChange={(value) => {
handleFilterChange('stockRange', filters.stockRange ? [filters.stockRange[0], value || 999999] : [0, value || 999999]);
}}
style={{ width: '100%' }}
/>
</Col>
</Row>
</Form.Item>
<Form.Item label="ROI范围">
<Row gutter={8}>
<Col span={11}>
<InputNumber
min={0}
placeholder="最小"
value={filters.roiRange?.[0] || undefined}
onChange={(value) => {
handleFilterChange('roiRange', filters.roiRange ? [value || 0, filters.roiRange[1]] : [value || 0, 999999]);
}}
style={{ width: '100%' }}
/>
</Col>
<Col span={2} style={{ textAlign: 'center' }}>-
</Col>
<Col span={11}>
<InputNumber
min={0}
placeholder="最大"
value={filters.roiRange?.[1] || undefined}
onChange={(value) => {
handleFilterChange('roiRange', filters.roiRange ? [filters.roiRange[0], value || 999999] : [0, value || 999999]);
}}
style={{ width: '100%' }}
/>
</Col>
</Row>
</Form.Item>
<Form.Item label="最小利润">
<InputNumber
min={0}
placeholder="输入最小利润"
value={filters.minProfit}
onChange={(value) => handleFilterChange('minProfit', value)}
style={{ width: '100%' }}
/>
</Form.Item>
<Form.Item label="最小库存">
<InputNumber
min={0}
placeholder="输入最小库存"
value={filters.minStock}
onChange={(value) => handleFilterChange('minStock', value)}
style={{ width: '100%' }}
/>
</Form.Item>
<Form.Item label="更新时间">
<RangePicker
value={filters.dateRange}
@@ -797,6 +1232,17 @@ export const ProductList: React.FC = () => {
style={{ width: '100%' }}
/>
</Form.Item>
<Form.Item>
<div style={{ display: 'flex', alignItems: 'center' }}>
<input
type="checkbox"
checked={filters.searchInDescription}
onChange={(e) => handleFilterChange('searchInDescription', e.target.checked)}
style={{ marginRight: 8 }}
/>
<label></label>
</div>
</Form.Item>
</Form>
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: 16, borderTop: '1px solid #f0f0f0', background: '#fff' }}>
<Space style={{ display: 'flex', justifyContent: 'flex-end' }}>
@@ -827,7 +1273,6 @@ export const ProductList: React.FC = () => {
<span>{item.label}</span>
<Space>
<Button
icon={<ArrowUpOutlined />}
type={sort.field === item.key && sort.order === 'ascend' ? 'primary' : 'default'}
onClick={() => handleSortChange(item.key, 'ascend')}
@@ -835,7 +1280,6 @@ export const ProductList: React.FC = () => {
</Button>
<Button
icon={<ArrowDownOutlined />}
type={sort.field === item.key && sort.order === 'descend' ? 'primary' : 'default'}
onClick={() => handleSortChange(item.key, 'descend')}
@@ -849,6 +1293,114 @@ export const ProductList: React.FC = () => {
</Space>
</Drawer>
<Drawer
title="列设置"
placement="right"
onClose={() => setColumnDrawerVisible(false)}
visible={columnDrawerVisible}
width={400}
>
<div style={{ marginBottom: 20 }}>
<h3></h3>
</div>
<Space direction="vertical" style={{ width: '100%', marginBottom: 20 }}>
{
[
{ key: 'name', label: '商品信息' },
{ key: 'price', label: '售价' },
{ key: 'costPrice', label: '成本' },
{ key: 'profit', label: '利润' },
{ key: 'roi', label: 'ROI' },
{ key: 'stock', label: '库存' },
{ key: 'status', label: '状态' },
{ key: 'platformStatus', label: '平台状态' },
{ key: 'updatedAt', label: '更新时间' },
{ key: 'action', label: '操作' },
].map(item => (
<div key={item.key} style={{ display: 'flex', alignItems: 'center', marginBottom: 12 }}>
<input
type="checkbox"
checked={visibleColumns.includes(item.key)}
onChange={(e) => handleColumnVisibilityChange(item.key, e.target.checked)}
style={{ marginRight: 12 }}
/>
<span>{item.label}</span>
</div>
))
}
</Space>
<div style={{ marginBottom: 20 }}>
<h3></h3>
<p style={{ color: '#999', fontSize: 12 }}></p>
</div>
<div style={{ border: '1px dashed #d9d9d9', borderRadius: 4, padding: 16, minHeight: 200 }}>
{columnOrder.map(key => {
const columnInfo = [
{ key: 'name', label: '商品信息' },
{ key: 'price', label: '售价' },
{ key: 'costPrice', label: '成本' },
{ key: 'profit', label: '利润' },
{ key: 'roi', label: 'ROI' },
{ key: 'stock', label: '库存' },
{ key: 'status', label: '状态' },
{ key: 'platformStatus', label: '平台状态' },
{ key: 'updatedAt', label: '更新时间' },
{ key: 'action', label: '操作' },
].find(item => item.key === key);
return (
<div key={key} style={{
padding: 8,
marginBottom: 8,
backgroundColor: '#f0f2f5',
borderRadius: 4,
cursor: 'move',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}>
<span>{columnInfo?.label}</span>
<Space size="small">
<Button
size="small"
icon={<ArrowUpOutlined />}
onClick={() => {
const currentIndex = columnOrder.indexOf(key);
if (currentIndex > 0) {
const newOrder = [...columnOrder];
[newOrder[currentIndex], newOrder[currentIndex - 1]] = [newOrder[currentIndex - 1], newOrder[currentIndex]];
handleColumnOrderChange(newOrder);
}
}}
/>
<Button
size="small"
icon={<ArrowDownOutlined />}
onClick={() => {
const currentIndex = columnOrder.indexOf(key);
if (currentIndex < columnOrder.length - 1) {
const newOrder = [...columnOrder];
[newOrder[currentIndex], newOrder[currentIndex + 1]] = [newOrder[currentIndex + 1], newOrder[currentIndex]];
handleColumnOrderChange(newOrder);
}
}}
/>
</Space>
</div>
);
})}
</div>
<div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, padding: 16, borderTop: '1px solid #f0f0f0', background: '#fff' }}>
<Space style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button onClick={() => {
setVisibleColumns(['name', 'price', 'costPrice', 'profit', 'roi', 'stock', 'status', 'platformStatus', 'updatedAt', 'action']);
setColumnOrder(['name', 'price', 'costPrice', 'profit', 'roi', 'stock', 'status', 'platformStatus', 'updatedAt', 'action']);
message.success('列设置已重置');
}}></Button>
<Button type="primary" onClick={() => setColumnDrawerVisible(false)}></Button>
</Space>
</div>
</Drawer>
<Modal
title="商品定价"
visible={pricingModalVisible}