☰
社区二手回收小程序源码v6.15.2深度解析:架构、估价与二次开发
2026/10/14 1:11:08 网站建设 项目流程

简介:这是面向微信小程序开发者的社区二手交易平台完整源码包,涵盖前端与后端,可快速搭建二手物品回收与交易系统。项目基于 v6.15.2 迭代,重点修复了个人中心跳转、意见反馈入口、主题背景联动、流量主广告展示等问题,并优化了详情页举报按钮位置及图片视频播放尺寸,利于提升用户操作体验。资源共 1942 个文件,以 PHP、JS、JSON、HTML、WXML、WXSS 等前后端代码为主,配以 PNG、GIF 等界面素材,压缩包约 13.59MB,代码结构清晰、目录组织完整。已有 833 人学习下载,适合想研究小程序电商逻辑、后台接口设计或进行二次开发的 IT 从业者,可从中获得完整项目架构、调试思路和实用优化经验。

1. 社区二手回收小程序:我为什么只盯着这套 v6.15.2 源码看

小区里每天都有旧纸箱、旧家电、旧衣物被扔进垃圾桶,想把这些“放错位置的资源”收起来,靠人喊不行,得有个小程序。社区二手回收小程序源码 v6.15.2 前端+后端这套东西,真正值钱的地方不在于页面有多好看,而在于它把“预约—估价—上门/自提—称重—结算—回收员分成”这条业务闭环完整落地了。前端是微信小程序,后端是常见 PHP 框架,两者能单独部署也能拆开改。想快速开展社区回收业务的创业者、接外包的开发者、拿来做课题的在校生,都能从这套源码里找到自己需要的东西。版本号 v6.15.2 不是随便标的,它代表着这套代码已经经历过若干次迭代,表结构和接口相对稳定,比那些只有 demo 级别的开源项目靠谱得多。接下来的内容,我会按“骨架、跑通、改流程、避坑”这个顺序拆,帮你判断这套东西能不能用、怎么做、坑在哪。

2. 社区二手回收小程序源码 v6.15.2 的前后端骨架拆解

2.1 先理解社区回收的业务闭环:四个角色和一条状态机

社区二手回收不是简单的商城下单。它有四个主要参与方:用户(卖废品的人)、回收员(上门收货或门店收货)、运营者(配置价格、处理结算)、后台管理员(审核订单和看数据)。一套能落地的源码,必须把这四个角色的权限、数据流和利益分配在数据库里体现出来。

我拿到这套 v6.15.2 源码之后,第一件事不是去看代码,而是通过后台菜单和前端的页面跳转反推它的业务流程。比较典型的回收订单状态是:用户提交回收预约 -> 回收员接单 -> 上门/用户到店 -> 称重/估价 -> 确认结算 -> 完成。中间还穿插“取消”“拒绝”“超时未处理”这些分支。状态机的核心表通常叫recycle_order,其中status字段的取值范围直接决定了整个系统能不能闭环。

在二次开发前,先把状态机理清,否则后面加任何功能都可能出现订单状态错乱。建议把这张表拉出来,逐条状态流转写清楚。下面是一个从源码里整理出来的常见状态定义,你可以对照自己的包来核对:

status含义可流向的状态
0待接单1, 5, 6
1已接单,待上门2, 5, 6
2已上门/到店,待确认3, 4, 5
3已称重,待结算4, 6
4已完成无
5已取消无
6已拒绝/超时关闭无

一条回收单能不能走到结算,跟“称重”这个动作强绑定。所以后端接口里必须有独立的称重记录表,记录每一次称重的重量、照片、操作人和操作时间。这套源码里我见过有两种实现:一种是在订单主表里直接存weight和total_price,简单但不好追溯;另一种是单独建order_weight_log表,每次修改重量都留一条记录,推荐用后者,审计和客户纠纷时都更好处理。

