ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

基于微信小程序的同城跑腿接单助手:Python后端与订单状态机设计实践

基于微信小程序的同城跑腿接单助手:Python后端与订单状态机设计实践 前阵子朋友甩给我一个同城跑腿项目的需求用户在小程序里下单附近的骑手抢单然后按时把东西从 A 点送到 B 点。这活儿听起来像美团跑腿的小型复刻也确实是我身边不少外包团队和本地生活项目常接的单子。但真正做起来之后我发现这类系统最磨人的不是页面设计也不是接口数量而是订单从创建到送达这条状态链路怎么走得稳。标题里的 Python 和微信小程序恰好是这条链路的左右手小程序负责接触用户和骑手Python 负责处理业务规则、距离计算和并发抢单。这篇文章就围绕基于微信小程序的同城跑腿服务接单助手这个项目把技术选型、表结构设计、核心接口逻辑、联调埋点一次性写透给同样想用 Python 做同城服务项目的同学做参考。先提醒一句市面上很多同城跑腿小程序源码交付件本质上只是前端壳子。小程序不能像普通网页那样打开就能看它需要开发者工具、AppID、后端接口三个条件同时具备才能完整跑通业务。想真正落地一个能接单、能派单、能结算的系统后端业务逻辑必须自己补齐这篇文章的重点也就在这里。1. 跑腿接单这件事真正要解决的是订单流转问题1.1 原始接单方式的混乱恰好是系统化的机会很多三四线城市的跑腿团队至今还是靠微信群接单用户把发件地址、收件地址、物品照片往群里一甩然后 某个骑手。看起来没什么门槛但跑起来全是问题订单消息被聊天记录冲掉十分钟后再找一条单子要往上翻半天。骑手有没有接单全凭口头回复用户根本不知道谁在给自己送。配送过程不透明用户半小时后问一句到哪了骑手还得停下手头的事情打字回复。结算更是靠截图对账稍一忙就漏单。接单助手这个项目解决的不是让用户能下单这么简单它真正解决的是订单如何高效流转创建订单、候选骑手、接单锁定、开始配送、确认送达每一个环节都有明确状态和操作人。用户看到结果骑手看到任务后台看到全量数据这就是系统化相对口口相传的核心优势。1.2 接单助手的三种角色视角做这类系统前先把角色梳理清楚。同城跑腿业务主要有三类使用对象下单用户在小程序里发起跑腿请求填写取送地址支付费用跟踪配送进度最后确认收货。跑腿骑手在小程序里查看附近待接订单抢单按地址完成取送更新配送状态。平台管理员可选审核骑手资质、处理客诉、查看订单流水、做结算统计。很多教程项目只做用户端但接单助手这个名字本身就说明骑手侧的接单体验才是核心。一个骑手每天可能要抢几十张单列表加载快不快、抢单反馈清不清晰、状态切换顺不顺直接决定他愿不愿意用。所以文章后面会花大篇幅讲抢单接口和并发控制这是接单助手的命门。2. 技术选型为什么是 Python 后端加微信小程序前端2.1 后端用 Python图的是开发效率和生态同城跑腿这类项目单量峰值可能也就几百上千业务复杂度不算高真正需要技术深度的点也就那么两处距离计算和并发抢单。Python 在这两个场景下的手感非常合适。框架选型我推荐 FastAPI 或者 Flask。FastAPI 自带异步支持和接口文档调试起来省不少事Flask 更轻适合想快速跑通的团队。本项目按 FastAPI 写核心逻辑但思路在 Flask 上同样成立。距离计算直接用 geopy 库算两点间的球面距离或者自己写一个哈弗辛公式Haversine Formula二三十行代码搞定不需要引入重量级 GIS 组件。并发控制抢单场景需要同一时刻只有一个骑手能抢成功的保证这个用 Redis 的原子操作或者数据库的条件更新都能做Python 生态里 redis-py 已经封装得很顺手。快速迭代同城业务的需求变更非常频繁比如新增帮送文件代买奶茶这种子类型Python 的动态特性让后端改动成本很低。对比一下其他方案Java 技术栈写起来稳但项目初期重Node.js 做这类业务也完全可以但如果你团队里 Python 是主力没必要为了前后端同语言去额外引入一套生态。小步快跑的项目选团队最熟的技术就是最好的技术。2.2 小程序端为什么比 App 和网页更合适这个项目核心场景是低门槛发起请求和骑手在外移动时快速操作微信小程序在这两点上有先天优势不需要下载安装用户和骑手都是一次性低频使用的角色让他们为跑腿业务专门装个 App 太难了。小程序扫码即用用完即走。微信生态能力齐全登录可以用 wx.login 静默授权地址选择有 wx.chooseLocation定位有 wx.getLocation进度通知有订阅消息这些都是直接可用的官方能力不用自己从零造轮子。打开率高骑手端的小程序可以被置顶聊天窗口接单通知来了直接从小程序切进去体验比网页 H5 好一个档次。还有一点标题和很多热搜词都提到小程序源码工程和网页之间的差异小程序前端代码不能直接在浏览器里跑它必须通过微信开发者工具编译预览发布后也要走微信审核。这和传统网页开发的调试思路完全不同我第一次接触时也踩了坑后面联调章节专门说。2.3 原生开发还是 uniapp如果这个项目只做微信小程序我建议原生开发也就是 WXML WXSS JS 那套。原因很简单原生能和微信 API 保持零延迟同步新功能出来马上能用不用等跨端框架适配。而且外卖跑腿这种项目对地图组件、手机号授权这类原生能力依赖很重绕开框架层能少踩很多坑。但如果你未来确定要上支付宝小程序、抖音小程序那就选 uniapp一套代码多端发布。需要注意的是 uniapp 打包微信小程序时容易触碰主包体积 2MB 的限制热搜词里就有关于 source size 超限的提问。解决办法是分包加载把骑手端和用户端的页面拆成不同分包首屏只加载用户端内容。这个坑后期很容易遇到提前规划页面结构能省不少事。3. 先把数据库表结构和状态机设计好再动接口3.1 核心表结构写业务代码前我习惯先设计表。跑腿接单助手至少要建三张核心表用户表、订单表、接单日志表。下面是我在项目中实际按这个思路落地的结构字段可以根据业务再调整。用户表 user字段类型说明idint主键openidvarchar(64)微信用户唯一标识nicknamevarchar(64)用户昵称avatar_urlvarchar(256)头像地址phonevarchar(32)手机号roletinyint角色0普通用户1跑腿骑手statustinyint状态1正常0禁用created_atdatetime注册时间订单表 order字段类型说明idint主键order_novarchar(32)订单编号业务展示用user_idint下单用户rider_idint接单骑手未接单前为空pickup_lngdecimal(10,7)取件经度pickup_latdecimal(10,7)取件纬度pickup_addressvarchar(256)取件文字地址receive_lngdecimal(10,7)送件经度receive_latdecimal(10,7)送件纬度receive_addressvarchar(256)送件文字地址item_descvarchar(256)物品描述item_typetinyint物品类型文件、餐饮、生鲜、其他weight_kgdecimal(4,2)重量关系到计价distance_kmdecimal(5,2)取送距离创建时计算并存储estimated_feedecimal(8,2)预估费用actual_feedecimal(8,2)实际费用完成时结算statustinyint订单状态见下方状态机created_atdatetime下单时间grabbed_atdatetime抢单时间delivered_atdatetime送达时间接单日志表 order_grab_log记录每个骑手的抢单行为用于防止恶意刷单和事后追溯。字段包括 id、order_id、rider_id、action、created_at。这张表不是业务必须但建议加上排查并发问题的时候非常好用。关键点我在设计时就反复确认过经纬度用 decimal 存不要用 float精度差异会在距离计算时被放大。订单号单独一列展示用不用主键编号直接对外。因为主键自增容易被别人猜到平台订单量。status 用 tinyint 存整数状态比字符串存状态值更省空间、查询更快维护成本也不高。3.2 订单状态机先定义清楚再写 if接单助手最容易出 bug 的地方就是对订单状态做了不受控的修改。比如骑手接单后订单又显示待接单用户取消后骑手还能点开始配送。要防止这类问题最佳实践是在写接口前把状态机画出来明确每一个状态允许迁移到什么状态。我的订单状态定义如下0已取消。下单后用户主动取消或者超时无人接单系统自动取消。1待接单。订单创建成功后进入骑手可抢。2已接单。骑手抢单成功后进入此时骑手信息已绑定到订单。3配送中。骑手已取到物品正在送往目的地。4已完成。骑手确认送达用户确认收货后可进入评价流程。允许的状态迁移路线只有这些1 - 0用户取消或系统超时取消1 - 2骑手抢单成功2 - 3骑手开始配送2 - 0骑手接单后想放弃申请取消平台审核后取消这个流程要慎用我项目里默认不允许避免恶意占单3 - 4骑手确认送达4终态不可再迁移每个接口在做状态更新时都必须校验当前状态是否允许迁移到目标状态而不是无脑 update。比如抢单接口只能用待接单状态的订单配送完成接口只能更新配送中的订单。这套规则写进代码之后并发和误操作带来的脏数据会少很多。3.3 为什么要存经纬度而不仅仅存文字地址同城跑腿业务里距离是最核心的计算因子。骑手要看这单离我多远决定抢不抢平台要用距离算预估费用商家要按照配送范围决定能不能接。文字地址没法做数学运算只有经纬度能。所以下单接口必然要求用户通过地图选点。小程序端可以用 wx.chooseLocation 让用户在地图上选位置把经纬度回传后端拿到两个坐标点用哈弗辛公式算球面距离再叠加城市道路系数得到估算距离。这个距离在创建订单时就算好并存储后续列表排序、费用展示都直接用存储值避免同一张单在每次请求时重复计算也避免骑手端和用户端展示出的距离不一致。经纬度还有一个好处骑手视角可以做附近订单的筛选。SQL 里用经纬度范围粗筛比如用户的坐标在矩形范围内再加距离排序性能比全表扫描好很多。4. 小程序端关键页面下单、抢单、配送状态操作4.1 登录与角色识别的实现路径小程序端的登录依赖微信的能力。流程是小程序调用 wx.login 获取临时 code把这个 code 传给 Python 后端后端调用微信接口 code2Session 换取 openid再自己生成业务 token 返回给小程序。小程序把 token 存在本地存储后续请求带上即可。这里有个细节同一套小程序如何区分用户和骑手两种做法角色选择页。首次登录让用户选择我是下单用户还是我是跑腿骑手提交时打上角色标签。后台审核制。用户申请成为骑手时提交手机号和资质信息管理员在后台审核通过后给 user 表的 role 字段置为 1。我建议用第二种更安全也更接近真实业务。骑手不是谁想当就能当的平台要确认这个人不会拿了东西就跑。小程序端根据 role 字段决定渲染哪一套页面普通用户看到下单和我的订单骑手看到接单大厅和配送任务。4.2 下单页地图选点与费用预估下单页是整个用户端最核心的界面涉及的交互比较多。我的页面组成包括取件地址选择、收件地址选择、物品类型和重量填写、备注输入、费用预估展示、提交按钮。取件和收件地址都调用 wx.chooseLocation这一步打完点之后把经纬度和地址名称一起回填到表单。如果用户拒绝授权定位就让他手动输入文字地址并在地图上确认总之经纬度必须拿到否则后端没法算距离。费用预估可以在前端简陋算一下比如起步价 distance_km * 每公里单价给用户一个大致的价格参考。但真正计费一定以后端为准前端数字只是友好提示防止用户下单后被实际费用吓一跳。提交订单后页面跳转到订单详情。订单详情页展示状态流转步骤条、地图上的路线缩略、物品信息、跑腿员信息和联系按钮。4.3 骑手端接单大厅列表刷新与抢单反馈骑手端打开接单大厅核心诉求是尽快看到周边有哪些待接订单。这里涉及一个常见问题列表数据怎么刷新方案A下拉刷新。简单可靠用户手动触发。方案B定时轮询。每 5 到 10 秒调一次列表接口自动更新。性能上可以接受毕竟同城订单量不大但要处理好清理定时器的问题否则页面退到后台还在请求浪费流量。方案CWebSocket 推送。体验最好但实现复杂度高需要额外的推送服务和长连接管理小项目不太必要。我实际做的时候用的是 B A 的组合页面 onShow 时拉一次列表同时开启定时轮询页面 onHide 时清除定时器。这样既保证实时性又不至于长期空跑。列表里每张卡片要展示的信息取件地址到收件地址的距离、预估费用、下单时间、物品描述。骑手点击卡片进入订单详情看到更完整的路线和物品信息确认没问题后点抢单按钮。抢单按钮的点击反馈非常关键。如果抢单成功要明确提示抢单成功请及时联系取件人如果订单已经被别人抢走要弹手慢了订单已被接走。用户最害怕的是点击抢单后页面没反应在原地傻等所以这个地方的交互提示宁可多写几个分支。4.4 配送状态操作与地图导航骑手抢单成功后订单进入骑手的配送任务列表。状态操作按钮随状态切换已接单状态显示开始配送点击后把订单推到配送中。配送中状态显示确认送达点击后走完成接口。完成之后显示订单已完成不可再操作。用户端在订单详情里可以看到配送进度待接单、已接单、配送中、已完成这四个节点的步骤条。骑手点了哪个环节用户端进度条同步更新。关于地图导航一个实用小技巧不要让小程序内嵌地图做大而全的导航功能直接调用 wx.openLocation 把目的地经纬度传进去系统会自动唤起微信内置的地图能力支持路线规划和导航。这样开发成本低体验还稳定。取件地址和收件地址分别提供去这里按钮骑手一键切换导航非常实用。5. Python 后端核心接口与并发抢单设计5.1 接口清单总览后端接口不需要多但要职责清晰。我按业务功能划分如下功能模块接口路径方法说明登录/api/auth/loginPOST接收 code返回 token 和角色下单/api/order/createPOST创建跑腿订单计算距离和费用订单列表/api/order/listGET按角色返回对应订单列表订单详情/api/order/detailGET返回订单完整信息抢单/api/order/grabPOST骑手抢单核心并发逻辑订单状态更新/api/order/update_statusPOST状态机流转入口取消订单/api/order/cancelPOST用户取消仅待接单状态可操作接口设计上抢单和状态更新拆开是刻意的。抢单操作必须原子化状态更新走统一的状态机校验逻辑两者职责分离后后续要加派单算法、超时自动取消之类的功能也更好扩展。5.2 用条件更新解决抢单并发不死锁、不超卖抢单场景本质上是典型的并发竞争两个骑手同时看到同一张单点击抢单后必须保证只有一个能成功。最容易想到的方案是先 SELECT 查一下订单状态如果是待接单再 UPDATE 更新骑手信息。这个方案在并发下必出问题——两个请求同时 SELECT 都查到待接单然后都走 UPDATE后更新的会覆盖先更新的。正确做法是用数据库条件更新在一个原子操作里完成状态校验和状态变更。SQL 逻辑如下UPDATE order SET rider_id %s, status 2, grabbed_at NOW() WHERE id %s AND status 1 AND rider_id IS NULL执行后检查更新影响的行数。如果影响行数为 1说明抢单成功如果影响行数为 0说明订单状态已经不是待接单抢单失败。这个方案简单到不需要引入分布式锁性能也够用我强烈建议优先采用。对应到 Python 代码FastAPI 风格的核心逻辑是app.post(/api/order/grab) async def grab_order(order_id: int, rider_id: int): # 执行条件更新 now datetime.now() result db.execute( text( UPDATE order SET rider_id :rider_id, status 2, grabbed_at :now WHERE id :order_id AND status 1 AND rider_id IS NULL ), {rider_id: rider_id, order_id: order_id, now: now} ) db.commit() # 影响行数为 1 说明抢到了 if result.rowcount 1: return {code: 0, msg: 抢单成功, rider_id: rider_id} else: return {code: 10001, msg: 手慢了订单已被接走}如果项目已经用了 Redis 作为缓存层也可以在 UPDATE 之前用 Lua 脚本加一个锁但数据库条件更新已经足够解决单库场景下的全部问题而且没有分布式锁的过期时间、误删锁等额外复杂度。5.3 距离计算哈弗辛公式的实现创建订单时后端拿到取送两个点的经纬度用哈弗辛公式计算球面距离。公式核心思路是把经纬度转成弧度计算球面上两点间的大圆距离。代码如下import math def haversine(lng1, lat1, lng2, lat2): # 经纬度转弧度 lng1, lat1, lng2, lat2 map(math.radians, [lng1, lat1, lng2, lat2]) # 差值 dlng lng2 - lng1 dlat lat2 - lat1 # 哈弗辛公式 a math.sin(dlat / 2) ** 2 \ math.cos(lat1) * math.cos(lat2) * math.sin(dlng / 2) ** 2 c 2 * math.asin(math.sqrt(a)) # 地球平均半径 6371 公里 distance_km 6371 * c return round(distance_km, 2)这个算出来的是直线距离。真实同城跑腿场景里骑手走的路肯定比直线长通常会给一个 1.2 到 1.5 的路径系数修正再叠加基础起步价和重量费用就是预估费用。要把系数留在配置里不要写死在接口内运营想调加价策略时后端改配置就行不用动代码。5.4 状态更新接口的统一校验状态更新接口不能做成前端传什么状态我就改成什么必须走状态机校验。我在实现时维护了一个允许的状态迁移映射表# 允许的状态迁移 STATUS_TRANSITIONS { 1: [0, 2], # 待接单 - 已取消 / 已接单 2: [3], # 已接单 - 配送中 3: [4], # 配送中 - 已完成 } app.post(/api/order/update_status) async def update_order_status(order_id: int, from_status: int, to_status: int): # 校验迁移合法性 if to_status not in STATUS_TRANSITIONS.get(from_status, []): return {code: 10002, msg: 非法的状态流转} # 条件更新防止并发下状态被重复推进 if to_status 4: sql UPDATE order SET status 4, delivered_at NOW() WHERE id :id AND status 3 else: sql UPDATE order SET status :status WHERE id :id AND status :from_status result db.execute(text(sql), {...}) db.commit() return {code: 0, msg: 状态更新成功}这里有一个看似多余但很重要的细节状态更新也要用 where 条件带旧状态去更新。比如骑手点了两次确认送达第一次已经把状态改成已完成第二次再更新时因为 where status 3 不成立影响行数为 0前端可以根据返回值提示订单已完成不要重复操作。既杜绝了重复提交又防止了脏数据。6. 前后端联调时绕不开的几个坑6.1 开发者工具能跑真机一测就废小程序开发里最典型的问题在微信开发者工具里一切正常真机打开就白屏或者接口全部超时。原因基本出在域名校验和 HTTPS 上。开发环境下开发者工具可以勾选不校验合法域名、TLS 版本以及 HTTPS 证书这样 localhost 或者局域网 IP 都能直接访问后端。但手机真机预览时微信强制要求请求地址必须是配置在后台的合法域名而且必须是 HTTPS。解决办法正式环境把后端 API 部署到一台有域名的服务器上配好 HTTPS 证书然后在微信公众平台的小程序后台配置 request 合法域名。联调阶段可以先申请一个测试域名配 HTTPS 后再把后端代理过去或者用本地调试隧道工具把本地端口映射到公网临时地址。需要注意如果本地开发用 HTTP还是要先保证调试工具的域名校验关闭隧道映射出来的地址通常也要求 HTTPS 才能在小程序里跑通。这个坑几乎每个小程序项目都会遇到建议项目一开始就把域名和证书准备好别等到真机测试时再手忙脚乱。6.2 手机号获取个人主体小程序没法直接用热词里有很多人在搜微信小程序登录获取手机号这里单独说明一下wx.getPhoneNumber 能力和小程序主体的认证状态强相关个人开发者注册的小程序默认拿不到用户手机号需要企业主体并且在小程序后台开通相应的接口权限。即便开通了2023 年之后微信也调整了授权逻辑不再支持 wx.getUserInfo 直接弹窗授权昵称头像。实际项目里我是这样做的注册登录阶段不强制拿真实手机号用户用微信登录后先分配临时身份等需要骑手入驻时再要求骑手填写手机号用于审核联系。用户端下单不需要手机号场景硬绑定收货电话放在订单备注里由用户填写即可。这样既绕开了微信的能力限制又符合业务需要。6.3 模拟器定位不准导致测试数据混乱小程序开发者工具里的定位默认是模拟的很多教程环境会固定返回一个地点经常是深圳或者北京某处这和真机定位完全是两码事。我第一次测试时用开发者工具下了好几张单全部集中在模拟点附近距离算出来都是 0 点几公里我还以为接口算错了。排查了很久才反应过来是模拟器定位的问题。真机上 wx.getLocation 返回的是当前设备定位和模拟器结果差异很大。建议测试联调阶段尽量用真机特别是涉及距离排序、费用计算的场景模拟器数据不能作为判断依据。另外wx.getLocation 需要在 app.json 里声明 permission 描述否则部分用户授权时会提示信息不完整。6.4 时间格式和距离单位的约定前后端联调最容易出各说各话的隐藏 bug。比如后端返回的 datetime 字段在 JSON 序列化后会变成 2024-06-01T12:00:00 这种字符串小程序端直接用 Date 处理倒还好但如果有的接口返回时间戳、有的返回字符串前端就得写兼容逻辑。我后来统一约定所有接口时间字段一律传秒级时间戳前端需要展示再自行格式化。距离单位更要注意。接口里 distance_km 用的是数字前端列表里要显示1.2km有的页面想按米精度显示1200m。如果没有约定好就会出现列表显示 1.2km详情页却显示 0.0012km 的尴尬。我的做法是接口一律返回公里数保留两位小数前端展示时判断小于 1 公里就显示约 850 米大于 1 公里显示1.2 公里。展示逻辑统一收敛在一个前端工具函数里不要散落在各页面。6.5 订阅消息不适合做全流程实时通知小程序端有一个天然的短板后台状态下没法长期保持 WebSocket所以骑手抢单成功后实时通知用户不能靠长连接推送实现。微信提供的方案是订阅消息但要注意它有个限制一次订阅授权只能推送一次消息。用户下单时要提示允许发送订单进度提醒他点一次授权平台才能在订单状态变化时推一条通知。想让用户在整个流程中收到多次通知就得设计多次授权引导比如下单页的订阅授权弹窗让用户多点几下。实际做下来最稳的通知方案是骑手接单后小程序端用订阅消息发一次骑手已接单配送中状态就靠用户自己在订单详情页刷新查看。非要全程实时的话建议引入厂商的小程序推送服务或者自建 WebSocket 网关但这属于大工程小项目没必要。6.6 抢单后立刻查订单可能查不到还有一个我自己踩过的小坑骑手抢单成功后前端立刻跳转到订单详情页结果页面调用详情接口时提示订单不存在。原因是抢单接口提交的订单 ID 是字符串前端在小程序 JS 里用的是 Number 类型比较ID 后面多了个 .0或者后端返回给前端的类型是 string 导致比较出错。这类问题特别隐蔽建议所有跨端接口统一把 ID 字段类型约定为 number 或者统一为 string避免 123 和 123 在比较时出现隐式转换问题。前后端联调前先约定接口协议字段名、类型、单位都列出来能省很多排查时间。7. 部署上线与后续扩展思路7.1 服务器部署的起步配置跑腿接单助手这种地方性业务初期用一台 2 核 4G 的云服务器完全够了。部署架构可以很简单后端Python 3.10 以上pip 装依赖用 uvicorn 拉起 FastAPI 服务。进程守护用 systemd 配一个服务保证进程挂了能自动拉起或者直接用 gunicorn 配多 worker。反向代理Nginx 做 HTTPS 终结把 API 路径代理到 uvicorn 监听的本地端口。数据库MySQL 或者 PostgreSQL初期单机实例足够。缓存可选如果上线后骑手量涨起来了可以加 Redis 存 token 和每次拉取列表的临时缓存减少数据库压力但这一阶段不是必须。上线前千万别忘了一件事把小程序后台上传的代码提交审核。审核期间后端域名必须是公网 HTTPS 可访问的否则审核员打开小程序时接口报错会被打回。第一次审核建议选择本地生活或者跑腿配送相关类目提前准备好相应的服务类目资质材料。7.2 从能接单到好用可以往这几个方向扩展项目跑通基础闭环之后真正投入运营前一般还要补几块拼图自动派单而不是全靠抢单系统可以根据骑手当前位置、在途订单数、评分自动把订单推给最合适的骑手设定 30 秒响应超时后再释放给所有人抢。钱包与结算跑腿业务的履约保证金、订单分成、骑手提现建议直接对接微信支付的分账能力订单完成后自动把跑腿费和平台佣金分账到各自账户。骑手入驻审核从简单的角色标记升级为骑手提交身份证、健康证、电动车照片管理员后端逐条审核。多城市支持订单表加大区字段接单大厅按城市隔离避免跨城骑手接到不合理的远单。评价体系订单完成后双向评价骑手评分影响后续派单权重。7.3 代码分层的小建议项目如果只有几个接口文件怎么都行但一旦加了骑手入驻、结算、客服这些功能代码就开始乱了。我的习惯是后端按模块分层路由层只做参数接收和响应封装业务层写状态机、距离计算、并发控制这些逻辑数据访问层单独抽出来避免在路由函数里直接拼 SQL。这样的结构在项目后期维护时省心很多。小程序端的代码也一样公共请求封装、登录态检查、角色判断这些抽成公共模块页面里只写页面逻辑。这个项目做完之后我最大的体会是跑腿系统的难点基本不在能下单、能接单这个主流程而在各种边界状态的处理。比如用户下单后十分钟没人接要不要提醒骑手接单后原地不动平台要不要干预用户顺路把单取消了骑手已经在取货路上损失怎么算。这些小问题在设计状态机的时候如果没想清楚写代码时就会不停打补丁。所以我给准备做同城跑腿项目的朋友一个最真诚的建议别着急写代码先花上半天时间把订单从创建到完成、从取消到异常处理的所有状态流转图一张一张画出来把每个节点的操作人和条件都写清楚。状态机定稿了剩下的接口实现就是照着图填代码效率反而最高。
返回列表