Date: 2026-09-20 | Spec: spec.md
本功能无新表、无视图、无字段变更。本文定义组合视图结构、游标格式与 tab 归类谓词的权威规则。
| 字段 | 类型 | 说明 |
|---|---|---|
| sourceType | String | takeaway / flash |
| role | String | 仅闪送有意义:sender 寄件 / receiver 收件;外卖恒 sender |
| orderId | Long | 源表主键(两表自增 ID 数值可能重叠,必须与 sourceType 联用) |
| orderNo | String | 外卖=业务单号 ddId;闪送=orderNo(FD 前缀)——详情跳转键 |
| unifiedStatus | String | 归属 tab 同款枚举(unpaid/active/completed/cancelled/refund;all 查询下返回该单实际归属的 tab 值) |
| createTime | Long | 下单时间毫秒时间戳(排序与游标基准) |
| amount | Long | 订单金额(外卖取现有列表展示金额字段,实现时对齐;闪送 amount) |
| currency | String | 币种(闪送 VND;外卖按现有返回,可为空) |
| hasAfterSale | Boolean | 外卖售后标记(afterSaleStatus>0);闪送恒 false |
type(0外送/1自取/2堂食)、state(0-4)、deliveryStatus(0-3,仅外送)、payStatus(0/1/2)、payType(1-6)、afterSaleStatus(0-6)、storeName(按 mdId 批量查 pos_store.posName,店铺已删回退订单快照 posName)、storeAvatar(pos_store.logo,同回退)、goodsCount(food 快照数组 number 求和)、collectPayment(到付标记)——数值原值透传,文案由前端渲染。
status(六态枚举原值)、orderVersion(乐观锁版本,编辑待接单订单须回传)、serviceType、deliveryType、vehicleType、deliveryMode+scheduledPickupStartAt/scheduledPickupEndAt、pickupAddress/pickupDetailAddress、deliveryAddress/deliveryDetailAddress、packageType、quantity、tipAmount、amount。
{createTimeMillis}_{sourceType}_{orderId},如 1726812345000_flash_1024。服务端生成,前端视为不透明字符串透传。createTime DESCsourceType 字典序 ASC(dinein < flash < pickup < takeaway)orderId DESCtakeaway/flash;dinein/pickup 仅在来源单选查询的游标中出现(堂食/自取是 pos_order.type 子集,单选时同源翻页同秒 id 决胜照常生效)。(t < T) OR (t = T AND 本源序 > cursor源序) OR (t = T AND 本源 = cursor源 AND id < cursorId),其中"本源序 > cursor 源序"在单源 SQL 中退化为常量布尔(实现封装在 UnifiedCursor,禁止散落拼接)。UserOrderController.orderList:555-582 现行条件| tab | 条件 |
|---|---|
| unpaid | payStatus=0 AND payType IN (2,3) AND state≠4 AND afterSaleStatus=0(仅在线支付未付) |
| active | state IN (0,1,2) AND afterSaleStatus=0 AND (payStatus=1 OR (payType IN ('1','4') AND type IN (1,2)))(2026-09-21:payType 扩入现金 4,随堂食/自取现金下单开放) |
| completed | state=3 AND afterSaleStatus=0 |
| cancelled | state=4 AND afterSaleStatus=0 |
| refund | afterSaleStatus>0 |
| all | 无条件(以上皆不过滤) |
不变量提醒(specs/018):payStatus=2 必然 state=4 且 afterSaleStatus=3——refund 条件天然覆盖已退款单。
| tab | 条件 |
|---|---|
| unpaid | —(恒空,查询层直接跳过闪送路) |
| active | status IN (WAITING_ACCEPTANCE, ACCEPTED, PICKED_UP, DELIVERED)(非终态) |
| completed | status = COMPLETED |
| cancelled | status = CANCELLED |
| refund | —(恒空,同上) |
| all | 无条件 |
UnifiedOrderTab 枚举内聚两域规则:wrapperFor(posOrder) / matches(PosOrder) 与 wrapperFor(flash) / matches(FlashDeliveryOrder);SQL 构造与内存判定使用同一组常量,单测双向校验(构造出的条件查回的样本必须全部通过内存判定)。unifiedStatus 取值 = 该单在谓词下命中的 tab(all 查询时由内存判定得出)。-- 外卖路(role 恒 sender)
-- 注:PosOrder 实体无 del_flag 字段,且现有 orderList 亦不过滤,为保持行为零漂移不加该条件
SELECT ... FROM pos_order
WHERE user_id = ? AND <来源type条件> AND <tab条件> AND <游标推进>
ORDER BY cretim DESC, id DESC
LIMIT size+1
-- 闪送路(含收件视角,OR 单查询天然去重)
SELECT ... FROM flash_delivery_order
WHERE (user_id = ? OR receiver_user_id = ?) AND <tab条件> AND <游标推进>
ORDER BY create_time DESC, id DESC
LIMIT size+1
source=takeaway → type=0(仅外送)、dinein → type=2、pickup → type=1;source=all 不加 type 条件(堂食/自取照常混排)。dinein/pickup 是外卖路子集,跳过闪送路。ORDER BY ... id DESC 对应;跨源同刻并列由 Java 归并的 source 字典序处理。tab=unpaid/refund:跳过闪送路;source 单选:跳过另一路。hasMore=true;nextCursor = 末条(t, source, id)。-- 2026-09-20 统一订单列表查询索引(030-unified-order-list,核实后执行:已存在则跳过)
ALTER TABLE pos_order ADD INDEX idx_user_cretim (user_id, cretim);
ALTER TABLE flash_delivery_order ADD INDEX idx_user_ctime (user_id, create_time);
ALTER TABLE flash_delivery_order ADD INDEX idx_receiver_ctime (receiver_user_id, create_time);
开发者先在库上 SHOW INDEX 核实,缺哪条执行哪条。
| key | 用途 |
|---|---|
no.unifiedorder.cursor.invalid |
游标格式非法 |
no.unifiedorder.param.invalid |
tab/source 取值非法 |