社区回收业务还有一个特点:回收员不是平台员工,而是按单结算的“合作方”。所以系统里要有一张结算表,记录每一笔订单回收员的分成比例和实收金额。有的源码把分成比例写死在订单表里,一旦平台跑起来调价,历史订单的分成也会跟着变,运营容易算错账。比较稳妥的做法是订单快照:在订单创建时把当时的“回收单价、回收员分成比例”存进订单冗余字段,后续再调整配置也不影响历史单。

2.2 前端小程序的目录结构:页面层级和请求封装

前端采用微信小程序原生语法或者 uni-app 封装,不同的源码包目录会不一样,但核心页面一定包含这几个:首页(回收品类展示与快速下单)、预约表单页、订单列表页、订单详情页、回收员端工作台、个人中心。v6.15.2 的前端我拿到的版本是把用户端和回收员端放在同一个小程序里,通过角色切换来区分显示。

这样做的好处是部署简单,一个 appid 就能搞定;坏处是权限判断容易写成“页面内判断”,导致前端代码里满屏if(userType=='recycler')。如果你准备长期迭代,建议在一开始就把底部 tabBar 做成两套,或者干脆拆成独立小程序。但这套源码默认合成一套,新同学先不要改动这个大结构,把业务跑通最重要。

前端与后端通信的统一入口是一个utils/request.js工具文件,里面封装了baseURL、token注入、错误码统一处理。你在本地联调时,最常改的就是这个文件里的baseURL,把默认的线上地址改成本机局域网 IP。下面是一个常见的请求封装核心代码:

// utils/request.js const BASE_URL = 'http://192.168.1.100:8080/api'; // 本机调试时改成你的后端地址 function request(path, method = 'GET', data = {}, header = {}) { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + path, method: method, data: data, header: { 'Content-Type': 'application/json', 'Authorization': wx.getStorageSync('token') || '', // token 注入 ...header }, success(res) { if (res.data.code === 0) { resolve(res.data.data); } else { wx.showToast({ title: res.data.msg || '请求失败', icon: 'none' }); reject(res.data); } }, fail(err) { wx.showToast({ title: '网络异常', icon: 'none' }); reject(err); } }); }); } module.exports = { request, BASE_URL };

这里的逻辑说明:BASE_URL是前后端联调的关键,微信开发者工具里模拟器可以访问本机,但真机调试必须指向局域网 IP,且后端要监听0.0.0.0。Authorization从本地缓存读取 token,请求头带上后后端中间件会统一鉴权。错误处理上,约定后端返回code=0为成功,其他 code 一律弹 toast,避免每个页面重复写错误逻辑。

参数说明:path必须以/开头,因为后端路由是按模块前缀定义的;method默认 GET,但 POST 时要手动传对象;data在 GET 请求里会被 wx.request 自动拼接成 query,POST 里转 JSON 体。如果后端要求表单格式,需要改Content-Type为application/x-www-form-urlencoded,并相应调整数据结构。

2.3 后端接口设计与数据库表关系:如何让“估价”和“结算”不脱节

后端的价值在于回收计价和结算。这套源码的后端接口一般分为三类:用户端接口(提交预约、查询价格、查看订单)、回收员端接口(接单、称重、提交结算)、管理后台接口(品类管理、订单审核、财务结算)。路由实现方式可能是 TP 风格的路由,也可能是其他风格的路由,但接口前缀通常是/api/user、/api/recycler、/api/admin。

数据库设计上,除了刚才提到的recycle_order和order_weight_log,还必须有一张recycle_category表保存回收品类和基础价格,比如废纸、废塑料、废金属、旧衣物、旧家电。这张表是估价逻辑的核心,字段一般包括category_name、unit_price(单价,单位是元/公斤)、min_weight(起收重量)、is_hot(是否首页推荐)。有的版本还会做多级类目,用parent_id关联。

订单和价格的联动是重点。很多二手回收小程序翻车的原因,是下单时显示的价格和实际结算价格不一致。根源在于:下单时只保存了“参考估价”,而最终结算依赖回收员在“称重”时重新计算。代码里必须区分estimated_price(预估金额)和final_price(结算金额),并且在前端详情页明确标注“实际金额以称重为准”。如果数据库表里只有一个price字段,那就要在接口层加一个price_type来区分,否则用户下单后看到的价格被覆盖,投诉率会直线上升。

