Files
medical-mall/pages/mall/delivery/doc/earnings.md
2026-02-02 18:20:22 +08:00

3.5 KiB
Raw Blame History

earnings.uvue — 收入明细

概要

order_no 聚合展示配送员收入明细(配送费、用户打赏、商家打赏),支持分页加载与按时间区间统计。

数据结构

  • EarningItem

    • id: string
    • order_no: string
    • date: string
    • amount: number
    • source: 'delivery_fee' | 'user_tip' | 'merchant_tip' | string
    • distance?: number
  • OrderEarning

    • order_no: string
    • date: string
    • distance?: number
    • totalAmount: number
    • details: EarningItem[]

关键方法

  • loadAllEarnings()

    • 从后端或本地数据源取原始 EarningItem[],按 order_no 聚合成 OrderEarning[]
    • 对每个 OrderEarning.details 补齐三类来源占位项amount=0以保证前端渲染顺序稳定。
  • calculateTotalStats()

    • 计算 totalEarnings, totalUserTips, totalMerchantTips
  • loadPage() / loadMore()

    • 基于 pageSize 控制分页渲染,避免一次性载入全部历史记录。

聚合示例(核心)

const orderMap = new Map()
raw.forEach(item => {
  let order = orderMap.get(item.order_no)
  if (!order) {
    order = { order_no: item.order_no, date: item.date, distance: item.distance, totalAmount: 0, details: [] }
    orderMap.set(item.order_no, order)
  }
  order.totalAmount += Number(item.amount || 0)
  order.details.push(item)
})
// 补齐三类来源
orderMap.forEach(order => {
  const has = type => order.details.some(d => d.source === type)
  ;['delivery_fee','merchant_tip','user_tip'].forEach(t => { if (!has(t)) order.details.push({ id: `${order.order_no}_${t}`, order_no: order.order_no, amount: 0, source: t }) })
})
const result = Array.from(orderMap.values())

接口 / DB 建议

  • 推荐后端提供按订单聚合的接口:
    • GET /api/driver/{id}/earnings?start=&end=&page=&size=
    • 返回 OrderEarning[] 已聚合的数据以减轻前端压力

数据源更新包含已接订单Accepted

  • 需求说明为了与“历史订单”页面保持一致收入统计应包含配送员已接取accepted/assigned的订单不仅限于已完成订单。也就是说只要 ml_delivery_tasksdriver_id = 当前司机且 status >= 2(已接取或进行中),其对应的订单都应计入收入统计范围。

  • 推荐 Supabase 查询示例(后端或前端按需实现):

-- 查询分配给当前司机且已接取的任务对应的订单ID
SELECT DISTINCT order_id FROM ml_delivery_tasks WHERE driver_id = :driverId AND status >= 2;

-- 基于 order_id 查询订单及收入项示例ml_orders + ml_delivery_tips
SELECT o.id,o.order_no,o.created_at,o.distance,o.delivery_fee, t.amount as tip_amount, 'user_tip' as tip_source
FROM ml_orders o
LEFT JOIN ml_delivery_tips t ON t.order_id = o.id
WHERE o.id IN (<order_id_list>)
ORDER BY o.created_at DESC
LIMIT :size OFFSET :offset;
  • 若在前端直接使用 supabase-js
const taskRes = await supa.from('ml_delivery_tasks').select('order_id').eq('driver_id', uid).gte('status', 2).execute()
const orderIds = taskRes.data.map(r => r.order_id)
const ordersRes = await supa.from('ml_orders').select('*,ml_delivery_tips(*)').in('id', orderIds).order('created_at',{ascending:false}).limit(size).execute()

注意:若订单很多,务必在后端做分页/聚合以减轻客户端开销。

注意事项

  • 在金额计算中使用整数 cents 或 BigInt 或固定小数处理,避免浮点误差。
  • 大量数据应后端分页/聚合并支持过滤(按时间、按来源)。