253 lines
6.4 KiB
TypeScript
253 lines
6.4 KiB
TypeScript
import { ordercontrollerGetorders } from '@/servers/api/order';
|
||
import {
|
||
App,
|
||
Col,
|
||
Modal,
|
||
Row,
|
||
Spin,
|
||
Statistic,
|
||
Table,
|
||
Tag,
|
||
Typography,
|
||
} from 'antd';
|
||
import dayjs from 'dayjs';
|
||
import { useState } from 'react';
|
||
|
||
const { Text, Title } = Typography;
|
||
|
||
interface HistoryOrdersProps {
|
||
customer: API.UnifiedCustomerDTO;
|
||
siteId?: number;
|
||
}
|
||
|
||
interface OrderStats {
|
||
totalOrders: number;
|
||
totalAmount: number;
|
||
yooneOrders: number;
|
||
yooneAmount: number;
|
||
}
|
||
|
||
const HistoryOrders: React.FC<HistoryOrdersProps> = ({ customer, siteId }) => {
|
||
const { message } = App.useApp();
|
||
const [modalVisible, setModalVisible] = useState(false);
|
||
const [orders, setOrders] = useState<any[]>([]);
|
||
const [loading, setLoading] = useState(false);
|
||
const [stats, setStats] = useState<OrderStats>({
|
||
totalOrders: 0,
|
||
totalAmount: 0,
|
||
yooneOrders: 0,
|
||
yooneAmount: 0,
|
||
});
|
||
|
||
// 计算订单统计信息
|
||
const calculateStats = (orders: any[]) => {
|
||
let totalOrders = 0;
|
||
let totalAmount = 0;
|
||
let yooneOrders = 0;
|
||
let yooneAmount = 0;
|
||
|
||
orders.forEach((order) => {
|
||
totalOrders++;
|
||
// total是字符串,需要转换为数字
|
||
const orderTotal = parseFloat(order.total || '0');
|
||
totalAmount += orderTotal;
|
||
|
||
// 检查订单中是否包含yoone商品
|
||
let hasYoone = false;
|
||
let orderYooneAmount = 0;
|
||
|
||
// 优先使用line_items,如果没有则使用items
|
||
const items = order.line_items || order.items || [];
|
||
if (Array.isArray(items)) {
|
||
items.forEach((item: any) => {
|
||
// 检查商品名称或SKU是否包含yoone(不区分大小写)
|
||
const itemName = (item.name || '').toLowerCase();
|
||
const sku = (item.sku || '').toLowerCase();
|
||
|
||
if (itemName.includes('yoone') || sku.includes('yoone')) {
|
||
hasYoone = true;
|
||
const itemTotal = parseFloat(item.total || item.price || '0');
|
||
orderYooneAmount += itemTotal;
|
||
}
|
||
});
|
||
}
|
||
|
||
if (hasYoone) {
|
||
yooneOrders++;
|
||
yooneAmount += orderYooneAmount;
|
||
}
|
||
});
|
||
|
||
return {
|
||
totalOrders,
|
||
totalAmount,
|
||
yooneOrders,
|
||
yooneAmount,
|
||
};
|
||
};
|
||
|
||
// 获取客户订单数据
|
||
const fetchOrders = async () => {
|
||
setLoading(true);
|
||
try {
|
||
const response = await ordercontrollerGetorders({
|
||
customer_email: customer.email,
|
||
});
|
||
|
||
if (response) {
|
||
const orderList = response.items || [];
|
||
setOrders(orderList);
|
||
const calculatedStats = calculateStats(orderList);
|
||
setStats(calculatedStats);
|
||
} else {
|
||
message.error('获取订单数据失败');
|
||
}
|
||
} catch (error) {
|
||
console.error('获取订单失败:', error);
|
||
message.error('获取订单失败');
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
// 打开弹框时获取数据
|
||
const handleOpenModal = () => {
|
||
setModalVisible(true);
|
||
fetchOrders();
|
||
};
|
||
|
||
// 订单表格列配置
|
||
const orderColumns = [
|
||
{
|
||
title: '订单号',
|
||
dataIndex: 'externalOrderId',
|
||
key: 'externalOrderId',
|
||
width: 120,
|
||
},
|
||
{
|
||
title: '订单状态',
|
||
dataIndex: 'status',
|
||
key: 'status',
|
||
width: 100,
|
||
render: (status: string) => {
|
||
const statusMap: Record<string, string> = {
|
||
pending: '待处理',
|
||
processing: '处理中',
|
||
'on-hold': '等待中',
|
||
completed: '已完成',
|
||
cancelled: '已取消',
|
||
refunded: '已退款',
|
||
failed: '失败',
|
||
};
|
||
return <Tag color="blue">{statusMap[status] || status}</Tag>;
|
||
},
|
||
},
|
||
{
|
||
title: '订单金额',
|
||
dataIndex: 'total',
|
||
key: 'total',
|
||
width: 100,
|
||
render: (total: string, record: any) => (
|
||
<Text>
|
||
{record.currency_symbol || '$'}
|
||
{parseFloat(total || '0').toFixed(2)}
|
||
</Text>
|
||
),
|
||
},
|
||
{
|
||
title: '创建时间',
|
||
dataIndex: 'date_created',
|
||
key: 'date_created',
|
||
width: 140,
|
||
render: (date: string) => (
|
||
<Text>{date ? dayjs(date).format('YYYY-MM-DD HH:mm') : '-'}</Text>
|
||
),
|
||
},
|
||
{
|
||
title: '包含Yoone',
|
||
key: 'hasYoone',
|
||
width: 80,
|
||
render: (_: any, record: any) => {
|
||
let hasYoone = false;
|
||
const items = record.line_items || record.items || [];
|
||
if (Array.isArray(items)) {
|
||
hasYoone = items.some((item: any) => {
|
||
const itemName = (item.name || '').toLowerCase();
|
||
const sku = (item.sku || '').toLowerCase();
|
||
return itemName.includes('yoone') || sku.includes('yoone');
|
||
});
|
||
}
|
||
return hasYoone ? <Tag color="green">是</Tag> : <Tag>否</Tag>;
|
||
},
|
||
},
|
||
];
|
||
|
||
return (
|
||
<>
|
||
<a onClick={handleOpenModal}>历史订单</a>
|
||
|
||
<Modal
|
||
title={`${customer.fullname || customer.email} 的历史订单`}
|
||
open={modalVisible}
|
||
onCancel={() => setModalVisible(false)}
|
||
footer={null}
|
||
width={1000}
|
||
>
|
||
<Spin spinning={loading}>
|
||
{/* 统计信息 */}
|
||
<Row gutter={16} style={{ marginBottom: 24 }}>
|
||
<Col span={6}>
|
||
<Statistic
|
||
title="总订单数"
|
||
value={stats.totalOrders}
|
||
prefix="#"
|
||
/>
|
||
</Col>
|
||
<Col span={6}>
|
||
<Statistic
|
||
title="总金额"
|
||
value={stats.totalAmount}
|
||
precision={2}
|
||
prefix="$"
|
||
/>
|
||
</Col>
|
||
<Col span={6}>
|
||
<Statistic
|
||
title="Yoone订单数"
|
||
value={stats.yooneOrders}
|
||
prefix="#"
|
||
/>
|
||
</Col>
|
||
<Col span={6}>
|
||
<Statistic
|
||
title="Yoone金额"
|
||
value={stats.yooneAmount}
|
||
precision={2}
|
||
prefix="$"
|
||
/>
|
||
</Col>
|
||
</Row>
|
||
|
||
{/* 订单列表 */}
|
||
<Title level={4} style={{ marginTop: 24 }}>
|
||
订单详情
|
||
</Title>
|
||
<Table
|
||
columns={orderColumns}
|
||
dataSource={orders}
|
||
rowKey="id"
|
||
pagination={{
|
||
pageSize: 10,
|
||
showSizeChanger: true,
|
||
showTotal: (total) => `共 ${total} 条`,
|
||
}}
|
||
scroll={{ x: 800 }}
|
||
/>
|
||
</Spin>
|
||
</Modal>
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default HistoryOrders;
|