下面是一段典型的回收品类价格查询接口实现,可以帮助你理解价格和订单的关系:

// api/category.php 简化逻辑 public function list_category_with_price() { $list = Db::name('recycle_category') ->where('status', 1) ->field('id, category_name, unit_price, unit, min_weight') ->order('sort_order asc') ->select(); // 价格一律转换成“元/公斤”,前端统一展示 foreach ($list as &$item) { $item['price_text'] = '¥' . number_format($item['unit_price'], 2) . '/' . $item['unit']; } return json(['code' => 0, 'data' => $list]); }

逻辑说明:这段代码从品类表读取启用的类目,只返回前端需要的字段。unit字段用来区分“元/公斤”还是“元/件”,因为旧家电可能按件估价,而废纸按公斤。前端在提交预约时,回传的就是category_id和预填的重量,后端根据unit_price计算参考价,不直接从用户输入的“总价”取值,防止价格被篡改。

参数说明:sort_order控制首页分类排序,status=1表示启用,如果某个品类暂时不收,不应删数据而是把 status 改为 0。min_weight一般要大于 0,否则会出现预约 0.1 公斤废纸,回收员跑一趟的情况,这在业务上需要额外规则。实际项目中,我还见过在查询列表时对category_id加缓存,减少 DB 压力,v6.15.2 源码不一定带了,但你可以自行加上 Redis 或文件缓存。

3. 本地跑通这套 v6.15.2 前端+后端的最小步骤

3.1 后端环境准备和配置文件修改

拿到源码包,先看目录结构。典型的是backend、frontend、database三个文件夹。database里一般是.sql文件,导入就可以用。后端如果是 ThinkPHP 5/6,需要 PHP 7.3 以上,nginx 或 Apache;我一般用 PHP 内置服务器来先跑通业务。

第一步先改数据库配置。以 ThinkPHP 的.env或config/database.php为例。假设你的数据库名是community_recycle,账号root,密码空。关键配置如下:

// config/database.php return [ 'type' => 'mysql', 'hostname' => '127.0.0.1', 'database' => 'community_recycle', // 数据库名 'username' => 'root', // 数据库用户 'password' => '', // 数据库密码 'hostport' => '3306', 'charset' => 'utf8mb4', 'prefix' => 'cr_', // 表前缀,导入时注意 ];

逻辑说明:prefix是表前缀,如果你导入的 SQL 里表名是cr_recycle_order,这里就一定要写cr_,否则后面所有模型查询都会带着前缀,查不到表。有些源码会省掉前缀,那这里留空即可。

参数说明:hostname不要用localhost,建议用127.0.0.1,避免 PHP 某些环境对 localhost 解析为 IPv6 导致连不上;charset用utf8mb4,因为手机号、地址、备注里可能有表情符号,需要 4 字节编码。如果你本机 PHP 版本高于 7.3,还要留意项目是否自带vendor目录,如果没有,需要先执行composer install还原依赖。

改完后,用命令行启动后端:

cd backend php think run -H 0.0.0.0 -p 8080

参数说明:-H 0.0.0.0表示监听所有网卡,这样同一局域网内的手机也能访问后端。-p 8080是端口,前后端联调时保持统一。注意 TP5.1 的think run支持-H,但 TP6 里可能要用php think run --host 0.0.0.0 --port 8080,具体用php think帮助查看。

启动后先测试接口是否通:在浏览器访问http://127.0.0.1:8080/api/category/list,如果能返回 JSON 数据,说明数据库和路由都正常。如果出现 404,先查public/index.php里的应用入口是否被正确重写,或者后端是否配置了伪静态规则。用 PHP 内置服务器时,一般不用重写,但如果用 nginx,就要把location /里的 try_files 配置到index.php。

3.2 数据库初始化:把 SQL 导入并核对表前缀

数据库导入是最容易翻车的环节。常见坑:SQL 文件太大,用 phpMyAdmin 导入超时;或者 SQL 里混入了别的库的表,导入后多出一堆无关表。我习惯的命令行导入方式:

