Files
medical-mall/pages/mall/delivery/doc/old(弃用)/earnings.md
2026-03-17 11:06:26 +08:00

93 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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_tasks``driver_id` = 当前司机且 `status >= 2`(已接取或进行中),其对应的订单都应计入收入统计范围。
- 需求说明(已采纳):收入统计以 `ml_delivery_tasks` 为数据源之一:只要任务记录显示 `driver_id` = 当前司机且 `status >= 2`(已接取或进行中),其对应订单即应计入统计范围。注意:部分 `ml_delivery_tasks` 可能没有可匹配的 `ml_orders``order_id` 为空或在 `ml_orders` 中找不到),页面/后端应对缺失 `order_no` 做回退显示并记录供核查。
- 推荐 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`
```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)
// 对于 order_id 为空或找不到的情况server 端应记录这些 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 或固定小数处理,避免浮点误差。
- 大量数据应后端分页/聚合并支持过滤(按时间、按来源)。