feat(mini-user): logistics sign photos, dial, ETA and courier callbacks (v3.4.13)
Extend Courier adapter for XFX sign photos and route callbacks; mini-user logistics UI with timeline, phone dial, and estimated arrival. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,6 +6,7 @@ export const XIAOFEIXIA_CMD = {
|
||||
GET_ORDER: '100104',
|
||||
ESTIMATE_FREIGHT: '100105',
|
||||
BATCH_GET_ORDER: '100106',
|
||||
SIGN_PHOTOS: '100108',
|
||||
DELIVERY_COVERAGE: '100301',
|
||||
} as const;
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ import type {
|
||||
ShipmentDetail,
|
||||
ShipmentQuery,
|
||||
TrackCallbackResponse,
|
||||
TrackCallbackPayload,
|
||||
TrackNode,
|
||||
CourierMappedOrderStatus,
|
||||
} from '../courier.types';
|
||||
import { XiaofeixiaClient } from './xiaofeixia.client';
|
||||
import { XIAOFEIXIA_CMD } from './xiaofeixia.constants';
|
||||
@@ -121,6 +123,57 @@ export class XiaofeixiaProvider implements ICourierProvider {
|
||||
return data ?? [];
|
||||
}
|
||||
|
||||
async getSignPhotos(query: ShipmentQuery, options?: CourierCallOptions): Promise<string[]> {
|
||||
this.assertShipmentQuery(query);
|
||||
const data = await this.client.request<string[]>(
|
||||
XIAOFEIXIA_CMD.SIGN_PHOTOS,
|
||||
{
|
||||
number: query.trackingNumber,
|
||||
outNumber: query.outNumber,
|
||||
},
|
||||
options?.xiaofeixia,
|
||||
);
|
||||
return (data ?? []).filter((item) => typeof item === 'string' && item.trim().length > 0);
|
||||
}
|
||||
|
||||
parseTrackCallback(body: unknown): TrackCallbackPayload | null {
|
||||
if (!body || typeof body !== 'object') return null;
|
||||
const raw = body as Record<string, unknown>;
|
||||
const outNumber = String(raw.outNumber ?? '').trim();
|
||||
const trackingNumber = String(raw.number ?? raw.trackingNumber ?? '').trim();
|
||||
const status = String(raw.status ?? '').trim();
|
||||
const statusName = String(raw.statusName ?? '').trim();
|
||||
const trackInfo = String(raw.trackInfo ?? '').trim();
|
||||
const createTime = String(raw.createTime ?? '').trim();
|
||||
if (!outNumber && !trackingNumber) return null;
|
||||
if (!status && !trackInfo) return null;
|
||||
return {
|
||||
outNumber,
|
||||
trackingNumber,
|
||||
status,
|
||||
statusName,
|
||||
trackInfo,
|
||||
createTime,
|
||||
};
|
||||
}
|
||||
|
||||
mapTrackStatus(status: string): CourierMappedOrderStatus | null {
|
||||
switch (String(status).trim()) {
|
||||
case '1':
|
||||
return 'OUT_WAREHOUSE';
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
return 'SHIPPING';
|
||||
case '5':
|
||||
return 'PENDING_RECEIVE';
|
||||
case '7':
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async checkDeliveryCoverage(toAddress: string, options?: CourierCallOptions): Promise<DeliveryCoverageResult> {
|
||||
const data = await this.client.request<XiaofeixiaDeliveryCoverageData>(
|
||||
XIAOFEIXIA_CMD.DELIVERY_COVERAGE,
|
||||
|
||||
Reference in New Issue
Block a user