mysql -uroot -p < database/community_recycle_v6.15.2.sql

导入后,登录 MySQL 检查以下几张关键表是否存在:recycle_order、recycle_order_weight_log、recycle_category、user、recycler、admin_user、config。

SHOW TABLES LIKE 'cr_%';

如果发现表名是cr_前缀,但后端配置里没写前缀,后面查询必然报“数据表不存在”。可以把 config 里的 prefix 改成cr_,也可以改 SQL 批量去前缀,但推荐前者,省事且不易出错。导入后最好重置运营者密码。很多源码会把后台默认账号写在admin_user表里,初始化后第一件事是用 SQL 改掉默认密码,别留着默认的admin/123456上生产环境。改密码通常走 bcrypt 加密,SQL 里用md5的也有,要按源码的路由来,不能一概而论。

检查表结构时,留意recycle_category里是否有unit字段。v6.15.2 常见的是unit存“kg”或“piece”,但有些旧表只有unit_price没有unit,这种就要手动补列。补列 SQL 参考:

ALTER TABLE `cr_recycle_category` ADD COLUMN `unit` VARCHAR(10) NOT NULL DEFAULT 'kg' COMMENT '计价单位' AFTER `unit_price`;

执行后记得刷新后端缓存。如果你用的是 ThinkPHP,可以在runtime目录下清掉编译缓存,否则模型字段缓存里可能还是旧结构,导致“字段不存在”的报错。

3.3 小程序前端导入与本地联调

前端不管是用微信开发者工具直接打开,还是 HBuilderX 运行到微信开发者工具,都需要配置appid。自己没注册小程序的话,可以用微信开发者工具的“测试号”,但测试号无法使用微信支付、订阅消息等能力。本地联调不受影响,所以先用测试号跑通,等要上线时再换正式 appid。

打开项目后,第一件事就是改utils/request.js里的BASE_URL。注意,微信小程序真机调试不能访问localhost,必须用电脑的局域网 IP,例如http://192.168.1.100:8080。并且要在开发者工具右上角“详情-本地设置”里勾选“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”,否则工具会拦截所有非 HTTPS 请求。这只是本地调试,上线前要换成 HTTPS 域名并配置合法域名。

改完后,编译小程序,能看见首页的品类列表从后端加载出来,就说明前后端联调通了。如果控制台报 403,检查后端是否开启了跨域限制。ThinkPHP 一般用中间件处理跨域,如果没处理,小程序端请求会失败。我通常在后端添加一个公共跨域头:

// 在入口或中间件中统一允许跨域 header('Access-Control-Allow-Origin:*'); header('Access-Control-Allow-Headers: Authorization, Content-Type'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');

注意:*代表接受任何来源,开发阶段无所谓,上线前应改成自己小程序的合法域名,否则任何人都能请求你的接口,存在安全隐患。改完跨域头重启后端,再编译小程序,首页品类就能加载出来。

到这一步,本地跑通的标志是:你从小程序里提交一个预约回收订单,在 MySQL 的recycle_order表里能看到这条记录。如果看不到,说明接口路径或者数据表名有偏差,按刚才的检查顺序排查:先看后端日志,再看network面板的请求响应,最后看 SQL 是否插入成功。

4. 从预约到结算:把 v6.15.2 的核心回收流程吃透并改造

4.1 预约回收接口与前端表单校验:防止无效订单

回收预约表单的核心字段包括:用户手机号、联系地址/小区名称、回收品类、预估重量、期望上门时间、备注。前端表单校验最重要的不是“必填”,而是“品类和重量联动”。如果用户选了“旧家电”,单位是“件”,重量输入就不应该显示公斤单位;选了“废纸”,重量必填——这个联动逻辑在 UI 层用监听category_index变化来切换。

提交预约时,后端需要做两件事:创建订单,并同步创建一条“预约状态变更记录”。有些人只在订单表里改status,没有日志,后面出现纠纷无从排查。v6.15.2 源码里如果只有一个状态字段,我会建议你在订单历史表和操作日志表上补数据。下面是简化版的前端提交函数:

