|
|
@@ -1,8 +1,10 @@
|
|
|
/**
|
|
|
* 司机运输计划单「复制发群」纯文本(不含附件)
|
|
|
+ * 规格:docs/superpowers/specs/2026-10-12-mini-pl-driver-plan-copy-text-enrich-design.md
|
|
|
*/
|
|
|
|
|
|
const DASH = '—'
|
|
|
+const FIELD_GAP = ' '
|
|
|
|
|
|
function stopTypeOf(stop) {
|
|
|
return String(stop?.stopType || stop?.stop_type || '').trim()
|
|
|
@@ -13,33 +15,77 @@ function customerNameOf(stop) {
|
|
|
return name || DASH
|
|
|
}
|
|
|
|
|
|
-function formatActualQtyLine(partyLabel, product) {
|
|
|
- const unit = String(product?.unit || '').trim()
|
|
|
- const raw = product?.actualQty ?? product?.actual_qty
|
|
|
- let qtyPart = DASH
|
|
|
- if (raw != null && raw !== '') {
|
|
|
- qtyPart = String(raw)
|
|
|
- if (unit) qtyPart = `${qtyPart} ${unit}`
|
|
|
- }
|
|
|
- return `${partyLabel}:${qtyPart}`
|
|
|
+function textOrDash(value) {
|
|
|
+ const s = String(value ?? '').trim()
|
|
|
+ return s || DASH
|
|
|
+}
|
|
|
+
|
|
|
+function formatQtyWithUnit(raw, unit) {
|
|
|
+ if (raw == null || raw === '') return DASH
|
|
|
+ const qty = String(raw).trim()
|
|
|
+ if (!qty) return DASH
|
|
|
+ const u = String(unit || '').trim()
|
|
|
+ return u ? `${qty} ${u}` : qty
|
|
|
+}
|
|
|
+
|
|
|
+function planQtyOf(product) {
|
|
|
+ if (product?.planQty != null && product.planQty !== '') return product.planQty
|
|
|
+ if (product?.plan_qty != null && product.plan_qty !== '') return product.plan_qty
|
|
|
+ if (product?.quantity != null && product.quantity !== '') return product.quantity
|
|
|
+ return null
|
|
|
+}
|
|
|
+
|
|
|
+function actualQtyOf(product) {
|
|
|
+ if (product?.actualQty != null && product.actualQty !== '') return product.actualQty
|
|
|
+ if (product?.actual_qty != null && product.actual_qty !== '') return product.actual_qty
|
|
|
+ return null
|
|
|
}
|
|
|
|
|
|
-function appendQtySection(lines, title, qtyLines) {
|
|
|
+/** 产品紧凑行:- 名称 型号 包装 计划数量:… 实际数量:… */
|
|
|
+function formatProductLine(product) {
|
|
|
+ const name = textOrDash(product?.productName ?? product?.product_name)
|
|
|
+ const model = textOrDash(product?.model)
|
|
|
+ const pack = textOrDash(product?.packageSpec ?? product?.package_spec)
|
|
|
+ const unit = product?.unit
|
|
|
+ const planPart = formatQtyWithUnit(planQtyOf(product), unit)
|
|
|
+ const actualPart = formatQtyWithUnit(actualQtyOf(product), unit)
|
|
|
+ return (
|
|
|
+ `- ${name}${FIELD_GAP}${model}${FIELD_GAP}${pack}` +
|
|
|
+ `${FIELD_GAP}计划数量:${planPart}${FIELD_GAP}实际数量:${actualPart}`
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 追加「送货信息:」或「装货信息:」区块。
|
|
|
+ * 无站点 → 标题下单独一行 —
|
|
|
+ * 有站点无产品 → 客户名:下一行 - —
|
|
|
+ */
|
|
|
+function appendInfoSection(lines, title, stops) {
|
|
|
lines.push(title)
|
|
|
- if (!qtyLines.length) {
|
|
|
+ if (!stops.length) {
|
|
|
lines.push(DASH)
|
|
|
- } else {
|
|
|
- lines.push(...qtyLines)
|
|
|
+ return
|
|
|
}
|
|
|
+ stops.forEach((stop) => {
|
|
|
+ lines.push(`${customerNameOf(stop)}:`)
|
|
|
+ const products = Array.isArray(stop?.products) ? stop.products : []
|
|
|
+ if (!products.length) {
|
|
|
+ lines.push(`- ${DASH}`)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ products.forEach((product) => {
|
|
|
+ lines.push(formatProductLine(product))
|
|
|
+ })
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @param {object} page driverPlanApi.get 详情
|
|
|
+ * @param {object} page driverPlanApi.get 详情(可含 copySeqNo)
|
|
|
* @returns {string}
|
|
|
*/
|
|
|
export function buildDriverPlanCopyText(page = {}) {
|
|
|
const stops = Array.isArray(page?.stops) ? page.stops : []
|
|
|
- const loadStop = stops.find((s) => stopTypeOf(s) === 'load')
|
|
|
+ const loadStops = stops.filter((s) => stopTypeOf(s) === 'load')
|
|
|
const deliveryStops = stops.filter((s) => stopTypeOf(s) === 'delivery')
|
|
|
|
|
|
const rawSeq = page?.copySeqNo ?? page?.copy_seq_no
|
|
|
@@ -47,35 +93,12 @@ export function buildDriverPlanCopyText(page = {}) {
|
|
|
|
|
|
const lines = [
|
|
|
`序号:${seqText}`,
|
|
|
- `计划编号:${String(page?.planNo || page?.plan_no || '').trim() || DASH}`,
|
|
|
- `装货方:${loadStop ? customerNameOf(loadStop) : DASH}`
|
|
|
+ `计划编号:${textOrDash(page?.planNo ?? page?.plan_no)}`,
|
|
|
+ `车辆:${textOrDash(page?.licensePlate ?? page?.license_plate)}`
|
|
|
]
|
|
|
|
|
|
- if (!deliveryStops.length) {
|
|
|
- lines.push(`送货方#1:${DASH}`)
|
|
|
- } else {
|
|
|
- deliveryStops.forEach((stop, index) => {
|
|
|
- lines.push(`送货方#${index + 1}:${customerNameOf(stop)}`)
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- const loadQtyLines = []
|
|
|
- if (loadStop) {
|
|
|
- const products = Array.isArray(loadStop.products) ? loadStop.products : []
|
|
|
- products.forEach((product) => {
|
|
|
- loadQtyLines.push(formatActualQtyLine('装货方', product))
|
|
|
- })
|
|
|
- }
|
|
|
- appendQtySection(lines, '实际装货量:', loadQtyLines)
|
|
|
-
|
|
|
- const deliveryQtyLines = []
|
|
|
- deliveryStops.forEach((stop, index) => {
|
|
|
- const products = Array.isArray(stop?.products) ? stop.products : []
|
|
|
- products.forEach((product) => {
|
|
|
- deliveryQtyLines.push(formatActualQtyLine(`送货方#${index + 1}`, product))
|
|
|
- })
|
|
|
- })
|
|
|
- appendQtySection(lines, '实际送货量:', deliveryQtyLines)
|
|
|
+ appendInfoSection(lines, '送货信息:', deliveryStops)
|
|
|
+ appendInfoSection(lines, '装货信息:', loadStops)
|
|
|
|
|
|
return lines.join('\n')
|
|
|
}
|