@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Link, useSearchParams } from 'react-router-dom';
|
||||
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
@@ -27,10 +27,12 @@ import dayjs, { type Dayjs } from 'dayjs';
|
||||
import { ORDER_TYPE_LABELS } from '@dukang/shared-types';
|
||||
import { request, type AdminOrderItem, type AdminOrderRow, type HqProfile, type Paginated } from '../lib/api';
|
||||
import { useAdminListColumns } from '../lib/useAdminListColumns';
|
||||
import { AdminPrimaryLink } from '../components/AdminPrimaryLink';
|
||||
import { downloadBase64File } from '../lib/exportExcel';
|
||||
import {
|
||||
ADMIN_OPTIONS_PAGE_SIZE,
|
||||
DELIVERY_PROVIDER_LABELS,
|
||||
DELIVERY_TYPE_LABELS,
|
||||
ORDER_STATUS_COLORS,
|
||||
ORDER_STATUS_LABELS,
|
||||
ORDER_STATUS_OPERATOR_LABELS,
|
||||
@@ -273,6 +275,7 @@ function warehouseToDefaults(wh: WarehouseOption, base?: ShipDefaults | null): S
|
||||
}
|
||||
|
||||
export default function OrdersPage() {
|
||||
const navigate = useNavigate();
|
||||
const [searchParams] = useSearchParams();
|
||||
const initialOrderNo = searchParams.get('orderNo')?.trim() || '';
|
||||
const [form] = Form.useForm();
|
||||
@@ -593,63 +596,98 @@ export default function OrdersPage() {
|
||||
|
||||
const baseColumns: ColumnsType<AdminOrderRow> = [
|
||||
{
|
||||
title: '商品',
|
||||
width: 240,
|
||||
render: (_, row) => (
|
||||
<div>
|
||||
<Space size={4} wrap>
|
||||
<span>{row.productName || '—'}</span>
|
||||
{row.isTest ? <Tag color="orange">测试</Tag> : null}
|
||||
{row.fulfillmentHold ? <Tag color="orange">大单</Tag> : null}
|
||||
{row.orderType === 'PROXY' || row.isProxyOrder ? (
|
||||
<Tag color="purple">代下单</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
<div>
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{[row.productSpec, row.quantity != null ? `×${row.quantity}` : null]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
title: '订单号',
|
||||
dataIndex: 'orderNo',
|
||||
width: 180,
|
||||
render: (v, row) => (
|
||||
<Space size={4}>
|
||||
<AdminPrimaryLink onClick={() => openDetail(row.id)}>{v}</AdminPrimaryLink>
|
||||
{row.isTest ? <Tag color="orange">测试</Tag> : null}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '状态 / 实付',
|
||||
width: 130,
|
||||
title: '用户',
|
||||
key: 'user',
|
||||
width: 120,
|
||||
render: (_, row) =>
|
||||
row.user?.id ? (
|
||||
<AdminPrimaryLink onClick={() => navigate('/users', { state: { openUserId: String(row.user!.id) } })}>
|
||||
{row.user.userNo}
|
||||
</AdminPrimaryLink>
|
||||
) : (
|
||||
(row.user?.userNo || '—')
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '商品',
|
||||
key: 'productName',
|
||||
width: 180,
|
||||
render: (_, row) => (
|
||||
<div>
|
||||
<Tag color={ORDER_STATUS_COLORS[row.status] || 'default'}>
|
||||
{ORDER_STATUS_LABELS[row.status] || row.status}
|
||||
</Tag>
|
||||
<div>¥{row.payAmount}</div>
|
||||
</div>
|
||||
<Space size={4} wrap>
|
||||
<span>{row.productName || '—'}</span>
|
||||
{row.fulfillmentHold ? <Tag color="orange">大单</Tag> : null}
|
||||
{row.orderType === 'PROXY' || row.isProxyOrder ? (
|
||||
<Tag color="purple">代下单</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '规格',
|
||||
dataIndex: 'productSpec',
|
||||
width: 140,
|
||||
render: (v: string | undefined) => v || '—',
|
||||
},
|
||||
{
|
||||
title: '数量',
|
||||
dataIndex: 'quantity',
|
||||
width: 80,
|
||||
render: (v: number | undefined, row) =>
|
||||
v == null ? '—' : `${v}${row.saleUnit === 'BOX' ? '箱' : '瓶'}`,
|
||||
},
|
||||
{
|
||||
title: '配送方式',
|
||||
dataIndex: 'deliveryType',
|
||||
width: 100,
|
||||
render: (v: string | undefined) => DELIVERY_TYPE_LABELS[v ?? ''] || v || '—',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
width: 100,
|
||||
render: (s: string) => (
|
||||
<Tag color={ORDER_STATUS_COLORS[s] || 'default'}>{ORDER_STATUS_LABELS[s] || s}</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '实付',
|
||||
dataIndex: 'payAmount',
|
||||
width: 90,
|
||||
render: (v: number) => `¥${v}`,
|
||||
},
|
||||
{
|
||||
title: '好客权益',
|
||||
width: 200,
|
||||
render: (_, row) => formatBenefitBrief(row),
|
||||
},
|
||||
{
|
||||
title: '收货信息',
|
||||
width: 240,
|
||||
render: (_, row) => {
|
||||
const address = formatReceiverAddress(row);
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
{row.receiverName || '—'} {row.receiverPhone || ''}
|
||||
</div>
|
||||
{address ? (
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{address}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
title: '收货人',
|
||||
dataIndex: 'receiverName',
|
||||
width: 90,
|
||||
render: (v: string | undefined) => v || '—',
|
||||
},
|
||||
{
|
||||
title: '电话',
|
||||
dataIndex: 'receiverPhone',
|
||||
width: 120,
|
||||
render: (v: string | undefined) => v || '—',
|
||||
},
|
||||
{
|
||||
title: '地址',
|
||||
key: 'receiverAddress',
|
||||
width: 260,
|
||||
render: (_, row) => formatReceiverAddress(row) || '—',
|
||||
},
|
||||
{
|
||||
title: '下单时间',
|
||||
|
||||
Reference in New Issue
Block a user