// pages/submit/submit.js 里的提交函数 const { request } = require('../../utils/request'); Page({ data: { categoryList: [], formData: { category_id: null, expect_weight: 0, address: '', contact_name: '', contact_mobile: '', expect_time: '' } }, onLoad() { this.loadCategories(); }, async loadCategories() { const list = await request('/api/category/list', 'GET'); this.setData({ categoryList: list }); }, async onSubmit() { const d = this.data.formData; if (!d.category_id) { wx.showToast({ title: '请选择回收品类', icon: 'none' }); return; } if (!/^1\d{10}$/.test(d.contact_mobile)) { wx.showToast({ title: '请填写正确的手机号', icon: 'none' }); return; } if (!d.address || d.address.length < 5) { wx.showToast({ title: '请填写详细地址', icon: 'none' }); return; } const res = await request('/api/order/create', 'POST', { category_id: d.category_id, expect_weight: d.expect_weight, address: d.address, contact_name: d.contact_name, contact_mobile: d.contact_mobile, expect_time: d.expect_time }); if (res) { wx.redirectTo({ url: '/pages/order/detail?id=' + res.order_id }); } } });

逻辑说明:request封装在 2.2 节,这里直接用。校验顺序是“品类 -> 手机号 -> 地址”,每步都给出明确提示。expect_weight在“旧家电”类目下可以传 0,但后端要根据category_id判断单位,如果不支持按件就不能传 0。提交成功后用redirectTo跳到订单详情页,而不是navigateTo,防止用户反复返回重复提交。

后端接收参数后,必须对category_id做存在性校验,并对expect_weight做范围校验。常见的翻车写法是后端只信前端传来的price,这是拒付接口最常见的漏洞。正确做法是后端用category_id查unit_price,再根据重量计算estimated_price,前端传的金额一律不作为录入字段。预约接口的返回值要带上order_id,方便前端跳转和后续轮询。

4.2 估价逻辑:把“废纸 0.8 元/斤”这种规则落进代码

小区回收的实际价格不是一成不变的,会跟着市场行情波动。很多源码把单价写死在品类表里,后台改一次价格,旧订单的参考价也跟着变,这不对。正确做法是订单创建时把当时的单价快照存进订单表,比如order_snapshot_price。这样后续调整品类表价格,不影响已经生成的订单。

估价逻辑还涉及“重量区间”:比如废纸 5 公斤以下按 0.6 元/公斤,5 公斤以上按 0.8 元/公斤。这种阶梯计价在 v6.15.2 源码里不一定具备,需要自己加。我常做的方案是在品类表加一个price_ruleJSON 字段,存阶梯规则:

{ "normal": 0.8, "steps": [ { "max": 5, "price": 0.6 }, { "max": 100, "price": 0.8 } ] }

后端在计算价格时,先判断有没有price_rule,没有就走默认的unit_price:

private function calcPrice($category_id, $weight) { $category = Db::name('recycle_category')->find($category_id); $price = $category['unit_price']; $rule = json_decode($category['price_rule'], true); if (!empty($rule['steps'])) { foreach ($rule['steps'] as $step) { if ($weight <= $step['max']) { $price = $step['price']; break; } } } return round($weight * $price, 2); }

逻辑说明:json_decode解析出来的steps要按max从小到大排,否则会匹配到错误区间。round(..., 2)保留两位小数,因为回收结算到分。如果price_rule为空,走默认单价,不会报错。这里去掉任何前端传过来的总价参与计算,保证价格来自服务端规则。

参数说明:阶梯规则的max是包含边界值,即 weight <=5 时按 0.6 算。如果你希望 5 公斤整也按下一档计费,要把条件改成<。另外,按件计价的品类不适合这套阶梯逻辑,直接判断unit字段为piece时跳过重量计算,改为后台预设的固定回收价。

4.3 订单状态推进:接单、称重、结算的接口与幂等

