1. 为什么我要做一套「二手废品」二合一的小区回收系统先说结论小区场景下的二手闲置交易和废品回收看起来是两个需求实际上是一拨人、一个小区、一套信任体系下的同一件事。我是在连续跑了好几个真实小区场景之后才把这两条业务线硬塞进同一个小程序系统里的原因后面会详细讲。最早触发这个想法是某小区物业运营团队找过来说他们每天在业主群里被两类消息刷屏一类是「搬家出沙发便宜出自提」另一类是「有没有收纸壳的师傅电话家里堆了几箱纸壳」。群接龙、私聊、打电话信息散得到处都是物业想帮忙又无从下手。他们想要一个能同时在业主端解决「闲置转让」和「废品预约上门」的小程序系统让我帮忙规划。这个需求特别具体也特别真实。我先把这几件事拆开看二手闲置的本质是人与人之间的低频交易废品回收的本质是人对服务的按需预约。它们确实差别很大但在同一个小区里两者共用同一套业主身份、同一本楼栋地址簿、同一个履约半径。一个业主今天发布二手沙发明天预约废品上门背后其实是同一个「家里有东西要清走」的场景。所以一套系统同时承接这两条线从用户体验到运营效率上都是划算的。这套系统做成后业主、回收员、物业三方都能在小程序里找到自己的位置这也是整套系统最核心的价值点。这篇内容适合谁看两类人第一类是正在帮小区、社区、物业团队做数字化方案的产品经理和前端后端开发可以直接抄里面的模块划分和表结构第二类是自己想跑通「小区回收」这类项目、准备外包或者自己动手做的个人开发者。我会把从需求拆解、功能设计、数据库设计到上线运营踩过的坑全部展开尽量做到你看完能直接复现一套可运行的demo。2. 系统整体结构一个后台收拢两条业务线四个角色各管一段2.1 三端一后台但入口只有一个整套系统我没有做成「二手App 回收App 管理后台」三个独立产品而是把所有用户入口收敛到一个小程序里业主打开后能看到「卖闲置」和「约回收」两个功能块。后台则是给物业运营方和系统管理员用的网页端负责审核、排班、数据统计。这样做的原因很直接小区场景的用户没有下载App的意愿也不想记两个入口小程序里点一下就完事。小程序端内部再按角色区隔业主看到的是发布、预约、订单、钱包入口回收员登录后看到的是待接单、上门列表、结算记录物业人员则多一个数据看板。角色切换我放在了登录环节用手机号加短信验证码完成业主注册后会自动分配一个「普通业主」身份回收员需要额外提交身份资料由后台审核开通。2.2 四类角色的职责边界这套系统里一共有四类角色职责不能混否则后面权限和状态机都会乱。角色核心职责主要操作业主住户发布二手闲置、预约废品回收、确认结算发布商品、预约上门、支付、确认订单、评价回收员承接回收订单、上门称重、现场结算抢单/接单、称重录入、生成结算单、完成订单物业运营方审核内容、管理回收员、处理投诉商品审核、回收员审核、订单仲裁、数据查看系统管理员维护系统参数、处理异常配置计价规则、调整小区范围、退款处理这里有一个容易被忽略的点物业运营方其实是最关键的落地角色不是系统管理员。因为小区里有信任背书的是物业业主愿意把家里地址告诉一个上门回收员前提是这个人是物业审核过的。所以我把「回收员审核」「商品内容审核」这两个权限都给了物业后台管理员只保留系统级配置权限这样权责才清晰。2.3 二手交易和废品回收不能共用一张订单表一开始我图省事想把两条业务线的订单统一放到一张表里后来在设计阶段就否决了。原因是两者的订单生命周期完全不同二手交易是从「买家发起意向」到「线下交割确认」废品回收是从「预约上门」到「现场称重结算」。如果硬塞一张表状态枚举会变得很拧巴查询和统计也麻烦。最终我采用了「业务分离、用户统一」的表结构方案。用户表、地址表是公用的但商品、二手订单、回收预约单、结算单各建各的表。小程序首页把两条业务入口并列展示后端通过统一的订单查询接口返回不同列表前端根据订单类型渲染不同卡片。这样看起来是一套系统实际上有两套清晰的业务模型在跑后续维护和扩展都会轻松很多。3. 核心业务流程与状态机设计这条链路必须精确到每一步3.1 二手闲置从发布到交割的完整链路二手闲置这条线我设计成「平台撮合、线下交割」的模式平台不碰货、不碰钱只负责把信息匹配和信任机制做好。业主发布闲置时必须填写标题、描述、图片、价格、新旧程度还要选择「面交地点」默认是小区内的固定点位比如物业门口或社区活动室。发布后先进入「待审核」状态物业运营方在小程序后台确认图片清晰、信息真实后放行状态变为「在售」。这一步不能省因为没有内容审核的二手区很快就变成广告区。买家看到商品后可以直接点击「联系购买」此时会生成一条购买意向单卖家会收到订阅消息通知。双方协商后买家在订单里确认付款方式——这里我没有做线上支付而是线下见面交易因为小区里低频的二手交易线上支付反而增加纠纷成本。买家确认收到货后订单状态变成「已完成」双方可以互相评价。状态机是这样的草稿→待审核→在售→交易中→已完成任何一方在「交易中」之前都可以取消取消后商品回到「在售」或下架。这里最需要注意的一点是不要允许「交易中」状态下卖家把商品改价或下架不然买家体验会很差我就在实测中遇到过卖家临时改价引起投诉的情况。3.2 废品预约回收的上门流程与状态流转废品回收线的核心是一个「预约单结算单」的两段式结构。业主选择废品种类纸类、塑料、金属、家电、衣物等填期望上门时间提交后生成预约单状态为「待接单」。回收员端可以看到自己负责的小区范围内待接单列表抢单或由物业分配接单后状态变为「已接单」同时业主会收到上门时间提醒。回收员上门后先核对废品逐类称重在小程序里录入每类废品的重量系统按配置好的单价自动算出总金额生成结算单。关键是这里的金额不是最终收入而是「估算金额」业主可以在结算单上确认或提出异议。业主确认后回收员通过小程序转账给业主订单进入「已结算」状态最后双方互相评价。整个状态序列是待接单→已接单→上门中→已称重→已结算→已完成另外保留「已取消」「争议中」两个旁路状态。「争议中」非常重要因为废品定价容易扯皮。比如业主觉得纸壳不止5公斤回收员坚持是5公斤这时候订单会自动锁定物业介入看回收员上传的现场照片和称重照片来仲裁否则整个信任体系都会崩掉。3.3 废品计价规则不能定死也不能全凭感觉废品回收的价格波动其实很大不同城市、不同品质价格都不一样。如果写死在代码里回收员和业主都会觉得不合理。我采用的方式是「后台动态配置计价规则」把废品分成大类每一类配置基础单价区间回收员在实际称重时录入的是「实际单价」但要落在后台配置的合理范围内。举一个具体的例子纸类设的基础区间是0.6到1.4元/公斤塑料瓶是0.8到2.0元/公斤铜铝金属单独按高单价计算。回收员录入时超出区间系统会提示「价格异常需上传原因说明」这样既保留灵活性又防止乱定价。这种计价规则还有一个好处物业后台可以按周调整区间跟随市场行情走不用发版更新小程序。另外一定要在回收员端做「称重小票」功能每笔结算单生成后自动附带称重照片和废品照片业主在确认页能看到。我上线运营后发现凡是提供了称重照片的订单争议率会下降一大截这一条很值得注意。4. 数据库表设计与关键接口逻辑用到第六版才稳定下来4.1 核心表结构用户、地址、商品、二手订单、回收预约单这套系统的数据库设计我反复改了很多版最终稳定下来的核心表有这么几张。这里只列关键字段方便你复现时做参考。-- 用户表 CREATE TABLE tb_user ( user_id BIGINT PRIMARY KEY AUTO_INCREMENT, open_id VARCHAR(64) UNIQUE, phone VARCHAR(20), nickname VARCHAR(50), avatar_url VARCHAR(255), user_type TINYINT, -- 1业主 2回收员 3物业 status TINYINT, -- 1正常 2冻结 create_time DATETIME ); -- 小区楼栋地址表 CREATE TABLE tb_address ( address_id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT, community_name VARCHAR(100), building VARCHAR(20), room VARCHAR(20), contact_name VARCHAR(30), contact_phone VARCHAR(20), is_default TINYINT );二手商品表的关键字段是item_id、seller_id、category_id、title、description、price、original_price、condition_desc、status、view_count。二手订单表的关键字段是order_id、item_id、seller_id、buyer_id、status、trade_place、create_time、finish_time。回收预约单表的关键字段是recycle_order_id、user_id、worker_id、category_json、expected_time、address_id、status、create_time。另外还有一张回收结算单表 recycle_settlement关联预约单ID存有每类废品的重量、单价、金额以及现场照片URL。这里有一个设计心得废品类别我用一个category_json字段存储不单独建多张明细表。因为一次上门可能同时收纸壳和塑料瓶类别数量不固定JSON字段在查询时需要解析但配合后台统计用的独立明细表完全够用。你如果追求更强的一致性可以拆明细表但项目初期没必要。4.2 订单状态的几个并发问题与解决方案在真实小区场景里最常出现的并发问题是回收员同时抢多个预约单。预约单在「待接单」状态下两个回收员同时点击接单后端如果用普通更新语句就可能出现两个人都接单成功。我的处理办法很简单接单操作使用条件更新在SQL语句中加上状态限制。UPDATE tb_recycle_order SET worker_id #{workerId}, status 2 WHERE recycle_order_id #{orderId} AND status 1然后判断更新影响的行数如果为0说明被别人抢先了直接提示「手慢了订单已被接走」。这个方案不需要引入分布式锁足够对付普通小区项目。同样的问题还出现在二手商品购买意向确认上解决办法也是条件更新。这类「乐观锁」思路在小程序后端开发里非常实用我建议你遇到状态流转都先想想能不能用条件更新解决。4.3 附近订单匹配与小区边界处理废品回收的接单不能是全城订单必须限定在回收员负责的小区范围内。我在回收员表里加了一个community_ids字段存的是这个回收员可以服务的所有小区ID列表。业主提交预约单时带上小区标识回收员端查询时直接筛选community_ids包含该小区ID的待接单列表不做地理位置匹配。为什么不搞LBS定位匹配因为测试阶段我发现在小区里用定位判断「谁离得近」根本不靠谱一栋楼和一个门的距离误差就能让指派逻辑出问题还经常定位到隔壁小区的快递站。小区回收是确定性场景直接按「服务小区」绑定比按经纬度匹配可靠得多。这套系统的核心不是算法而是业务的准确流转。5. 小程序端开发中踩过的具体坑每一个都是线上真实反馈5.1 定位权限与模拟定位导致的订单错派废品回收的预约单里有一个「选择小区」的下拉框数据来自业主注册时填写的社区信息不依赖实时定位。但我最初低估了地图选点功能的吸引力想着用户选一栋楼更精准结果接入了地图选点后各种问题冒出来了用户拒绝授权定位时选不了坐标模拟定位环境下选到了距离实际楼栋几百米的地方订单的address_id和对不上。后来我把地图选点砍掉了统一改成「手动选择小区楼栋房间号」的三级结构。反正预约回收和二手交易都需要业主填准确的门牌号与其让定位猜不如让用户直接确认。在实测中业主对这种填写方式的接受度比想象中高因为他们本来就需要留下联系方式。5.2 订阅消息一次性授权的困扰废品回收最需要消息通知的场景是回收员接单后通知业主。小程序平台的一次性订阅消息授权机制在这里很麻烦每次订阅只能推送一条通知而且用户弹窗授权时选择「总是保持以上选择」的比例并不高。我的对策是「集中订阅、按需触发」业主提交预约单时一次性申请多个订阅项包括接单通知、上门提醒、结算结果每一步使用时检查授权状态如果没有授权在订单详情页弹一个引导按钮让用户重新授权。这里要特别注意不能只在第一个页面把所有订阅权限都要完用户会反感要给一个可理解的理由比如「接下来您会收到上门与结算提醒」。5.3 支付与退款的账务处理细节废品回收结算这个环节涉及到真实资金流转。我最初设计的是回收员线下扫码转账给业主小程序只记录结果。但实测中发现一个问题回收员转账后忘记在系统里点「确认已转账」订单一直卡在「已称重」状态业主看不到结算结果就会投诉。后来我改成「回收员确认转账生成结算单」的强制流程并且加了转账凭证图片上传。回收员转账完成后必须拍照上传转账记录系统才允许把订单状态推进到「已结算」。这也让我意识到在小区回收这种强线下场景里线上的每一步状态推进都必须绑定一个有据可查的动作否则系统记录和现实情况就会脱节。6. 上线后的运营经验系统做出来只是开始运营规则才是分水岭系统开发完成后我在两个模拟小区里跑了两轮灰度一套配置在真实小区楼栋环境下另一套放在大型社区服务中心。第一轮之后优化了三个运营层面的东西这些虽然不在需求文档里但恰恰决定了系统能不能活下来。第一是要建立回收员的「履约评分」机制。每次拿单后爽约、称重争议多的回收员评分会降评分低的回收员会减少派单优先级。这套机制上线后回收员的履约率明显提升因为接单不再无成本大家会掂量一下自己的服务能力。第二是二手商品的发布审核必须有人值班。一开始审核放在上午统一处理结果业主晚上发布的信息第二天上午才上架热度全过了。改成「高峰时段即时审核、其他时段两小时一过」之后二手区的活跃度明显上升。运营上说审核频次其实就是内容社区的生命线。第三是废品预约的「一键续约」功能。很多业主预约一次回收后后续隔一两周又会继续预约我在订单完成页加了一个「再次预约」按钮默认复用上次的废品类别和地址实测复约率能到三成以上。这个功能虽然改动很小却是整个系统里投产比最高的一个迭代。最后再分享一个我个人的体会做这类社区型系统难点其实不在代码而在业务规则的取舍。你需要在「灵活」和「可控」之间反复试探比如计价规则不能定死但又要限制回收员乱开价二手交易不能管太死但审核又不能放太松。每一条规则都是一次真实的用户反馈堆出来的没有捷径。如果有朋友准备做类似的小区回收项目我的建议是先拿一个真实小区做纸面推演把角色职责、订单状态、定价规则拆清楚再动代码那样开发周期会短很多返工也少。