三端管理不是做三个独立小程序,而是用一套共享订单、商品、用户、骑手和结算数据的后端,配用户端、商家端、骑手端三类角色入口,再由平台后台统一管控。实现时以订单号为主线:权限在服务端按账号、角色和数据范围校验,状态只由后端状态机推进,关键节点通过消息通知同步。校园外卖还要增加校门交接、集中收餐、楼栋分拣、批量通知和多校区数据范围。首期验收用正常单、转单单、退款单和越权访问四组场景,核对状态、金额、责任人是否一致。
三端入口可以分别是用户小程序、商家小程序或网页、骑手小程序,平台后台用PC网页;入口形态不同,订单主键、商品、用户、骑手和结算数据必须同源。否则一笔订单在商家、骑手、用户三处会出现不同状态和金额,客服与财务只能人工拼表。
角色端 | 首期职责 | 关键数据 |
|---|---|---|
用户端 | 选商家或发跑腿、支付、看进度、售后 | 订单号、地址、实付金额、优惠 |
商家端 | 商品、接单出餐、缺货处理、对账 | 门店、商品明细、应结金额 |
骑手端 | 接单或抢单、取送凭证、转单、收益 | 任务号、交接时间、送达凭证 |
平台后台 | 审核、调度、权限、结算、售后、配置 | 校区、站点、角色、资金记录 |
数据层建议至少拆成订单主表、订单明细、状态事件、骑手任务、结算记录和退款记录,全部用订单号关联。外卖订单有商家和商品,跑腿任务可以没有商家;两类订单可共用地址和骑手池,但计价、结算和售后记录分开,避免退款与分账互相影响。
权限不能靠前端隐藏按钮。登录后会话中应带角色和归属标识,例如 platform、campus_admin、site、merchant、rider、finance、support,以及 merchant_id、rider_id、campus_id、site_id。每个接口先校验操作者能否访问该资源,再执行查询或写入;列表查询和导出使用同一套数据范围。商家只能看本店订单、商品和流水,骑手只能看分配给自己的任务和收益,校区管理员只能看本校数据。
角色 | 可见范围 | 可操作范围 | 导出控制 |
|---|---|---|---|
总部/财务 | 全平台订单、结算、退款 | 配置、审核、结算复核 | 按岗位授权,导出列与可见列一致 |
校区管理员 | 本校商家、骑手、订单、账单 | 本校区调度、人员、售后 | 仅本校数据 |
站点 | 本站订单与交接任务 | 收餐、分拣、中转、送达 | 本站任务与凭证 |
商家 | 本店订单、商品、流水 | 接单、出餐、对账、提现申请 | 本店账单 |
骑手 | 本人任务与收益 | 接单、取送、转单申请 | 本人收益 |
客服 | 授权校区或工单关联订单 | 查询、售后、工单处理 | 按工单与校区授权 |
导出是容易漏掉的越权点:同一报表在不同子账号下,可见列和可导出列应一致;财务、客服、站点的导出字段按岗位授权。验收时用商家账号、骑手账号和校区账号交叉访问,记录被拦截的请求。
下面是一个只依赖标准库的权限校验示例,运行环境为Python 3.10及以上。它用于说明资源归属校验应放在服务端,而不是前端按钮。
from dataclasses import dataclass
from typing import Literal
Role = Literal['platform', 'campus_admin', 'site', 'merchant', 'rider', 'finance', 'support']
@dataclass(frozen=True)
class Principal:
role: Role
user_id: int
merchant_id: int | None = None
rider_id: int | None = None
campus_id: int | None = None
site_id: int | None = None
@dataclass(frozen=True)
class OrderScope:
order_id: int
merchant_id: int
rider_id: int | None
campus_id: int
site_id: int
def can_read_order(p: Principal, o: OrderScope) -> bool:
if p.role in {'platform', 'finance'}:
return True
if p.role == 'campus_admin':
return p.campus_id == o.campus_id
if p.role == 'site':
return p.campus_id == o.campus_id and p.site_id == o.site_id
if p.role == 'merchant':
return p.merchant_id == o.merchant_id
if p.role == 'rider':
return p.rider_id == o.rider_id
if p.role == 'support':
return p.campus_id is None or p.campus_id == o.campus_id
return False验证方法:用不同Principal调用can_read_order,预期商家读取同店订单返回True、读取他店订单返回False;骑手读取本人任务返回True、读取他人任务返回False。
状态不能由前端按钮直接改。订单主表保存当前状态,状态事件表记录每次变更;服务端用允许转移表校验,例如未支付不能接单,未取餐不能送达,已结算退款要生成冲回记录。转单不是简单换人:原骑手任务结束、新骑手任务生成、用户进度和商家账单同步更新。重复提交和重复回调用幂等键与事件唯一键拦截。
验收单 | 观察点 | 留证 |
|---|---|---|
正常单 | 支付、接单、取餐、送达、结算状态与金额一致 | 订单轨迹、支付与结算记录 |
转单单 | 原任务结束、新任务生成、用户进度和商家账单同步 | 转单原因、操作人、任务记录 |
退款单 | 接单前、配送中、部分退款和结算后退款均可冲回 | 退款单、原结算关联记录 |
重复操作/支付超时 | 同一请求只形成一次有效处理,超时可查询与复核 | 幂等键、事件唯一键、处理日志 |
下面给出订单主表和事件表的最小结构示例,重点是可追溯与幂等,属于设计示例,不是某个产品的内部实现。
CREATE TABLE biz_order (
order_no VARCHAR(32) PRIMARY KEY,
order_type VARCHAR(16) NOT NULL,
merchant_id VARCHAR(32),
rider_id VARCHAR(32),
campus_id VARCHAR(32) NOT NULL,
site_id VARCHAR(32) NOT NULL,
status VARCHAR(24) NOT NULL,
user_paid DECIMAL(10,2) NOT NULL,
refunded DECIMAL(10,2) NOT NULL DEFAULT 0,
idem_key VARCHAR(64) NOT NULL,
UNIQUE KEY uk_order_idem (idem_key)
);
CREATE TABLE order_event (
event_id BIGINT PRIMARY KEY,
order_no VARCHAR(32) NOT NULL,
event_type VARCHAR(24) NOT NULL,
event_key VARCHAR(64) NOT NULL,
operator_id VARCHAR(32) NOT NULL,
created_at TIMESTAMP NOT NULL,
UNIQUE KEY uk_event (order_no, event_type, event_key)
);验收时每笔单记录四列:订单状态、金额变化、责任角色、凭证。正常单核对支付、接单、取餐、送达、结算;转单单核对原骑手任务结束、新骑手任务生成、用户进度、商家账单;退款单覆盖接单前取消、配送中取消、部分退款和结算后退款,核对退款记录关联原结算并冲回;重复操作和支付超时核对同一请求只形成一次有效处理。
校园订单与普通同城外卖的差异在末端履约。普通订单送到地址即可,校园订单常要经过校门核单、集中收餐、按楼栋分拣、校内接力和送达通知。系统地址结构要能预设学校、校区、楼栋、宿舍、楼层;订单要能按楼栋或宿舍分组,支持批量中转、批量送达、批量通知;多校区运营要有独立后台和分站数据范围。
环节 | 角色 | 系统动作 | 异常接续 | 留证 |
|---|---|---|---|---|
商家出餐 | 商家 | 接单、出餐确认、打印或通知 | 缺货、拒单转客服 | 出餐时间、商品明细 |
校外运输 | 校外骑手 | 取餐、到站登记 | 超时改派 | 取餐凭证、到站时间 |
校门核单 | 站点人员 | 扫码或录码收餐、核对批次 | 少餐错餐转异常单 | 交接人、批次、差异记录 |
楼栋分拣 | 分拣人员 | 按楼栋或宿舍分组、批量中转 | 错分回退原组 | 分组结果、操作人 |
校内接力/送达通知 | 校内骑手 | 接力送达、批量送达、批量通知 | 无人接收暂存或改约 | 送达凭证、通知记录 |
验收时用本校真实地址配置校门、楼栋和取餐点,再走一笔从商家出餐到宿舍楼下的订单;同时用校区账号访问其他校区数据,检查列表和导出是否被限制。校方通行规则、站点空间、现场人员分工和版本配置需要在演示中逐项核对。
首期落地先判断数据控制、技术团队、上线节奏和维护责任,再选择标准SaaS、私有化部署、源码安装或个性化开发。沟通时把软件模块、终端入口、部署环境、第三方服务、培训、售后和升级分项列清;报价按模块、终端、部署和服务拆分,历史成交价只对应某次项目配置,不能当作统一报价。校园项目要求用本校地址做场景演示。
演示清单可按“标准配置、组合配置、需定制、未演示”四类记录:正常单、转单单、退款单、重复操作、支付超时、越权访问。每项写清操作账号、预期状态、金额变化和留证方式。这样技术结果能回到经营判断:系统能否接住异常、财务能否还原金额、校区权限是否真正隔离。
不是。三端应共用订单、商品、用户和骑手数据,用角色入口和权限隔离;入口可以不同,订单主键和后端鉴权必须同源。
可以。入口形态不影响权限隔离,关键是同一订单数据和后端鉴权;门店打印、设备适配和账号权限按项目演示核对。
差异集中在校门交接、集中收餐、楼栋分拣、批量通知和多校区数据范围;用本校真实地址走一笔到宿舍楼下的订单即可核对。
正常单、转单单、退款单、重复操作或支付超时、越权访问。每项记录状态、金额、责任人和凭证,结果分为标准配置、组合配置、需定制或未演示。
准备启动时,先整理校区数量、商家来源、骑手组织、地址结构和结算规则,再带正常单、转单单、退款单各一笔做场景演示,把每项标记为标准配置、组合配置、需定制或未演示,形成需求清单和验收记录。
作者:微订(上海逊柯计算机科技有限公司)。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。