回收员端最主要的操作是“接单”和“称重结算”。接单接口要把订单状态从 0 改成 1,并且要校验回收员是否已经被指派,还是可以自己抢单。v6.15.2 的默认逻辑可能是按小区分配回收员,那你只需要判断回收员负责的区域是否覆盖订单地址。

称重结算时,前端上传两张照片(回收物品照片、称重照片),后端保存照片路径,同时把重量、金额、状态更新为“待确认”。这里有一个很关键的幂等问题:回收员连续点两次“确认结算”,会导致订单状态被重复推进,甚至余额增加两次。所以后端接口必须带上order_id + 当前 status作为更新条件。

// 结算更新示例(ThinkPHP) $result = Db::name('recycle_order') ->where('order_id', $order_id) ->where('status', 2) // 只有当前是“待确认称重”状态才更新 ->update([ 'status' => 3, 'weight' => $weight, 'final_price' => $price, 'update_time' => time() ]); if ($result === 0) { return json(['code' => 1, 'msg' => '订单状态已变更,请刷新后重试']); }

逻辑说明:where('status', 2)是乐观锁的意思,同时只有一个请求能成功。如果更新影响行数为 0,说明订单已经不是待确认状态,必须给用户明确的“请刷新”提示。这里不要用update返回真假来判断,因为 MySQL 里影响行数 0 可能代表数据没变化,需要用result === 0或false判断失败。

参数说明:final_price必须在后端根据实际重量和快照单价重新计算,不能直接采用前端传的price。前端传来的价格只用于回显,后端要重新计算并覆盖,这是防止报价被改的一条底线。

结算之后,还要走“回收员分成”。常见做法是在订单表里存一个recycler_ratio字段,比如 0.8 表示回收员拿 80%。结算时记录分成金额,并在回收员余额表里加钱。这套逻辑如果源码里没有,建议在“确认结算”的事务里一起更新,保证订单表和余额表要么都成功要么都失败,避免一半成功导致账不平。

5. v6.15.2 上线与二次开发的避坑清单

5.1 微信小程序合法域名问题:开发工具能通,真机一碰就挂

现象:本地调试一切正常,预览到手机时就白屏或请求全部失败。

原因:微信小程序的“不校验合法域名”开关只在开发者工具内生效,真机小程序强制要求request的域名已经配置到 MP 后台的“服务器域名”白名单,而且必须是 HTTPS,且备案过的域名。

解决:上线前先把后端 API 部署到带 HTTPS 的域名,然后在微信公众平台-开发-开发设置-服务器域名里添加request合法域名。域名不能带路径,只能是https://api.example.com这种格式,且不能是 IP。如果你正在用测试号,真机上可以先打开“开发版”并开启“不校验合法域名”选项,但正式版必须配置。

5.2 图片上传失败:回收员传称重照片总是转圈

现象:真机上选择图片后上传,等了几秒提示“上传失败”,控制台报uploadFile:fail url not in domain list或者 413。

原因:wx.uploadFile的上传域名和wx.request的域名是分开配置的,很多人只配了 request 合法域名,没配 uploadFile 合法域名;另外后端限制了上传文件大小,默认 2M 不够用,称重照片体积常在 3M 以上。

解决:在 MP 后台配置uploadFile合法域名,并调整后端upload_max_filesize和post_max_size。同时在前端压缩图片再上传,我一般用wx.compressImage把照片压到 1.5M 以内再交上传接口。还要检查后端是否是直传本地目录,如果上传目录没有写入权限,会出现“文件保存失败”但接口返回 200 的假象。

5.3 订单状态不一致:用户下单后订单神秘消失

现象:用户提交预约成功,但在订单列表里看不到记录,数据库却有一条status=5(已取消)的单子。

原因:订单创建后,系统可能启动了“超时未支付自动取消”的定时任务,但回收订单本应是“货到付款/统一结算”模式,不需要用户预先支付。定时任务把未支付订单直接取消了。

