feat(mini-user): show shipping logistics preview and detail timeline (v3.4.13)

Order detail displays latest XFX route under 配送中 with link to full timeline page; docs updated.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-05 23:03:41 +08:00
parent fa6fb80d19
commit 8ca893efab
7 changed files with 270 additions and 55 deletions
+56
View File
@@ -0,0 +1,56 @@
import { isXfxProviderCode } from '@dukang/shared-types';
import { formatShanghaiDateTime } from './datetime';
import { request } from './api';
export type OrderDelivery = {
provider?: string;
trackingNo?: string;
logisticsCompany?: string;
manualQueryUrl?: string;
};
export type OrderTrackNode = {
trackInfo?: string;
createTime?: string;
createdAt?: string;
statusName?: string;
};
export type OrderTrackResponse = {
nodes?: OrderTrackNode[];
manualQueryUrl?: string | null;
provider?: string;
trackingNo?: string;
logisticsCompany?: string;
};
/** 订单详情页展示物流摘要的状态(配送中) */
export const ORDER_LOGISTICS_PREVIEW_STATUSES = ['SHIPPING', 'SHIPPED'] as const;
export function deliveryProviderLabel(provider?: string, company?: string) {
if (company) return company;
if (!provider || provider === 'MOCK' || isXfxProviderCode(provider)) {
return '小飞侠配送';
}
if (provider === 'LOGISTICS') return '快递配送';
return provider;
}
export function shouldLoadOrderTrack(delivery?: OrderDelivery | null) {
if (!delivery) return false;
if (delivery.trackingNo) return true;
return isXfxProviderCode(delivery.provider || '');
}
export function formatTrackNodeTime(node: OrderTrackNode) {
return formatShanghaiDateTime(node.createTime || node.createdAt);
}
export function latestTrackNode(nodes: OrderTrackNode[]) {
if (nodes.length === 0) return null;
return nodes[0];
}
export async function fetchOrderTrack(orderId: string) {
return request<OrderTrackResponse>(`/trade/orders/${orderId}/track`);
}