feat: 添加前端页面和业务说明书

refactor(server): 重构服务层代码结构
feat(server): 添加基础设施、跨境电商、AI决策等核心服务
docs: 完善前端业务说明书和开发进度文档
style: 格式化代码和文档
This commit is contained in:
2026-03-18 19:12:38 +08:00
parent c932a67be2
commit 6d0d2b6157
140 changed files with 23859 additions and 5833 deletions

View File

@@ -0,0 +1,297 @@
import React, { useState } from 'react';
import { Card, Layout, Typography, Row, Col, Form, Input, Select, Button, Table, Statistic, Spin, message, Alert } from 'antd';
import { CalculatorOutlined, SaveOutlined, HistoryOutlined, LineChartOutlined } from '@ant-design/icons';
import { Link } from 'umi';
const { Content } = Layout;
const { Title, Text, Paragraph } = Typography;
const { Option } = Select;
const { Item } = Form;
interface PricingSuggestion {
id: string;
scenario: string;
suggestedPrice: number;
expectedProfit: number;
expectedROI: number;
expectedSales: number;
confidence: number;
}
interface PriceHistory {
id: string;
date: string;
oldPrice: number;
newPrice: number;
reason: string;
operator: string;
}
const AIPricing: React.FC = () => {
const [loading, setLoading] = useState<boolean>(false);
const [pricingSuggestions, setPricingSuggestions] = useState<PricingSuggestion[]>([]);
const [priceHistory, setPriceHistory] = useState<PriceHistory[]>([]);
const [form] = Form.useForm();
const mockPricingSuggestions: PricingSuggestion[] = [
{
id: '1',
scenario: '激进定价',
suggestedPrice: 349,
expectedProfit: 199,
expectedROI: 132.67,
expectedSales: 80,
confidence: 0.85,
},
{
id: '2',
scenario: '均衡定价',
suggestedPrice: 299,
expectedProfit: 149,
expectedROI: 99.33,
expectedSales: 120,
confidence: 0.95,
},
{
id: '3',
scenario: '保守定价',
suggestedPrice: 279,
expectedProfit: 129,
expectedROI: 86.00,
expectedSales: 150,
confidence: 0.90,
},
];
const mockPriceHistory: PriceHistory[] = [
{
id: '1',
date: '2026-03-15',
oldPrice: 279,
newPrice: 299,
reason: '基于市场竞争分析',
operator: 'AI系统',
},
{
id: '2',
date: '2026-03-10',
oldPrice: 259,
newPrice: 279,
reason: '成本上升',
operator: '运营专员',
},
{
id: '3',
date: '2026-03-01',
oldPrice: 239,
newPrice: 259,
reason: '新品上市',
operator: '运营专员',
},
];
const handleCalculatePrice = () => {
setLoading(true);
// 模拟API请求
setTimeout(() => {
setPricingSuggestions(mockPricingSuggestions);
setPriceHistory(mockPriceHistory);
setLoading(false);
message.success('智能定价计算完成');
}, 1500);
};
const handleApplyPrice = (scenario: string, price: number) => {
message.success(`已应用${scenario}定价策略,新价格:¥${price}`);
};
const columns = [
{
title: '场景',
dataIndex: 'scenario',
key: 'scenario',
},
{
title: '建议售价',
dataIndex: 'suggestedPrice',
key: 'suggestedPrice',
render: (text: number) => `¥${text}`,
},
{
title: '预期利润',
dataIndex: 'expectedProfit',
key: 'expectedProfit',
render: (text: number) => `¥${text}`,
},
{
title: '预期ROI',
dataIndex: 'expectedROI',
key: 'expectedROI',
render: (text: number) => `${text}%`,
},
{
title: '预期销量',
dataIndex: 'expectedSales',
key: 'expectedSales',
},
{
title: '置信度',
dataIndex: 'confidence',
key: 'confidence',
render: (text: number) => `${(text * 100).toFixed(0)}%`,
},
{
title: '操作',
key: 'action',
render: (_: any, record: PricingSuggestion) => (
<Button
type="primary"
size="small"
onClick={() => handleApplyPrice(record.scenario, record.suggestedPrice)}
>
</Button>
),
},
];
const historyColumns = [
{
title: '日期',
dataIndex: 'date',
key: 'date',
},
{
title: '旧价格',
dataIndex: 'oldPrice',
key: 'oldPrice',
render: (text: number) => `¥${text}`,
},
{
title: '新价格',
dataIndex: 'newPrice',
key: 'newPrice',
render: (text: number) => `¥${text}`,
},
{
title: '调整原因',
dataIndex: 'reason',
key: 'reason',
},
{
title: '操作人',
dataIndex: 'operator',
key: 'operator',
},
];
return (
<Content style={{ padding: 24, margin: 0, minHeight: 280, background: '#fff' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }}>
<Title level={4}>AI智能定价</Title>
<Button type="primary" icon={<HistoryOutlined />}>
<Link to="/Product/PriceHistory"></Link>
</Button>
</div>
{/* 定价参数表单 */}
<Card title="定价参数" style={{ marginBottom: 24 }}>
<Form
form={form}
layout="horizontal"
initialValues={{
productId: 'P001',
cost: 150,
currentPrice: 299,
competitorPrice: 329,
salesVolume: 120,
pricingStrategy: 'balanced',
}}
>
<Row gutter={[16, 16]}>
<Col span={6}>
<Item label="商品ID" name="productId">
<Input placeholder="输入商品ID" />
</Item>
</Col>
<Col span={6}>
<Item label="成本" name="cost" rules={[{ required: true, message: '请输入成本' }]}>
<Input type="number" prefix="¥" placeholder="输入成本" />
</Item>
</Col>
<Col span={6}>
<Item label="当前售价" name="currentPrice" rules={[{ required: true, message: '请输入当前售价' }]}>
<Input type="number" prefix="¥" placeholder="输入当前售价" />
</Item>
</Col>
<Col span={6}>
<Item label="竞品价格" name="competitorPrice">
<Input type="number" prefix="¥" placeholder="输入竞品价格" />
</Item>
</Col>
<Col span={6}>
<Item label="月销量" name="salesVolume">
<Input type="number" placeholder="输入月销量" />
</Item>
</Col>
<Col span={6}>
<Item label="定价策略" name="pricingStrategy">
<Select>
<Option value="aggressive"></Option>
<Option value="balanced"></Option>
<Option value="conservative"></Option>
</Select>
</Item>
</Col>
<Col span={12} style={{ display: 'flex', alignItems: 'flex-end' }}>
<Button
type="primary"
icon={<CalculatorOutlined />}
onClick={handleCalculatePrice}
loading={loading}
style={{ width: '100%' }}
>
</Button>
</Col>
</Row>
</Form>
</Card>
{/* 定价建议 */}
<Card title="智能定价建议" style={{ marginBottom: 24 }}>
{loading ? (
<div style={{ display: 'flex', justifyContent: 'center', padding: '40px 0' }}>
<Spin size="large" />
</div>
) : pricingSuggestions.length > 0 ? (
<Table
columns={columns}
dataSource={pricingSuggestions}
rowKey="id"
pagination={false}
/>
) : (
<Alert
message="请输入定价参数并点击计算按钮"
type="info"
showIcon
style={{ margin: '20px 0' }}
/>
)}
</Card>
{/* 价格历史 */}
<Card title="价格调整历史">
<Table
columns={historyColumns}
dataSource={priceHistory}
rowKey="id"
pagination={{ pageSize: 5 }}
/>
</Card>
</Content>
);
};
export default AIPricing;

