# 多店下单:用户端与骑手端列表、详情联合方案 日期:2026-10-16;2026-10-19 收口。状态:实施目标,页面与列表接口尚未实现。本文件补充 036 的列表展示,不替代既有支付、退款、容量和逐子单履约规则。用户已确认骑手接单距离以首店为基准,以及用户端和骑手端须升级后才能使用多店功能;组合卡的具体样式和字段由本轮规格采用,仍需 App 设计验收。 同日项目审查的四项建议已获用户确认,见 spec.md FR-042~045:多店接入 037、未生效预约过期、建批后地址冻结和下调上限保护。它们已纳入本轮实施要求,不能与本文件尚未实现的页面状态混为一谈。 ## 1. 两端共用的关系 一次结算对应 `batchId`,每家店对应独立 `orderId`,选择同骑手时另有 `groupId`。用户查看结算批次,骑手承接配送组;两端通过成员子单关联,不能用同一用户、同一地址或时间接近来猜测关联。普通订单和历史订单无 036 成员关联时继续按原单笔方式展示。 | 内容 | 用户端 | 骑手端 | |---|---|---| | 普通单 | 一单一张原订单卡 | 一单一张原任务卡 | | 036 多店 | 一个批次一张多店卡,卡内逐店展示 | 同骑手一个配送组一张任务卡,卡内逐店展示 | | 列表位置 | 在外卖订单列表按下单时间与普通外卖单混排;若 App 自身另有闪送汇总,仍按来源组合展示 | 在美食待抢、待取餐、配送中等列表与普通外卖任务混排 | | 主入口 | 批次详情和继续结算;逐店可查看子单详情 | 组详情和整组接单;逐店执行原取餐、送达等操作 | | 容量 | 不适用 | 组整体占一个任务;子单数量、卡片个数和页签角标不能替代容量计数 | 圈外店不属于该批次或配送组,不出现在这张卡片内。不选择同骑手的成员不能因同批结算被包装成一个可整组承接的骑手任务。 ### 借鉴闪送多点取送 已核对闪送现有骑手列表服务、列表 DTO、用户统一列表及 [v2 前端交接文档](../../docs/flash-delivery-v2-frontend-handoff.md)。闪送采用一笔订单一张卡、一个主流程页签,同时返回逐站摘要和取送双进度:尚未取完仍在待取件,即使已有站点送达;全部取完后进入配送中。多店采用相同展示原则,撤回本草案最初“同组同时出现在待取餐和配送中”的建议,避免同一任务跨工作页签重复出现。 两端可复用卡头、取送进度和可展开明细的交互;多店明细使用成员子单,而非把各店强行转换成闪送 `stops`。闪送是一笔订单、多站履约;多店有独立商家、商品、付款、取消、退款和逐单账单。多店卡必须额外保留这些逐店事实,不复用闪送的整单收款或统一结算逻辑。当前工作区未提供 App 页面源码,本次核对的是后端实际返回及交付契约,不代表已验证真实 App 视觉效果。 ## 2. 用户端 ### 卡片与详情 多店卡头显示“多店订单 · N 家店”、下单时间及批次当前阶段;卡内逐店显示店名、商品摘要、该店实付、付款方式、支付确认及履约状态。摘要同时列出创建时订单总额、线上已实收、已退/退款中及到付约定待收,不能把到付确认标成已经扣款。原总额及各店折后金额保持创建快照,取消和退款另列分项,不向剩余成员补差,也不把不同资金方向混成一个付款成功金额。 未生效时显示“已确认 X/N 家”、支付发起截止、必要的核实中状态和“继续结算”。建批时已逐店选择方式,到付店当场确认为就绪;点击进入批次收银进度页,用户可定位尚未线上付款的店。截止后的缓冲期显示“付款结果核实中”,不再提供新发起、重试或改选;批次取消后显示各店真实退款进度。 未生效预约核实齐付款时若已到或超过原预约结束,显示预约已过期、订单已取消及真实退款进度,不进入进行中、不自动转即时。建批后地址及坐标为快照,只读展示;修改地址簿不改变这批订单,页面不提供逐店改址。 生效后仍保持一张多店卡,增加“已取餐 X/N 家 · 已送达 Y/N 单”的双进度,卡内分别显示“待接单、待取餐、配送中、已送达、已取消、退款中”等真实状态。点击卡头进入批次总览,点击店铺行进入该子单详情。取消或退款按现有 036 边界提供按钮,不能用一个汇总状态替所有子单执行操作。 ### 页签建议 “全部”每批只出现一张卡。主流程页签按整批当前阶段归类,退款/售后作为补充筛选;部分退款不能把仍在配送的其他成员从进行中列表隐藏。 | 页签 | 036 批次规则 | |---|---| | 待付款 | `PENDING` 批次,包括部分线上付款、线上结果核实中;新建成员均已选方式,历史未选记录仍可见,已付及到付已确认成员仍显示在同卡内 | | 进行中 | `ACTIVE` 且至少一个成员尚未履约结束或异常处理结束;卡内展示全部成员进度 | | 已完成 | 所有有效成员已结束且至少一单已送达;若另有取消成员,明确显示“部分取消”,不宣称每店都送达 | | 已取消 | 未生效整批取消,或生效后全部成员均已合法取消 | | 退款/售后 | 任一成员存在退款或售后记录;可同时出现在进行中等主流程页签,卡内明确标出涉及哪家店 | 批次统一生效状态、履约汇总和退款结果是三个维度。禁止仅凭 `payStatus=1`、到付默认状态、某一家已付款或某一家进入售后推导整批已生效/已结束。 ## 3. 骑手端 ### 待抢任务 批次已 `ACTIVE` 且达到预约原开放时点后,同骑手配送组才出现一次。卡头显示“多店配送 · N 店取餐 · 同一收货地址”;显示各取餐店名称、位置、即时/预约信息、共同送达位置,以及有效成员折后配送费合计。该金额沿原账单口径展示,不将其直接标为扣除佣金/税后的净收入。 无人接单按 037 现有阈值处理,基准取统一生效、首次实际开放和预约开始的最晚值;某子单先付款不提前开始,部分取消不重置。超时未接组整组从待抢消失,相关详情显示逐店取消/退款结果;接组已成功则不会再被该超时路径取消,App 以服务端返回为准。 需代收的到付金额单独展示,并逐店注明付款方式。线上已付餐费不能加入待代收现金;给各商家的到付款按各子单金额减该店折后运费展示。客户联系方式等信息继续遵守现有接单前后访问边界,不因组摘要额外公开。 一个按钮“接此组订单”在服务端原子分配全部可承接成员,成功后返回最新组和成员;竞争失败则刷新。旧单笔接单入口拒绝拆抢组成员。部分成员在接单前合法取消时重新返回有效成员、费用及版本;不能把已取消成员继续交给骑手。 骑手待抢距离、接单范围和排序统一以本批快照中的首店为基准,沿用现有外卖 `sys_qs_newtask_distance` 字典、位置时效及接单资格规则;列表展示首店到骑手的距离,接组时服务端在骑手锁内重新核验。首店到后续店的 1 公里合并围栏是另一项条件,不能代替骑手到首店的接单距离。其他店距离可在组详情逐店展示,仅供骑手规划取餐;骑手仍可自行决定取餐顺序。 ### 已接任务及混合进度 接单后保留组卡和同一组标识,沿闪送方式同时显示“已取餐 X/N 家 · 已送达 Y/N 单”。N 按当前有效成员计,另外显示原成员总数和已取消数,避免取消一店后进度变化被误解为已取餐。送达进度按子单数计,不按去重后的收货地址数计;同一个收货地址仍逐子单确认送达。进入组详情可看到各店商品、出餐状态、电话、导航、付款方式、现金金额和本店操作按钮。每个已满足条件的子单可独立取餐、送达;骑手自由决定先去哪家。某店已送达时仍可去其他店取餐,没有“全部取齐”门禁,也没有全组取餐、全组送达或全组结算按钮。 | 现有骑手页签 | 组卡出现规则 | |---|---| | 待抢 `newTask` | 符合开放条件且无人承接的组显示一次 | | 待取餐 `toPickup` | 已接组且仍有有效成员尚未取餐,组只在此工作页签显示,允许部分成员已送达;双进度和店铺行展示真实进度 | | 配送中 `delivering` | 全部有效成员均已取餐,且仍有未送达/未处理完的履约成员,组只在此工作页签显示 | | 已完成 | 所有有效成员履约或异常处理已结束,且至少一单已送达后显示组历史 | | 已取消/售后 | 展示涉及的成员及实际处理状态;仍有待处理履约成员的组继续留在对应工作页签 | 同一组只归属一个主流程工作页签,角标按任务组计一次,不按店数或站点数计。示例:三家店已取 2/3、已送达 1/3,仍在待取餐;已取 3/3、已送达 1/3 后进入配送中;全部有效成员送达/结束才进入组历史。A 已送达、B 待取时,组仍在待取餐并占一个任务。分组归类只是展示摘要,不能据此关闭已取子单的送达按钮、要求按店序取餐,或阻止已送一单后继续取另一单。 成员取消后保留该行取消历史、从待操作目标及对应待收现金中移除;剩余成员按原快照继续。已取餐异常未处理完不能仅因售后标记而从工作列表隐藏或释放容量。实际收入和退款不通过列表汇总字段回写。 ## 4. 后端和 App 的共同契约 列表必须在服务端按批次/配送组聚合后再分页和计数。不能先对子单分页、再由 App 合并,否则会跨页拆组、重复卡片、角标不一致。普通订单、用户多店批次、骑手配送组使用带类型的唯一展示键,避免不同表 ID 相同导致覆盖;父单号、组 ID 和子单号各保留其职责。 实施目标的只读字段(精确字段见 [API 契约](contracts/api.md),目前尚未实现): | 对象 | 字段信息 | |---|---| | 用户列表项 | 卡片类型、`batchId`、创建时间、批次阶段、履约摘要、退款摘要、成员总数/就绪数、两个截止、金额分项、逐店成员摘要、允许操作 | | 骑手任务项 | 任务类型、`groupId`、组版本、有效成员数/已取/已送数、折后配送费合计、到付待代收、各店距离与状态、允许操作 | | 成员摘要 | `orderId`、业务单号、店铺展示信息、付款方式、实际支付/到付确认、取送与取消状态、相关金额;按角色限制身份及联系信息 | 列表、详情、角标、通知跳转和接单响应使用同一批次/组关联。组只发一个待抢通知,点击进入组详情;逐单后续取送通知仍按已确认规则处理。接单/取消等操作后返回或刷新最新组,App 不在本地假定其他子单同步成功。 新用户端和骑手端分别使用 `/system/multiStoreCheckout/user/cards`、`/system/multiStoreCheckout/rider/tasks` 获取服务端聚合后的混合列表,列表与角标使用相同过滤口径;普通单仍是一张卡。旧 App 没有组合卡和整组接单能力,用户已确认须升级后才能使用本功能:上线前两端完成兼容版本发布与强制更新门禁,多店入口只对兼容版本开放;不允许旧骑手 App 通过原单笔接单接口拆抢组成员。已有批次用户或已承接组骑手使用旧版时提示升级,不能把新批次当普通子单允许付款、取消或接单。原非多店订单继续保持旧接口与行为。新增有 JSON body 的业务接口把业务 ID 和操作参数统一放 body;GET 的简单查询/路径参数沿项目现有规则。组接单采用 `POST /system/multiStoreCheckout/groups/accept`,body 为 `{groupId, version, clientRequestId}`,版本仅用于发现卡片过期,服务端仍须在事务锁内重验成员与容量。 ## 5. 实施与验收 字段、分页、错误及旧 App 兼容以 [API 契约](contracts/api.md) 和 [App 接入说明](frontend-app-integration.md) 为准,再实施 T014–T018、T021。App 源码由前端人员接入;本轮只交文档,不执行 SQL,也不标记页面或接口已完成。 - 普通单、多店批次、闪送混排及同时间/跨页情况,无重复、无漏单、无拆批。 - 用户部分线上付款、建批全到付即确认、缓冲、取消后退款、某店退款另店配送均能持续找到原批次。 - 骑手同组待抢只出现一次;两骑手竞争和旧单笔拆抢均不会部分分配。 - A 已取/B 待取,A 已送/B 待取,部分取消等状态下,一组只在一个主流程工作页签,双进度不被汇总状态覆盖,角标和容量按组计一次。 - 任意取餐顺序、已取成员先送达可操作,现金不包含线上已付餐费,单店操作不联动修改其他店状态。 - 未生效/未到预约开放时点不推不抢;越权读取批次/组/成员拒绝,旧 App 与普通单行为有定向回归。 本轮展示目标按闪送参考修订为:用户一批一张卡;骑手一组一张卡、一个主流程工作页签、取餐/送达双进度;用户主阶段与退款筛选可以交叉。骑手待抢距离按用户已确认的首店口径计算;两端旧 App 必须升级。以上展示目标不改变此前已确认的付款、取消、容量与自由取送规则。