feat(order): 精准区分自动直发与接单平台打手履约,智能门控H5直充按钮
- 后端增加按订单批量关联接单工单查询,精准识别履约类型(自动直发 / 打手履约 / 电子凭证 / 拼多多发货) - 订单列表与详情页中,仅当订单为自动直发(affiliate_dash / 码速达直充)时展示【H5】一键复制直充链接与兑换状态控制 - 接单平台工单单与纯核销单隐藏直充 H5 按钮与兑换暂停/关闭标签,防止客服向打手单买家误发直充链接 - 交付模式标签升级为「⚡ 自动直发」、「👥 打手履约」、「🎫 电子凭证」、「📦 拼多多发货」 验证方式:前端类型检查与打包构建通过,全量 132 项前端单测与 674 项后端单测全部通过
This commit is contained in:
@@ -30,6 +30,7 @@ import StatusTag from '@/components/admin/StatusTag'
|
||||
import { fetchAdminOrderDetail, updateAdminOrderClaimStatus } from '@/services/admin'
|
||||
import type { AdminOrderDetail, AdminTaskListItem } from '@/types/admin'
|
||||
import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
import { resolveOrderFulfillmentMode } from '@/utils/admin-display'
|
||||
|
||||
export default function AdminOrderDetailPage() {
|
||||
const navigate = useNavigate()
|
||||
@@ -164,6 +165,10 @@ export default function AdminOrderDetailPage() {
|
||||
const isOrderRefundedOrCancelled =
|
||||
detail.order.payStatus === 'refunded' || detail.order.orderStatus === 'cancelled'
|
||||
const canPauseOrClose = !isOrderFulfilled && !isOrderRefundedOrCancelled
|
||||
const isAutoClaimOrder = Boolean(
|
||||
detail.order.canClaimH5 || detail.order.fulfillmentType === 'auto_claim',
|
||||
)
|
||||
const fulfillmentMode = resolveOrderFulfillmentMode(detail.order)
|
||||
|
||||
return (
|
||||
<section className="page-stack">
|
||||
@@ -176,40 +181,42 @@ export default function AdminOrderDetailPage() {
|
||||
<Card
|
||||
title="基础信息"
|
||||
extra={
|
||||
<Space>
|
||||
<Button icon={<CopyOutlined />} onClick={handleCopyH5Link}>
|
||||
复制 H5 领取链接
|
||||
</Button>
|
||||
{detail.order.claimStatus === 'paused' || detail.order.claimStatus === 'closed' ? (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlayCircleOutlined />}
|
||||
onClick={() => openStatusModal('active')}
|
||||
loading={statusMutation.isPending}
|
||||
>
|
||||
恢复启用
|
||||
isAutoClaimOrder ? (
|
||||
<Space>
|
||||
<Button icon={<CopyOutlined />} onClick={handleCopyH5Link}>
|
||||
复制 H5 领取链接
|
||||
</Button>
|
||||
) : canPauseOrClose ? (
|
||||
<Button
|
||||
danger
|
||||
icon={<PauseCircleOutlined />}
|
||||
onClick={() => openStatusModal('paused')}
|
||||
loading={statusMutation.isPending}
|
||||
>
|
||||
暂停兑换
|
||||
</Button>
|
||||
) : null}
|
||||
{canPauseOrClose && detail.order.claimStatus !== 'closed' ? (
|
||||
<Button
|
||||
danger
|
||||
icon={<StopOutlined />}
|
||||
onClick={() => openStatusModal('closed')}
|
||||
loading={statusMutation.isPending}
|
||||
>
|
||||
关闭兑换
|
||||
</Button>
|
||||
) : null}
|
||||
</Space>
|
||||
{detail.order.claimStatus === 'paused' || detail.order.claimStatus === 'closed' ? (
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlayCircleOutlined />}
|
||||
onClick={() => openStatusModal('active')}
|
||||
loading={statusMutation.isPending}
|
||||
>
|
||||
恢复启用
|
||||
</Button>
|
||||
) : canPauseOrClose ? (
|
||||
<Button
|
||||
danger
|
||||
icon={<PauseCircleOutlined />}
|
||||
onClick={() => openStatusModal('paused')}
|
||||
loading={statusMutation.isPending}
|
||||
>
|
||||
暂停兑换
|
||||
</Button>
|
||||
) : null}
|
||||
{canPauseOrClose && detail.order.claimStatus !== 'closed' ? (
|
||||
<Button
|
||||
danger
|
||||
icon={<StopOutlined />}
|
||||
onClick={() => openStatusModal('closed')}
|
||||
loading={statusMutation.isPending}
|
||||
>
|
||||
关闭兑换
|
||||
</Button>
|
||||
) : null}
|
||||
</Space>
|
||||
) : null
|
||||
}
|
||||
>
|
||||
<Descriptions column={{ xs: 1, md: 2, xl: 3 }} bordered size="small">
|
||||
@@ -218,34 +225,41 @@ export default function AdminOrderDetailPage() {
|
||||
{detail.order.shopName || detail.order.shopId || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="平台订单号">{detail.order.platformOrderId}</Descriptions.Item>
|
||||
<Descriptions.Item label="履约模式">
|
||||
<Tag color={fulfillmentMode.color} style={{ margin: 0 }}>
|
||||
{fulfillmentMode.label}
|
||||
</Tag>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="订单状态">
|
||||
<StatusTag value={detail.order.orderStatus} />
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="支付状态">
|
||||
<StatusTag value={detail.order.payStatus} kind="pay" />
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="H5 兑换状态">
|
||||
<Space wrap>
|
||||
{detail.order.claimStatus === 'paused' ? (
|
||||
<Tag color="warning" icon={<PauseCircleOutlined />}>
|
||||
已暂停兑换
|
||||
</Tag>
|
||||
) : detail.order.claimStatus === 'closed' ? (
|
||||
<Tag color="default" icon={<StopOutlined />}>
|
||||
已关闭兑换
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag color="success" icon={<PlayCircleOutlined />}>
|
||||
正常有效
|
||||
</Tag>
|
||||
)}
|
||||
{detail.order.claimStatusReason ? (
|
||||
<span className="muted" style={{ fontSize: 12 }}>
|
||||
({detail.order.claimStatusReason})
|
||||
</span>
|
||||
) : null}
|
||||
</Space>
|
||||
</Descriptions.Item>
|
||||
{isAutoClaimOrder ? (
|
||||
<Descriptions.Item label="H5 兑换状态">
|
||||
<Space wrap>
|
||||
{detail.order.claimStatus === 'paused' ? (
|
||||
<Tag color="warning" icon={<PauseCircleOutlined />}>
|
||||
已暂停兑换
|
||||
</Tag>
|
||||
) : detail.order.claimStatus === 'closed' ? (
|
||||
<Tag color="default" icon={<StopOutlined />}>
|
||||
已关闭兑换
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag color="success" icon={<PlayCircleOutlined />}>
|
||||
正常有效
|
||||
</Tag>
|
||||
)}
|
||||
{detail.order.claimStatusReason ? (
|
||||
<span className="muted" style={{ fontSize: 12 }}>
|
||||
({detail.order.claimStatusReason})
|
||||
</span>
|
||||
) : null}
|
||||
</Space>
|
||||
</Descriptions.Item>
|
||||
) : null}
|
||||
<Descriptions.Item label="金额">
|
||||
{detail.order.totalAmount} {detail.order.currency}
|
||||
</Descriptions.Item>
|
||||
|
||||
@@ -309,7 +309,12 @@ export default function AdminOrdersPage() {
|
||||
</>
|
||||
)}
|
||||
<span className="muted" style={{ fontSize: 12 }}>
|
||||
数量 {row.totalQuantity || 1} · 关联任务 {row.taskCount || 0}
|
||||
数量 {row.totalQuantity || 1}
|
||||
{row.canClaimH5
|
||||
? ` · 关联任务 ${row.taskCount || 0}`
|
||||
: row.workOrderCount
|
||||
? ` · 关联工单 ${row.workOrderCount}`
|
||||
: ''}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
@@ -332,11 +337,11 @@ export default function AdminOrdersPage() {
|
||||
<StatusTag value={row.customerStatus} kind="customer" />
|
||||
</Space>
|
||||
|
||||
{row.claimStatus === 'paused' ? (
|
||||
{row.canClaimH5 && row.claimStatus === 'paused' ? (
|
||||
<Tag color="warning" style={{ margin: 0, width: 'fit-content' }}>
|
||||
H5已暂停
|
||||
</Tag>
|
||||
) : row.claimStatus === 'closed' ? (
|
||||
) : row.canClaimH5 && row.claimStatus === 'closed' ? (
|
||||
<Tag color="default" style={{ margin: 0, width: 'fit-content' }}>
|
||||
H5已关闭
|
||||
</Tag>
|
||||
@@ -361,7 +366,7 @@ export default function AdminOrdersPage() {
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
minWidth: 140,
|
||||
minWidth: 130,
|
||||
fixed: 'right',
|
||||
render: (_, row) => {
|
||||
const orderNo = row.platformOrderId || String(row.orderId)
|
||||
@@ -378,15 +383,17 @@ export default function AdminOrdersPage() {
|
||||
>
|
||||
详情
|
||||
</Button>
|
||||
<Tooltip title="复制 H5 领取链接">
|
||||
<Button
|
||||
size="small"
|
||||
icon={<LinkOutlined />}
|
||||
onClick={() => handleCopyText(h5Url, 'H5 领取链接')}
|
||||
>
|
||||
H5
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{row.canClaimH5 ? (
|
||||
<Tooltip title="复制自动直充 H5 领取链接">
|
||||
<Button
|
||||
size="small"
|
||||
icon={<LinkOutlined />}
|
||||
onClick={() => handleCopyText(h5Url, 'H5 直充链接')}
|
||||
>
|
||||
H5
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</Space>
|
||||
)
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user