149 lines
4.5 KiB
TypeScript
149 lines
4.5 KiB
TypeScript
import React, { useRef } from 'react';
|
||
import { PageContainer } from '@ant-design/pro-layout';
|
||
import type { ProColumns, ActionType, ProTableProps } from '@ant-design/pro-components';
|
||
import { ProTable } from '@ant-design/pro-components';
|
||
import { App } from 'antd';
|
||
import dayjs from 'dayjs';
|
||
import { ordercontrollerGetordersales } from '@/servers/api/order';
|
||
import { sitecontrollerAll } from '@/servers/api/site';
|
||
|
||
// 列表行数据结构(订单商品聚合)
|
||
interface OrderItemAggRow {
|
||
externalProductId: number; // 商品ID(来自 WooCommerce 产品ID)
|
||
externalVariationId: number; // 变体ID(来自 WooCommerce 变体ID)
|
||
name: string; // 商品名称
|
||
totalQuantity: number; // 总售出数量(时间范围内)
|
||
totalOrders: number; // 涉及订单数(去重)
|
||
firstOrderCount: number; // 客户首单次数(该商品)
|
||
secondOrderCount: number; // 客户第二次购买次数(该商品)
|
||
thirdOrderCount: number; // 客户第三次购买次数(该商品)
|
||
moreThirdOrderCount: number; // 客户超过三次购买次数(该商品)
|
||
}
|
||
|
||
const OrderItemsPage: React.FC = () => {
|
||
const actionRef = useRef<ActionType>();
|
||
const { message } = App.useApp();
|
||
|
||
// 列配置(中文标题,符合当前项目风格;显示英文默认语言可后续走国际化)
|
||
const columns: ProColumns<OrderItemAggRow>[] = [
|
||
{
|
||
title: '商品名称',
|
||
dataIndex: 'name',
|
||
width: 220,
|
||
},
|
||
{
|
||
title: '商品ID',
|
||
dataIndex: 'externalProductId',
|
||
width: 120,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '变体ID',
|
||
dataIndex: 'externalVariationId',
|
||
width: 120,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '总售出数量',
|
||
dataIndex: 'totalQuantity',
|
||
width: 130,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '订单数',
|
||
dataIndex: 'totalOrders',
|
||
width: 110,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '首单次数',
|
||
dataIndex: 'firstOrderCount',
|
||
width: 120,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '第二次购买',
|
||
dataIndex: 'secondOrderCount',
|
||
width: 120,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '第三次购买',
|
||
dataIndex: 'thirdOrderCount',
|
||
width: 120,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '超过三次购买',
|
||
dataIndex: 'moreThirdOrderCount',
|
||
width: 140,
|
||
hideInSearch: true,
|
||
},
|
||
// 搜索区域字段
|
||
{
|
||
title: '站点',
|
||
dataIndex: 'siteId',
|
||
valueType: 'select',
|
||
request: async () => {
|
||
// 拉取站点列表(后台 /site/all)
|
||
const { data = [] } = await sitecontrollerAll();
|
||
return (data || []).map((item: any) => ({ label: item.siteName, value: item.id }));
|
||
},
|
||
},
|
||
{
|
||
title: '时间范围',
|
||
dataIndex: 'dateRange',
|
||
valueType: 'dateRange',
|
||
hideInTable: true,
|
||
},
|
||
{
|
||
title: '商品关键字',
|
||
dataIndex: 'name',
|
||
hideInTable: true,
|
||
},
|
||
];
|
||
|
||
// 表格请求方法:调用 /order/getOrderSales 接口并设置 isSource=true 获取订单项聚合
|
||
const request: ProTableProps<OrderItemAggRow>['request'] = async (params:any) => {
|
||
try {
|
||
const { current = 1, pageSize = 10, siteId, name } = params as any;
|
||
const [startDate, endDate] = (params as any).dateRange || [];
|
||
// 调用后端接口(isSource=true 表示按订单项聚合)
|
||
const resp = await ordercontrollerGetordersales({
|
||
current,
|
||
pageSize,
|
||
siteId,
|
||
name,
|
||
isSource: true as any,
|
||
startDate: startDate ? (dayjs(startDate).toISOString() as any) : undefined,
|
||
endDate: endDate ? (dayjs(endDate).toISOString() as any) : undefined,
|
||
} as any);
|
||
const { success, data, message: errMsg } = resp as any;
|
||
if (!success) throw new Error(errMsg || '获取失败');
|
||
return {
|
||
data: (data?.items ?? []) as OrderItemAggRow[],
|
||
total: data?.total ?? 0,
|
||
success: true,
|
||
};
|
||
} catch (e: any) {
|
||
message.error(e?.message || '获取失败');
|
||
return { data: [], total: 0, success: false };
|
||
}
|
||
};
|
||
|
||
return (
|
||
<PageContainer title='订单商品概览'>
|
||
<ProTable<OrderItemAggRow>
|
||
actionRef={actionRef}
|
||
rowKey={(r) => `${r.externalProductId}-${r.externalVariationId}-${r.name}`}
|
||
columns={columns}
|
||
request={request}
|
||
pagination={{ showSizeChanger: true }}
|
||
search={{ labelWidth: 90, span: 6 }}
|
||
toolBarRender={false}
|
||
/>
|
||
</PageContainer>
|
||
);
|
||
};
|
||
|
||
export default OrderItemsPage; |