231 lines
7.3 KiB
TypeScript
231 lines
7.3 KiB
TypeScript
import React, { useRef, useState } 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, Tag, Button, Drawer, List } from 'antd';
|
||
import dayjs from 'dayjs';
|
||
import { ordercontrollerGetorders } from '@/servers/api/order';
|
||
import { sitecontrollerAll } from '@/servers/api/site';
|
||
import { request } from 'umi';
|
||
|
||
interface OrderItemRow {
|
||
id: number;
|
||
externalOrderId: string;
|
||
siteId: string;
|
||
date_created: string;
|
||
customer_email: string;
|
||
payment_method: string;
|
||
total: number;
|
||
orderStatus: string;
|
||
}
|
||
|
||
const OrdersPage: React.FC = () => {
|
||
const actionRef = useRef<ActionType>();
|
||
const { message } = App.useApp();
|
||
// 抽屉状态:用于展示与订阅相关的订单详情(含行项目meta)
|
||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||
const [drawerTitle, setDrawerTitle] = useState<string>('订阅关联');
|
||
const [drawerItems, setDrawerItems] = useState<any[]>([]);
|
||
const [drawerMeta, setDrawerMeta] = useState<any[]>([]);
|
||
const [isSubscription, setIsSubscription] = useState<boolean>(false);
|
||
|
||
const columns: ProColumns<OrderItemRow>[] = [
|
||
{
|
||
title: '订单ID',
|
||
dataIndex: 'externalOrderId',
|
||
width: 120,
|
||
ellipsis: true,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '站点',
|
||
dataIndex: 'siteId',
|
||
width: 120,
|
||
valueType: 'select',
|
||
request: async () => {
|
||
const { data = [] } = await sitecontrollerAll();
|
||
return (data || []).map((item: any) => ({ label: item.siteName, value: item.id }));
|
||
},
|
||
},
|
||
{
|
||
title: '下单时间',
|
||
dataIndex: 'date_created',
|
||
width: 180,
|
||
hideInSearch: true,
|
||
render: (_, row) => (row?.date_created ? dayjs(row.date_created).format('YYYY-MM-DD HH:mm') : '-'),
|
||
},
|
||
{
|
||
title: '邮箱',
|
||
dataIndex: 'customer_email',
|
||
width: 200,
|
||
},
|
||
{
|
||
title: '支付方式',
|
||
dataIndex: 'payment_method',
|
||
width: 140,
|
||
},
|
||
{
|
||
title: '金额',
|
||
dataIndex: 'total',
|
||
width: 100,
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: 'ERP状态',
|
||
dataIndex: 'orderStatus',
|
||
width: 120,
|
||
hideInSearch: true,
|
||
render: (_, row) => <Tag>{row.orderStatus}</Tag>,
|
||
},
|
||
{
|
||
title: '订阅关联',
|
||
dataIndex: 'subscription_related',
|
||
width: 120,
|
||
hideInSearch: true,
|
||
render: (_, row) => (
|
||
<Button
|
||
size="small"
|
||
onClick={async () => {
|
||
try {
|
||
// 拉取订单详情(包含 items 与 meta_data),用于判断是否为订阅订单
|
||
const resp = await request(`/order/${row.id}`, { method: 'GET' });
|
||
const { success, data, message: errMsg } = resp as any;
|
||
if (!success) throw new Error(errMsg || '获取失败');
|
||
const items: any[] = data?.items || [];
|
||
const orderMeta: any[] = data?.meta_data || [];
|
||
// 订阅识别:检查行项目 meta_data 中的关键键
|
||
const keys = [
|
||
'is_subscription',
|
||
'_wcs_bought_as_subscription',
|
||
'subscription_product_type',
|
||
'subscription_period',
|
||
'subscription_interval',
|
||
'_subscription',
|
||
'_subscription_period',
|
||
'_subscription_interval',
|
||
];
|
||
let detected = false;
|
||
for (const it of items) {
|
||
const md = Array.isArray(it?.meta_data) ? it.meta_data : [];
|
||
if (md.some((m: any) => keys.includes(String(m?.key)))) {
|
||
detected = true;
|
||
break;
|
||
}
|
||
}
|
||
setIsSubscription(detected);
|
||
setDrawerItems(items);
|
||
setDrawerMeta(orderMeta);
|
||
setDrawerTitle(`订阅关联(订单号:${row.externalOrderId})`);
|
||
setDrawerOpen(true);
|
||
} catch (e: any) {
|
||
message.error(e?.message || '获取失败');
|
||
}
|
||
}}
|
||
>
|
||
查看
|
||
</Button>
|
||
),
|
||
},
|
||
{
|
||
title: '时间范围',
|
||
dataIndex: 'dateRange',
|
||
valueType: 'dateRange',
|
||
hideInTable: true,
|
||
},
|
||
{
|
||
title: '商品关键字',
|
||
dataIndex: 'keyword',
|
||
hideInTable: true,
|
||
},
|
||
];
|
||
|
||
const request: ProTableProps<OrderItemRow>['request'] = async (params) => {
|
||
try {
|
||
const { current = 1, pageSize = 10, siteId, keyword, customer_email, payment_method } = params as any;
|
||
const [startDate, endDate] = (params as any).dateRange || [];
|
||
const resp = await ordercontrollerGetorders({
|
||
current,
|
||
pageSize,
|
||
siteId,
|
||
keyword,
|
||
customer_email,
|
||
payment_method,
|
||
isSubscriptionOnly: 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 OrderItemRow[],
|
||
total: data?.total ?? 0,
|
||
success: true,
|
||
};
|
||
} catch (e: any) {
|
||
message.error(e?.message || '获取失败');
|
||
return { data: [], total: 0, success: false };
|
||
}
|
||
};
|
||
|
||
return (
|
||
<PageContainer title='订阅订单'>
|
||
<ProTable<OrderItemRow>
|
||
actionRef={actionRef}
|
||
rowKey='id'
|
||
columns={columns}
|
||
request={request}
|
||
pagination={{ showSizeChanger: true }}
|
||
search={{
|
||
labelWidth: 90,
|
||
span: 6,
|
||
}}
|
||
toolBarRender={false}
|
||
/>
|
||
{/* 订阅关联抽屉:展示行项目与订单元数据,标注是否订阅 */}
|
||
<Drawer
|
||
open={drawerOpen}
|
||
title={drawerTitle}
|
||
width={720}
|
||
onClose={() => setDrawerOpen(false)}
|
||
>
|
||
<div style={{ marginBottom: 12 }}>
|
||
<Tag color={isSubscription ? 'green' : 'default'}>
|
||
{isSubscription ? '订阅订单' : '非订阅订单'}
|
||
</Tag>
|
||
</div>
|
||
{/* 行项目列表,展示 meta_data 关键键值 */}
|
||
<List
|
||
header={<div>订单行项目</div>}
|
||
dataSource={drawerItems}
|
||
renderItem={(item: any) => (
|
||
<List.Item>
|
||
<List.Item.Meta
|
||
title={`${item?.name || '-'}(数量:${item?.quantity || 0})`}
|
||
description={`SKU:${item?.sku || '-'},产品ID:${item?.externalProductId || '-'},变体ID:${item?.externalVariationId || '-'}`}
|
||
/>
|
||
<div style={{ maxWidth: 420 }}>
|
||
{(Array.isArray(item?.meta_data) ? item.meta_data : []).map((m: any) => (
|
||
<Tag key={`${m?.key}-${m?.id}`}>{`${m?.key}: ${m?.value}`}</Tag>
|
||
))}
|
||
</div>
|
||
</List.Item>
|
||
)}
|
||
/>
|
||
{/* 订单级元数据 */}
|
||
<List
|
||
style={{ marginTop: 16 }}
|
||
header={<div>订单元数据</div>}
|
||
dataSource={drawerMeta}
|
||
renderItem={(m: any) => (
|
||
<List.Item>
|
||
<Tag>{`${m?.key}: ${m?.value}`}</Tag>
|
||
</List.Item>
|
||
)}
|
||
/>
|
||
</Drawer>
|
||
</PageContainer>
|
||
);
|
||
};
|
||
|
||
export default OrdersPage;
|