import type { PlanDelivery, PlanLoad, PlanProduct, PlanStopProduct } from '@/api/pl' import { appendAmapNavLine, buildAmapNavigationUrlWithFallback } from '@/utils/amap/navigation' import { formatDate } from '@/utils/format' import { formatPlanProductListText } from '@/utils/pl-display' export type DriverSummaryStopBlock = { label: string customerName?: string stopTime?: string address?: string lng?: number | null lat?: number | null contact?: string notes?: string productLines: string[] } type DriverSummaryPlan = { planNo?: string licensePlate?: string pickupTime?: string planDate?: string personnelSummary?: string pickupAddress?: string pickupLng?: number | null pickupLat?: number | null pickupContact?: string pickupNotes?: string destinationAddress?: string destinationName?: string destinationLng?: number | null destinationLat?: number | null deliveryContact?: string destinationNotes?: string startPoint?: string endPoint?: string load?: PlanLoad | null deliveries?: PlanDelivery[] | null } function formatDriverStopProductLine( product: PlanStopProduct, getUnitLabel?: (unit: string) => string ) { return formatPlanProductListText( { productName: product.productName, model: product.model, packageSpec: product.packageSpec, unit: product.unit, quantity: product.planQty }, getUnitLabel, { usePlannedQuantity: true } ) } function formatPlanLevelProductLines( products: PlanProduct[], getUnitLabel?: (unit: string) => string ) { return products .map((product) => formatPlanProductListText(product, getUnitLabel, { usePlannedQuantity: true })) .filter(Boolean) } function appendDriverStopBlockLines(lines: string[], stop: DriverSummaryStopBlock) { lines.push(`【${stop.label} · ${stop.customerName || '—'}】`) if (stop.stopTime) { lines.push(`时间:${stop.stopTime}`) } if (stop.address) { lines.push(`地址:${stop.address}`) } appendAmapNavLine( lines, '导航', buildAmapNavigationUrlWithFallback({ lng: stop.lng, lat: stop.lat, address: stop.address, name: stop.label }) ) if (stop.contact) { lines.push(`联系方式:${stop.contact}`) } if (stop.notes) { lines.push(`注意事项:${stop.notes}`) } if (stop.productLines.length) { stop.productLines.forEach((line) => lines.push(`产品:${line}`)) } else { lines.push('产品:—') } } export function buildDriverStopBlocksFromPlan( plan?: DriverSummaryPlan | null, getUnitLabel?: (unit: string) => string ): DriverSummaryStopBlock[] { if (!plan) return [] const blocks: DriverSummaryStopBlock[] = [] const load = plan.load if (load) { blocks.push({ label: '装货', customerName: load.customerName || undefined, stopTime: formatDate(load.loadTime) || undefined, address: load.address || undefined, lng: load.lng, lat: load.lat, contact: load.contact || undefined, notes: load.notes || undefined, productLines: (load.products || []).map((product) => formatDriverStopProductLine(product, getUnitLabel) ) }) } for (const delivery of plan.deliveries || []) { const seq = delivery.seq != null ? Number(delivery.seq) : 0 blocks.push({ label: seq > 0 ? `送货 #${seq}` : '送货', customerName: delivery.customerName || undefined, stopTime: formatDate(delivery.deliveryTime) || undefined, address: delivery.address || undefined, lng: delivery.lng, lat: delivery.lat, contact: delivery.contact || undefined, notes: delivery.notes || undefined, productLines: (delivery.products || []).map((product) => formatDriverStopProductLine(product, getUnitLabel) ) }) } return blocks } function buildLegacyDriverStopBlocks( plan: DriverSummaryPlan, overrides: { pickupAddress?: string pickupLng?: number | null pickupLat?: number | null pickupContact?: string pickupNotes?: string destinationAddress?: string destinationLng?: number | null destinationLat?: number | null deliveryContact?: string destinationNotes?: string startPoint?: string endPoint?: string }, productLines: string[] ): DriverSummaryStopBlock[] { const pickupAddress = overrides.pickupAddress || plan.pickupAddress || overrides.startPoint || plan.startPoint const destinationAddress = overrides.destinationAddress || plan.destinationAddress || plan.destinationName || overrides.endPoint || plan.endPoint const blocks: DriverSummaryStopBlock[] = [] if (pickupAddress) { blocks.push({ label: '取货', customerName: plan.load?.customerName || undefined, stopTime: formatDate(plan.pickupTime) || undefined, address: pickupAddress, lng: overrides.pickupLng ?? plan.pickupLng, lat: overrides.pickupLat ?? plan.pickupLat, contact: overrides.pickupContact || plan.pickupContact || undefined, notes: overrides.pickupNotes || plan.pickupNotes || undefined, productLines: productLines.length ? productLines : [] }) } if (destinationAddress) { blocks.push({ label: '送货', customerName: undefined, stopTime: undefined, address: destinationAddress, lng: overrides.destinationLng ?? plan.destinationLng, lat: overrides.destinationLat ?? plan.destinationLat, contact: overrides.deliveryContact || plan.deliveryContact || undefined, notes: overrides.destinationNotes || plan.destinationNotes || undefined, productLines: [] }) } return blocks } export function buildPoundQrcodePublicUrl(inventoryId: string, origin = window.location.origin) { return `${origin}/#/public/pl/pound-qrcode/${encodeURIComponent(inventoryId)}` } export function buildPoundQrcodeLinksFromInventoryRecords( records: { dbInventoryId: string dbPurchasePlanId?: string businessType?: string partnerCompany?: string }[], origin = window.location.origin ) { return records .filter((r) => r.dbPurchasePlanId?.trim() && r.dbInventoryId?.trim()) .map((r) => { const bt = (r.businessType || '').trim() const pc = (r.partnerCompany || '').trim() const label = bt && pc ? `${bt} · ${pc}` : bt || pc || '磅单' return { label, url: buildPoundQrcodePublicUrl(r.dbInventoryId, origin) } }) } export function buildDriverSummaryFromPlan(options: { plan?: DriverSummaryPlan | null planNo?: string licensePlate?: string pickupTime?: string planDate?: string personnelSummary?: string driverUrl?: string products?: PlanProduct[] stopBlocks?: DriverSummaryStopBlock[] getUnitLabel?: (unit: string) => string pickupAddress?: string pickupLng?: number | null pickupLat?: number | null destinationAddress?: string destinationLng?: number | null destinationLat?: number | null pickupContact?: string pickupNotes?: string deliveryContact?: string destinationNotes?: string startPoint?: string endPoint?: string poundQrcodeLinks?: { label: string; url: string }[] }) { const plan = options.plan || {} const plate = options.licensePlate || plan.licensePlate || '—' const lines = [`【${plate} - 运输计划】`] lines.push(`计划号:${options.planNo || plan.planNo || '—'}`) lines.push(`车牌:${plate}`) const time = formatDate(options.pickupTime || plan.pickupTime) || options.planDate || plan.planDate if (time) lines.push(`时间:${time}`) const productLines = formatPlanLevelProductLines(options.products || [], options.getUnitLabel) let stopBlocks = options.stopBlocks || buildDriverStopBlocksFromPlan(plan, options.getUnitLabel) if (!stopBlocks.length) { stopBlocks = buildLegacyDriverStopBlocks(plan, options, productLines) } if (stopBlocks.length) { lines.push('') stopBlocks.forEach((stop, index) => { if (index > 0) lines.push('') appendDriverStopBlockLines(lines, stop) }) } else if (productLines.length) { lines.push('') lines.push(`产品:${productLines.join(';')}`) } lines.push('') lines.push(`司机链接:${options.driverUrl || '—'}`) const links = (options.poundQrcodeLinks || []).filter((x) => x?.url) if (links.length) { lines.push('') lines.push('磅单二维码链接:') for (const item of links) { lines.push(`${item.label}:${item.url}`) } } return lines.join('\n') }