View File

@@ -0,0 +1,360 @@
import React, { useState, useEffect } from 'react';
import { Card, Layout, Typography, Row, Col, Select, Button, Table, Statistic, Spin, message, Alert, Badge } from 'antd';
import { LineChart, Line, AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
import { AlertOutlined, TrendingUpOutlined, TrendingDownOutlined, ReloadOutlined, EyeOutlined } from '@ant-design/icons';
import { Link } from 'umi';
const { Content } = Layout;
const { Title, Text, Paragraph } = Typography;
const { Option } = Select;
interface ProfitData {
id: string;
date: string;
profit: number;
sales: number;
cost: number;
roi: number;
}
interface AlertItem {
id: string;
productId: string;
productName: string;
type: string;
message: string;
severity: 'info' | 'warning' | 'error';
date: string;
}
interface ProductProfit {
id: string;
productId: string;
productName: string;
currentProfit: number;
previousProfit: number;
change: number;
roi: number;
status: 'up' | 'down' | 'stable';
}
const ProfitMonitor: React.FC = () => {
const [loading, setLoading] = useState<boolean>(false);
const [profitData, setProfitData] = useState<ProfitData[]>([]);
const [alerts, setAlerts] = useState<AlertItem[]>([]);
const [productProfits, setProductProfits] = useState<ProductProfit[]>([]);
const [selectedProduct, setSelectedProduct] = useState<string>('');
const [timeRange, setTimeRange] = useState<string>('7d');
const mockProfitData: ProfitData[] = [
{ id: '1', date: '2026-03-12', profit: 14900, sales: 12000, cost: 8000, roi: 99.33 },
{ id: '2', date: '2026-03-13', profit: 15200, sales: 12500, cost: 8200, roi: 100.67 },
{ id: '3', date: '2026-03-14', profit: 14800, sales: 11800, cost: 8100, roi: 98.67 },
{ id: '4', date: '2026-03-15', profit: 16500, sales: 13500, cost: 8500, roi: 103.33 },
{ id: '5', date: '2026-03-16', profit: 17200, sales: 14000, cost: 8800, roi: 105.33 },
{ id: '6', date: '2026-03-17', profit: 16800, sales: 13800, cost: 8700, roi: 104.00 },
{ id: '7', date: '2026-03-18', profit: 18500, sales: 15000, cost: 9200, roi: 108.33 },
];
const mockAlerts: AlertItem[] = [
{
id: '1',
productId: 'P001',
productName: '智能手表',
type: '利润下降',
message: '连续3天利润下降当前利润低于预期15%',
severity: 'warning',
date: '2026-03-18 10:30',
},
{
id: '2',
productId: 'P002',
productName: '无线耳机',
type: 'ROI异常',
message: 'ROI突然上升30%,可能存在定价问题',
severity: 'info',
date: '2026-03-18 09:15',
},
{
id: '3',
productId: 'P003',
productName: '智能音箱',
type: '成本上升',
message: '成本上升10%,建议调整售价',
severity: 'error',
date: '2026-03-17 16:45',
},
];
const mockProductProfits: ProductProfit[] = [
{
id: '1',
productId: 'P001',
productName: '智能手表',
currentProfit: 14900,
previousProfit: 15200,
change: -2.0,
roi: 99.33,
status: 'down',
},
{
id: '2',
productId: 'P002',
productName: '无线耳机',
currentProfit: 23800,
previousProfit: 21500,
change: 10.7,
roi: 148.75,
status: 'up',
},
{
id: '3',
productId: 'P003',
productName: '智能音箱',
currentProfit: 9500,
previousProfit: 9400,
change: 1.1,
roi: 86.36,
status: 'stable',
},
];
const fetchProfitData = () => {
setLoading(true);
// 模拟API请求
setTimeout(() => {
setProfitData(mockProfitData);
setAlerts(mockAlerts);
setProductProfits(mockProductProfits);
setLoading(false);
}, 1000);
};
useEffect(() => {
fetchProfitData();
}, []);
const handleProductChange = (value: string) => {
setSelectedProduct(value);
};
const handleTimeRangeChange = (value: string) => {
setTimeRange(value);
};
const handleRefresh = () => {
fetchProfitData();
};
const columns = [
{
title: '商品ID',
dataIndex: 'productId',
key: 'productId',
},
{
title: '商品名称',
dataIndex: 'productName',
key: 'productName',
},
{
title: '当前利润',
dataIndex: 'currentProfit',
key: 'currentProfit',
render: (text: number) => `¥${text}`,
},
{
title: '变化率',
dataIndex: 'change',
key: 'change',
render: (text: number) => (
<span style={{ color: text > 0 ? '#52c41a' : text < 0 ? '#ff4d4f' : '#1890ff' }}>
{text > 0 ? '+' : ''}{text}%
</span>
),
},
{
title: 'ROI',
dataIndex: 'roi',
key: 'roi',
render: (text: number) => `${text}%`,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => (
<Badge
status={status === 'up' ? 'success' : status === 'down' ? 'error' : 'default'}
text={status === 'up' ? '上升' : status === 'down' ? '下降' : '稳定'}
/>
),
},
];
const alertColumns = [
{
title: '商品ID',
dataIndex: 'productId',
key: 'productId',
},
{
title: '商品名称',
dataIndex: 'productName',
key: 'productName',
},
{
title: '类型',
dataIndex: 'type',
key: 'type',
},
{
title: '消息',
dataIndex: 'message',
key: 'message',
},
{
title: '严重程度',
dataIndex: 'severity',
key: 'severity',
render: (severity: string) => (
<Badge
status={severity === 'info' ? 'default' : severity === 'warning' ? 'warning' : 'error'}
text={severity === 'info' ? '信息' : severity === 'warning' ? '警告' : '错误'}
/>
),
},
{
title: '时间',
dataIndex: 'date',
key: 'date',
},
];
return (
<Content style={{ padding: 24, margin: 0, minHeight: 280, background: '#fff' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }}>
<Title level={4}></Title>
<div style={{ display: 'flex', gap: 12 }}>
<Select
placeholder="选择商品"
style={{ width: 200 }}
onChange={handleProductChange}
>
<Option value=""></Option>
<Option value="P001"></Option>
<Option value="P002">线</Option>
<Option value="P003"></Option>
</Select>
<Select
defaultValue="7d"
style={{ width: 120 }}
onChange={handleTimeRangeChange}
>
<Option value="7d">7</Option>
<Option value="30d">30</Option>
<Option value="90d">90</Option>
</Select>
<Button
type="primary"
icon={<ReloadOutlined />}
onClick={handleRefresh}
loading={loading}
>
</Button>
</div>
</div>
{/* 利润概览 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
<Col span={6}>
<Card>
<Statistic
title="总利润"
value={mockProductProfits.reduce((sum, item) => sum + item.currentProfit, 0)}
prefix="¥"
valueStyle={{ color: '#3f8600' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="平均ROI"
value={mockProductProfits.reduce((sum, item) => sum + item.roi, 0) / mockProductProfits.length}
suffix="%"
valueStyle={{ color: '#3f8600' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="利润预警"
value={mockAlerts.length}
prefix={<AlertOutlined />}
valueStyle={{ color: '#faad14' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="监控商品数"
value={mockProductProfits.length}
prefix={<EyeOutlined />}
valueStyle={{ color: '#1890ff' }}
/>
</Card>
</Col>
</Row>
{/* 利润趋势图表 */}
<Card title="利润趋势" style={{ marginBottom: 24 }}>
<ResponsiveContainer width="100%" height={400}>
<AreaChart data={profitData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" />
<YAxis />
<Tooltip />
<Legend />
<Area type="monotone" dataKey="profit" name="利润" fill="#52c41a" stroke="#52c41a" />
<Area type="monotone" dataKey="sales" name="销售额" fill="#1890ff" stroke="#1890ff" />
<Area type="monotone" dataKey="cost" name="成本" fill="#faad14" stroke="#faad14" />
</AreaChart>
</ResponsiveContainer>
</Card>
<Row gutter={[16, 16]}>
{/* 商品利润列表 */}
<Col span={12}>
<Card title="商品利润详情">
<Table
columns={columns}
dataSource={productProfits}
rowKey="id"
loading={loading}
pagination={{ pageSize: 5 }}
/>
</Card>
</Col>
{/* 利润预警 */}
<Col span={12}>
<Card title="利润预警">
<Table
columns={alertColumns}
dataSource={alerts}
rowKey="id"
loading={loading}
pagination={{ pageSize: 5 }}
/>
</Card>
</Col>
</Row>
</Content>
);
};
export default ProfitMonitor;

View File

@@ -0,0 +1,325 @@
import React, { useState, useEffect } from 'react';
import { Card, Layout, Typography, Row, Col, DatePicker, Select, Button, Table, Statistic, Spin, message } from 'antd';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, LineChart, Line } from 'recharts';
import { ArrowUpOutlined, ArrowDownOutlined, ReloadOutlined } from '@ant-design/icons';
import { Link } from 'umi';
const { Content } = Layout;
const { Title, Text } = Typography;
const { RangePicker } = DatePicker;
const { Option } = Select;
interface ROIItem {
id: string;
productId: string;
productName: string;
cost: number;
price: number;
profit: number;
roi: number;
salesVolume: number;
date: string;
}
const ROIAnalysis: React.FC = () => {
const [loading, setLoading] = useState<boolean>(false);
const [roiData, setRoiData] = useState<ROIItem[]>([]);
const [timeRange, setTimeRange] = useState<any>(null);
const [productId, setProductId] = useState<string>('');
const [summary, setSummary] = useState<{
totalSales: number;
totalProfit: number;
averageROI: number;
bestProduct: string;
}>({
totalSales: 0,
totalProfit: 0,
averageROI: 0,
bestProduct: '',
});
const mockROIData: ROIItem[] = [
{
id: '1',
productId: 'P001',
productName: '智能手表',
cost: 150,
price: 299,
profit: 149,
roi: 99.33,
salesVolume: 120,
date: '2026-03-01',
},
{
id: '2',
productId: 'P001',
productName: '智能手表',
cost: 150,
price: 299,
profit: 149,
roi: 99.33,
salesVolume: 110,
date: '2026-03-02',
},
{
id: '3',
productId: 'P001',
productName: '智能手表',
cost: 150,
price: 299,
profit: 149,
roi: 99.33,
salesVolume: 130,
date: '2026-03-03',
},
{
id: '4',
productId: 'P002',
productName: '无线耳机',
cost: 80,
price: 199,
profit: 119,
roi: 148.75,
salesVolume: 200,
date: '2026-03-01',
},
{
id: '5',
productId: 'P002',
productName: '无线耳机',
cost: 80,
price: 199,
profit: 119,
roi: 148.75,
salesVolume: 210,
date: '2026-03-02',
},
{
id: '6',
productId: 'P002',
productName: '无线耳机',
cost: 80,
price: 199,
profit: 119,
roi: 148.75,
salesVolume: 190,
date: '2026-03-03',
},
];
const fetchROIData = () => {
setLoading(true);
// 模拟API请求
setTimeout(() => {
setRoiData(mockROIData);
// 计算汇总数据
const totalSales = mockROIData.reduce((sum, item) => sum + item.salesVolume, 0);
const totalProfit = mockROIData.reduce((sum, item) => sum + item.profit * item.salesVolume, 0);
const averageROI = mockROIData.reduce((sum, item) => sum + item.roi, 0) / mockROIData.length;
const bestProduct = mockROIData.reduce((best, current) =>
current.roi > best.roi ? current : best
).productName;
setSummary({
totalSales,
totalProfit,
averageROI: parseFloat(averageROI.toFixed(2)),
bestProduct,
});
setLoading(false);
}, 1000);
};
useEffect(() => {
fetchROIData();
}, []);
const handleTimeRangeChange = (dates: any) => {
setTimeRange(dates);
};
const handleProductChange = (value: string) => {
setProductId(value);
};
const handleRefresh = () => {
fetchROIData();
};
const columns = [
{
title: '商品ID',
dataIndex: 'productId',
key: 'productId',
},
{
title: '商品名称',
dataIndex: 'productName',
key: 'productName',
},
{
title: '成本',
dataIndex: 'cost',
key: 'cost',
render: (text: number) => `¥${text}`,
},
{
title: '售价',
dataIndex: 'price',
key: 'price',
render: (text: number) => `¥${text}`,
},
{
title: '利润',
dataIndex: 'profit',
key: 'profit',
render: (text: number) => `¥${text}`,
},
{
title: 'ROI',
dataIndex: 'roi',
key: 'roi',
render: (text: number) => `${text}%`,
},
{
title: '销量',
dataIndex: 'salesVolume',
key: 'salesVolume',
},
{
title: '日期',
dataIndex: 'date',
key: 'date',
},
];
// 准备图表数据
const chartData = mockROIData.map(item => ({
date: item.date,
销量: item.salesVolume,
利润: item.profit * item.salesVolume,
}));
const roiTrendData = mockROIData.map(item => ({
date: item.date,
ROI: item.roi,
}));
return (
<Content style={{ padding: 24, margin: 0, minHeight: 280, background: '#fff' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }}>
<Title level={4}>ROI分析</Title>
<div style={{ display: 'flex', gap: 12 }}>
<Select
placeholder="选择商品"
style={{ width: 200 }}
onChange={handleProductChange}
>
<Option value=""></Option>
<Option value="P001"></Option>
<Option value="P002">线</Option>
</Select>
<RangePicker onChange={handleTimeRangeChange} />
<Button
type="primary"
icon={<ReloadOutlined />}
onClick={handleRefresh}
loading={loading}
>
</Button>
</div>
</div>
{/* 汇总统计 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
<Col span={6}>
<Card>
<Statistic
title="总销量"
value={summary.totalSales}
prefix={<ArrowUpOutlined />}
suffix="件"
valueStyle={{ color: '#3f8600' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="总利润"
value={summary.totalProfit}
prefix="¥"
valueStyle={{ color: '#3f8600' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="平均ROI"
value={summary.averageROI}
suffix="%"
valueStyle={{ color: '#3f8600' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="最佳商品"
value={summary.bestProduct}
valueStyle={{ color: '#1890ff' }}
/>
</Card>
</Col>
</Row>
{/* 图表区域 */}
<Row gutter={[16, 16]} style={{ marginBottom: 24 }}>
<Col span={12}>
<Card title="销量与利润趋势">
<ResponsiveContainer width="100%" height={300}>
<BarChart data={chartData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" />
<YAxis />
<Tooltip />
<Legend />
<Bar dataKey="销量" fill="#1890ff" />
<Bar dataKey="利润" fill="#52c41a" />
</BarChart>
</ResponsiveContainer>
</Card>
</Col>
<Col span={12}>
<Card title="ROI趋势">
<ResponsiveContainer width="100%" height={300}>
<LineChart data={roiTrendData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="date" />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="ROI" stroke="#ff4d4f" strokeWidth={2} />
</LineChart>
</ResponsiveContainer>
</Card>
</Col>
</Row>
{/* 详细数据表格 */}
<Card title="ROI详细数据">
<Table
columns={columns}
dataSource={roiData}
rowKey="id"
loading={loading}
pagination={{ pageSize: 10 }}
/>
</Card>
</Content>
);
};
export default ROIAnalysis;

View File

@@ -0,0 +1,38 @@
import React from 'react';
import { Card, Layout, Typography, Row, Col, Button } from 'antd';
import { PlusOutlined, UploadOutlined, EditOutlined } from '@ant-design/icons';
import { Link } from 'umi';
const { Content } = Layout;
const { Title, Text } = Typography;
const ProductManagement: React.FC = () => {
return (
<Content style={{ padding: 24, margin: 0, minHeight: 280, background: '#fff' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 24 }}>
<Title level={4}></Title>
<div>
<Button type="primary" icon={<PlusOutlined />} style={{ marginRight: 8 }}>
<Link to="/Product/ProductPublishForm"></Link>
</Button>
<Button icon={<UploadOutlined />} style={{ marginRight: 8 }}>
<Link to="/Product/MaterialUpload"></Link>
</Button>
<Button icon={<EditOutlined />}>
<Link to="/Product/ProductDetail"></Link>
</Button>
</div>
</div>
<Row gutter={[16, 16]}>
<Col span={24}>
<Card title="商品列表">
<Text></Text>
</Card>
</Col>
</Row>
</Content>
);
};
export default ProductManagement;