import { http, unwrapApiResponse, type ApiEnvelope } from '@/shared/api/http' import { normalizeTripDetail, type TripDetail, type PickupTask, type PickupCandidate, type PickupEvidence, type PickupPlan, type TripAssignment, type TripResourceRelease } from '@/modules/overseas-master-data' export type TransportType = 'PICKUP' | 'LOCAL_TRUCK' export const transportLabels = { DELIVERY: '仓库派送', PICKUP: '到仓取货', LOCAL_TRUCK: '本土卡车' } export interface TransportDetail { dispatchNo: string; taskType: TransportType; execution: TripDetail; customerId: string | null; orderNo: string | null; pickups: PickupTask[]; completionEvidence: PickupEvidence[] } export interface TruckCandidate { customerId: string; orderNo: string; origin: string; originAddress: string; destination: string; destinationAddress: string; palletCount: number; packageCount: number } export interface TruckPlan { customerId: string; orderNo: string; warehouseId: string; plannedDepartureAt: string; expectedDriverEndAt: string; idempotencyKey: string } type WireDetail = Omit & { execution: Parameters[0] } const base = '/platform/v1/last-leg/dispatches/transport-tasks' const path = (number: string) => `${base}/${encodeURIComponent(number)}` async function get(url: string, params?: object) { return unwrapApiResponse(await http.get, ApiEnvelope>(url, { params })) } async function post(url: string, body: object) { return unwrapApiResponse(await http.post, ApiEnvelope>(url, body)) } const normalize = (value: WireDetail): TransportDetail => ({ ...value, execution: normalizeTripDetail(value.execution), pickups: value.pickups.map(row => ({ ...row, packageCount: Number(row.packageCount), actualPackages: row.actualPackages == null ? null : Number(row.actualPackages) })) }) export const getTransport = (number: string) => get(path(number)).then(normalize) export const pickupCandidates = () => get<{ records: PickupCandidate[]; total: number | string }>(`${base}/pickup-candidates`, { page: 1, size: 100 }) export const truckCandidates = () => get(`${base}/truck-candidates`) export const createTransportPickup = (body: PickupPlan) => post(`${base}/pickup`, body).then(normalize) export const createTransportTruck = (body: TruckPlan) => post(`${base}/truck`, body).then(normalize) export const assignTransport = (number: string, body: TripAssignment) => post(`${path(number)}/assign`, body).then(normalize) export const transportOccupancy = (number: string, kind: 'VEHICLE' | 'DRIVER', resourceIds: string[]) => resourceIds.length ? post>(`${path(number)}/resource-occupancy`, { kind, resourceIds }) : Promise.resolve([]) export const cancelTransport = (number: string, body: object) => post(`${path(number)}/cancel`, body) export const releaseTransport = (number: string, body: TripResourceRelease) => post(`${path(number)}/release`, body) export const commandTransport = (number: string, suffix: string, body: object) => post(`${path(number)}/${suffix}`, body) export async function uploadTransport(number: string, suffix: string, file: File) { const body = new FormData(); body.append('file', file); return post(`${path(number)}/${suffix}/files`, body) } export const downloadTransportEvidence = (number: string, fileId: string, row?: PickupTask): Promise => http.get(`${path(number)}/${row ? `pickup/${encodeURIComponent(row.customerId)}/${encodeURIComponent(row.transferNo)}` : 'truck'}/files/${encodeURIComponent(fileId)}`, { responseType: 'blob' })