plDriverPlanCopy.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /**
  2. * 司机运输计划单「复制发群」纯文本(不含附件)
  3. * 规格:docs/superpowers/specs/2026-10-12-mini-pl-driver-plan-copy-text-enrich-design.md
  4. */
  5. const DASH = '—'
  6. const FIELD_GAP = ' '
  7. function stopTypeOf(stop) {
  8. return String(stop?.stopType || stop?.stop_type || '').trim()
  9. }
  10. function customerNameOf(stop) {
  11. const name = String(stop?.customerName || stop?.customer_name || '').trim()
  12. return name || DASH
  13. }
  14. function textOrDash(value) {
  15. const s = String(value ?? '').trim()
  16. return s || DASH
  17. }
  18. function formatQtyWithUnit(raw, unit) {
  19. if (raw == null || raw === '') return DASH
  20. const qty = String(raw).trim()
  21. if (!qty) return DASH
  22. const u = String(unit || '').trim()
  23. return u ? `${qty} ${u}` : qty
  24. }
  25. function planQtyOf(product) {
  26. if (product?.planQty != null && product.planQty !== '') return product.planQty
  27. if (product?.plan_qty != null && product.plan_qty !== '') return product.plan_qty
  28. if (product?.quantity != null && product.quantity !== '') return product.quantity
  29. return null
  30. }
  31. function actualQtyOf(product) {
  32. if (product?.actualQty != null && product.actualQty !== '') return product.actualQty
  33. if (product?.actual_qty != null && product.actual_qty !== '') return product.actual_qty
  34. return null
  35. }
  36. /** 产品紧凑行:- 名称 型号 包装 计划数量:… 实际数量:… */
  37. function formatProductLine(product) {
  38. const name = textOrDash(product?.productName ?? product?.product_name)
  39. const model = textOrDash(product?.model)
  40. const pack = textOrDash(product?.packageSpec ?? product?.package_spec)
  41. const unit = product?.unit
  42. const planPart = formatQtyWithUnit(planQtyOf(product), unit)
  43. const actualPart = formatQtyWithUnit(actualQtyOf(product), unit)
  44. return (
  45. `- ${name}${FIELD_GAP}${model}${FIELD_GAP}${pack}` +
  46. `${FIELD_GAP}计划数量:${planPart}${FIELD_GAP}实际数量:${actualPart}`
  47. )
  48. }
  49. /**
  50. * 追加「送货信息:」或「装货信息:」区块。
  51. * 无站点 → 标题下单独一行 —
  52. * 有站点无产品 → 客户名:下一行 - —
  53. */
  54. function appendInfoSection(lines, title, stops) {
  55. lines.push(title)
  56. if (!stops.length) {
  57. lines.push(DASH)
  58. return
  59. }
  60. stops.forEach((stop) => {
  61. lines.push(`${customerNameOf(stop)}:`)
  62. const products = Array.isArray(stop?.products) ? stop.products : []
  63. if (!products.length) {
  64. lines.push(`- ${DASH}`)
  65. return
  66. }
  67. products.forEach((product) => {
  68. lines.push(formatProductLine(product))
  69. })
  70. })
  71. }
  72. /**
  73. * @param {object} page driverPlanApi.get 详情(可含 copySeqNo)
  74. * @returns {string}
  75. */
  76. export function buildDriverPlanCopyText(page = {}) {
  77. const stops = Array.isArray(page?.stops) ? page.stops : []
  78. const loadStops = stops.filter((s) => stopTypeOf(s) === 'load')
  79. const deliveryStops = stops.filter((s) => stopTypeOf(s) === 'delivery')
  80. const rawSeq = page?.copySeqNo ?? page?.copy_seq_no
  81. const seqText = rawSeq != null && rawSeq !== '' ? String(rawSeq) : DASH
  82. const lines = [
  83. `序号:${seqText}`,
  84. `计划编号:${textOrDash(page?.planNo ?? page?.plan_no)}`,
  85. `车辆:${textOrDash(page?.licensePlate ?? page?.license_plate)}`
  86. ]
  87. appendInfoSection(lines, '送货信息:', deliveryStops)
  88. appendInfoSection(lines, '装货信息:', loadStops)
  89. return lines.join('\n')
  90. }
  91. /** 复制到剪贴板;成功返回 true */
  92. export function copyDriverPlanToClipboard(page) {
  93. const text = buildDriverPlanCopyText(page)
  94. if (!text) {
  95. uni.showToast({ title: '暂无可复制内容', icon: 'none' })
  96. return Promise.resolve(false)
  97. }
  98. return new Promise((resolve) => {
  99. uni.setClipboardData({
  100. data: text,
  101. success: () => {
  102. uni.showToast({ title: '已复制', icon: 'success' })
  103. resolve(true)
  104. },
  105. fail: () => {
  106. uni.showToast({ title: '复制失败', icon: 'none' })
  107. resolve(false)
  108. }
  109. })
  110. })
  111. }