解决:先查config表里是否有order_timeout或auto_cancel参数,把这个参数调大或关闭。更彻底的做法是检查创建订单的接口,是否默认设置了payment_status=0并触发支付超时逻辑。如果是,就把回收订单排除在支付超时任务之外,判断条件改为“仅当订单类型为在线支付时才参与自动取消”。

5.4 定位距离误差:按小区派单时回收员接不到单

现象:回收员在小区 A 门口,却看不到 100 米外的小区 B 的订单,派单规则只按订单地址的经纬度算 500 米半径,坐标偏移导致覆盖不足。

原因:前端wx.getLocation返回的是 GCJ-02 坐标,小程序后端如果直接比较 GPS 坐标,可能在某些地图 SDK 迁移时出现上百米偏差;另外很多人复制了测试地址的经纬度,订单定位落在主干道上。

解决:统一使用同一坐标系,前端上报经纬度时可以用wx.getLocation的isHighAccuracy,后端围栏计算前先做坐标偏移校准,比较稳妥的做法是拿到经纬度后调用统一的地图解析服务转换成规范坐标。如果不想引外依赖,就在派单算法里把半径扩大 200 米并采用“圆形范围 + 地址关键词匹配”双保险,至少不会漏单。

5.5 升级 v6.15.x 后数据库字段不兼容

现象:从旧版本升级到 v6.15.2 后,后台价格配置页打不开,报Unknown column 'unit_field'。

原因:新版在品类表里新增了unit_field字段,但 SQL 升级脚本没有自动执行,旧表还是老结构。

解决:源码包里通常会带upgrade_sql目录,逐一执行里面的增量 SQL。如果没带,可以对比后台控制器里常用的表字段,用ALTER TABLE补上缺失列。这里一定要先备份数据库再改。我遇到过有人直接在数据库查询器里点了执行,结果删错字段,最后只能从备份恢复。升级前把recycle_order、recycle_category两张表单独导出再动手,是重复一万次都不会亏的习惯。

6. 给估价表加一个自定义字段:复用 v6.15.2 的品类配置,最省事的做法

很多运营需求是“废纸今天涨到 9 毛,明天跌回 7 毛”,如果每次都要改代码、发版小程序,谁也受不了。更好的习惯是把计价规则做成可配置,且尽量不动现有表结构。我给 v6.15.2 做二次开发时,最常用的一招是在recycle_category表上增加一个price_rule字段,类型用text,存 JSON 字符串,后台表单里放一个多行文本域,前端估价接口直接解析这个字段。

好处是显而易见的:你不需要为每一种定价规则建新表、写新接口,运营人员自己在后台粘贴一段 JSON 就能生效。下面是后台保存规则的简化代码:

// 后台保存品类规则 public function save_rule() { $data = request()->post(); $category_id = intval($data['category_id']); $price_rule = $data['price_rule']; // 形如 {"normal":0.8,"steps":[{"max":5,"price":0.6}]} if (!json_decode($price_rule)) { return json(['code' => 1, 'msg' => '规则必须是合法 JSON']); } Db::name('recycle_category') ->where('id', $category_id) ->update(['price_rule' => $price_rule]); return json(['code' => 0, 'msg' => '保存成功']); }

前端计算价格时,判断price_rule是否为空,为空则用unit_price,不为空则按阶梯规则计算。这样“正常价”和“活动价”能同时存在,也方便后续做促销活动。注意后台校验 JSON 合法性,不要保存了空字符串后前端直接崩。

我一开始把价格写死在代码里,运营每改一次价格,我就要重新传一次包,后来把所有规则都挪到后台配置,彻底告别了这种无意义的体力活。这个习惯后来也影响了我做其他模块:凡是运营要改的数值,一律配置化,代码里只留默认值。现在你拿到这套 v6.15.2 源码,第一件事也是把估价规则、回收员分成比例、客服电话这种运营素材全部确认一遍,能进配置表的就不要写死。

如果你以后要扩展“按小区差异化定价”,也可以照着这个思路再建一张community_price表,用community_id + category_id做唯一索引,前端根据用户定位所在小区拉对应价格。这个方向比改代码硬撑要稳妥,也更容易被运营接受。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询