ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

共享雨伞租借系统毕业设计:Python后端+微信小程序全流程实现

共享雨伞租借系统毕业设计:Python后端+微信小程序全流程实现 简介基于微信小程序的共享雨伞租借系统是一份面向计算机相关专业的高分毕业设计或课程设计完整项目源码包。源码内含可直接运行的小程序前端页面与逻辑并配有详细说明文档覆盖首页、下单、开锁、支付、钱包、押金、余额、日志等主要业务模块能够帮助学习者快速理解共享租借类小程序的完整实现流程。资源包共计五十六个文件以十三个脚本逻辑文件、十一份配置、十份样式和九份页面模板为主另有图片、说明文档及附加压缩包整体体积仅有一点零三兆轻量且结构清晰便于查阅与二次开发。目前已有两百二十九人学习浏览适合作为项目初期演示、课程作业或毕业设计参考。所有代码均经过运行测试功能稳定可直接在此基础上扩展其他功能具有较强的实用与学习价值。1. 共享雨伞租借系统毕业设计里少见的「能跑通全流程」选题选毕业设计题目时很多人栽在「伪需求」上——做个商城、做个点餐功能堆得再全评委看一眼就知道是照着教程抄的。共享雨伞这个选题不一样它有真实业务闭环借伞 → 计费 → 还伞 → 押金有硬件联动想象空间扫码桩、GPS又有小程序端 Python 后端 管理后台的三层结构天然适合拿高分。这份源码包我拆过一遍后端用 Python 系框架写接口前端是微信小程序原生实现数据库用 MySQL整套流程从用户授权登录到订单结算都有完整落库。最关键的是它把押金、计费规则、超时扣费这些容易翻车的业务逻辑都做了处理不是只摆几个页面糊弄事。适合谁一是正在做 Python 类毕业设计、需要「有深度且能演示」项目的人二是想把小程序 后端这套交互流程搞明白、但不想从零踩一遍授权和支付的开发者。下面我按自己拆包的顺序把这套系统的设计、接口、联调逐层说透最后把最容易卡住的地方直接标出来。2. 先把骨架搭明白三层结构、数据库表设计与租借状态机拿到一份源码我不建议先双击运行而是先把「数据怎么流」理清楚。这套系统分三层微信小程序做用户端扫码借伞、查看订单、缴纳押金Python 后端提供 REST 接口并处理计费逻辑管理后台做雨伞和订单管理。三层之间靠 HTTP JSON 通信用户身份靠微信登录凭证换取 openid 来识别。2.1 数据库表共享雨伞最核心的 4 张表打开 SQL 脚本你会发现表并不多但每张表都有讲究。我一般会把核心表整理成下面这样方便对着源码看字段含义。表名核心字段作用关键索引useropenid、nickname、avatar、deposit_status用户身份与押金状态openid 唯一索引umbrellaumbrella_id、site_id、status(0空闲/1租出/2保修)、rfid_code雨伞实体与位置status、site_id 联合索引orderorder_id、user_id、umbrella_id、start_time、end_time、fee、deposit、status借还记录与计费结果user_id status 联合索引sitesite_id、name、address、longitude、latitude、total_count、available_count借还伞点经纬度字段用于距离排序值得注意的一点是order表没有直接存「押金明细」而是通过deposit字段记录订单发生时的押金快照。这个设计的好处是如果押金规则后期调整比如从 29.9 涨到 39.9历史订单的结算仍然以快照为准不会出现对不上账的情况。毕业设计答辩时如果你能主动讲出「为什么不做关联而是做快照」老师一般会认可你的数据一致性意识。2.2 租借状态机避免「伞不见了」的设计关键共享雨伞最常见的翻车点是状态不同步——用户借了伞但系统没记录或者还了伞但伞点数量没恢复。这套系统用状态机控制核心逻辑是只能按固定方向迁移-- 伞状态0空闲 - 1租出 - 0空闲正常归还 -- 异常分支1租出 - 2保修用户报修伞物理回收 UPDATE umbrella SET status 1, current_order_id ORD20250101001 WHERE umbrella_id U001 AND status 0;上面这条 SQL 是关键操作的雏形借伞时必须带上AND status 0条件利用数据库行锁避免并发下同一把伞被两个人同时借走。如果更新影响行数为 0说明伞已被借出接口直接返回失败。后端接口里还要区分「用户还伞」与「管理端强制结单」两种路径。强制结单需要额外记录操作人这个字段在 order 表里用admin_id保留。常见做法是管理端强制还伞后物理伞状态标记为「待盘点」而不是直接变成空闲这样能给线下工作人员一个缓冲时间去确认伞是否真的在桩位上。有了这一层答辩时被问「遗失怎么办」就能答得很有底气。2.3 站点容量控制available_count 怎么保证准确每个伞点的available_count是用户端展示可借数量的来源。很多毕设项目直接读表结果就是还伞时只更新伞状态忘了更新站点数量前端显示 0 但实际有伞。这套源码的处理方式是在一个事务里完成「伞状态更新 站点数量增减」START TRANSACTION; UPDATE umbrella SET status 1 WHERE umbrella_id U001 AND status 0; UPDATE site SET available_count available_count - 1 WHERE site_id S001 AND available_count 0; COMMIT;两条更新必须放在同一个事务里任何一条失败都要回滚。最后一句的AND available_count 0是防负数属于防御式编程。如果更新行数不符合预期接口层要抛「库存不足」异常而不是继续往下走。3. 后端接口这样写借伞、还伞、计费规则一次讲清楚小程序端只是交互壳真正的业务判断都在 Python 后端。我拆的这份源码里后端用了 Flask 风格的路由组织按业务模块拆分了蓝图blueprint请求参数校验和错误码都做了统一封装。下面挑三个核心接口讲这三个也是毕业设计演示时必被问到的。3.1 借伞接口锁伞 订单创建 押金校验api.route(/umbrella/borrow, methods[POST]) def borrow_umbrella(): 借伞流程校验押金 - 锁伞 - 创建订单 请求参数openid, umbrella_id, site_id data request.get_json() openid data.get(openid) umbrella_id data.get(umbrella_id) site_id data.get(site_id) # 1. 押金校验用户必须已缴纳押金或在免押金白名单 user get_user_by_openid(openid) if user.deposit_status ! 1: return jsonify(code4001, msg未缴纳押金或押金已退还) # 2. 锁伞尝试行数判断唯一性 locked try_lock_umbrella(umbrella_id, openid) if not locked: return jsonify(code4002, msg雨伞已被借出或处于保修状态) # 3. 创建订单 order_id generate_order_id(openid) insert_order(order_id, openid, umbrella_id, site_id) return jsonify(code0, msg借伞成功, data{order_id: order_id})这里的关键点是第 2 步的try_lock_umbrella它底层就是前面贴的那条带条件更新的 SQL。用「更新行数是否为 0」来判断是否抢到比先 SELECT 再 UPDATE 安全得多后者在并发下会有竞态条件。押金校验放在锁伞之前这是为了减少无效锁伞操作。如果用户没交押金就直接让他锁伞伞会被锁住但订单创建失败状态就卡死了。源码里对这种情况有超时释放机制——锁伞后 60 秒内订单未创建成功自动把伞状态回滚为空闲。这个细节可以在文档里找check_umbrella_timeout函数确认。3.2 还伞接口计费规则与订单关闭计费是本项目最核心的业务逻辑也最容易在答辩时被追问。源码里采用的规则是首小时免费超过 1 小时后按 1 元/小时计费不足 1 小时按 1 小时算单日封顶 10 元。这个规则既有梯度又封顶演示时效果最好——借几分钟免费借 5 小时也就扣 5 块用户不会觉得被坑。def calc_fee(start_time, end_time): 计费规则首小时免费超出部分1元/小时单日封顶10元 返回金额单位分 duration_hours (end_time - start_time).total_seconds() / 3600 if duration_hours 1: return 0 # 超出部分向上取整小时 extra_hours math.ceil(duration_hours - 1) fee extra_hours * 100 # 1元 100分 # 单日封顶 10 元 1000 分 fee min(fee, 1000) return fee需要留意的参数细节extra_hours用math.ceil向上取整意味着借了 1 小时 1 分钟就按 2 小时收费。计费尽量用整数分运算避免浮点精度问题。演示时如果用户借了 59 分钟还伞费用为 0前端要提示「首小时内免费」否则用户会以为自己被白嫖了。还伞接口在此基础上还要处理「超时未还的罚金」——源码里用定时任务扫描超过 24 小时未还的订单自动追加扣费并把伞标记为「滞留」。单日封顶的逻辑是两级封顶按自然日算一次整个订单周期也设一个上限防止用户借了一个月被扣几百块导致客诉。3.3 微信登录openid 换取的完整链路小程序端wx.login()拿到的是临时 code后端要用 code 换 openid。源码里封装了一个WXSessionService核心是请求微信接口def code2session(js_code): 用小程序登录 code 换取 openid 和 session_key appid 与 secret 从配置文件读取不得硬编码 url https://api.weixin.qq.com/sns/jscode2session params { appid: APP_ID, secret: APP_SECRET, js_code: js_code, grant_type: authorization_code } resp requests.get(url, paramsparams, timeout5).json() if openid not in resp: # 记录原始错误码便于排查 logger.error(fwx login failed: {resp}) return None return resp[openid]这里有两个重要的坑。一是APP_SECRET绝对不能出现在小程序前端代码里否则任何人可以反编译拿到你的密钥二是 code 只能用一次而且有效期只有 5 分钟后端拿到 code 后必须立即调用换取接口。源码里对换取失败的情况做了降级处理——如果网络超时返回「请重试」而不是直接报错因为微信接口偶尔会抖动。拿到 openid 之后源码用itsdangerous生成带签名的 token 返回给小程序。后续请求通过请求头Authorization: Bearer token携带后端每个受保护接口都要校验签名和有效期。这个设计比「把 openid 直接传参」安全得多也符合真实项目的 token 体系。4. 小程序端从 0 到能演示登录、扫码借伞、订单列表与支付对接前端部分拆包后是原生微信小程序项目没有用 uniapp 或第三方框架基础库版本要求不算高。页面结构包括首页地图找伞点、借伞页扫码、订单页、我的页面。下面按调试顺序讲关键实现。4.1 登录态管理手动调 code 流转// utils/auth.js function login() { return new Promise((resolve, reject) { wx.login({ success: async (res) { if (!res.code) { reject(new Error(获取code失败)); return; } // 调用后端 /user/login 接口换取 token const { data } await request.post(/user/login, { code: res.code }); wx.setStorageSync(token, data.token); wx.setStorageSync(openid, data.openid); resolve(data); }, fail: reject }); }); }注意wx.login在每次小程序冷启动时都要调用一次返回的 code 都是新的。后端换到 openid 后如果用户已在数据库则直接返回 token否则自动注册一条新记录——这就是「静默注册」。真实场景里建议再完善一步返回 token 前检查用户资料是否完整如果没填昵称头像给前端一个「补全资料」的跳转标记。token 过期处理我推荐在request封装里统一拦截。源码里有个handleTokenExpired函数当后端返回 40101 错误码时自动重新走一遍 login 流程然后重放原请求。这个小功能看起来不起眼但演示时极其加分——连续操作两三个页面不退出登录说明状态管理是及格的。4.2 扫码借伞扫不出来怎么办扫码借伞用的是wx.scanCode接口但是这里有个常见的翻车点——小程序只能识别普通二维码而一套完整的共享伞系统通常要用「二维码 蓝牙秤砣」双通道来防伪。毕设项目一般直接扫伞上贴的二维码二维码内容约定为一个伞的唯一标识码后端再和数据库里的 rfid_code 做绑定检查。// pages/borrow/borrow.js async function scanAndBorrow() { const res await wx.scanCode({ onlyFromCamera: true }); const umbrellaCode res.result; // 例如 UM-20250101001 // 先调后端校验二维码是否有效 const { data } await request.post(/umbrella/verify, { code: umbrellaCode }); if (!data.valid) { wx.showToast({ title: 该二维码不存在, icon: none }); return; } // 弹出确认框确认后调借伞接口 const confirmed await wx.showModal({ title: 确认借伞, content: 编号 ${umbrellaCode}使用中请保管 }); if (confirmed.confirm) { await request.post(/umbrella/borrow, { umbrellaId: data.umbrella_id }); wx.redirectTo({ url: /pages/order/detail?id data.order_id }); } }onlyFromCamera: true这个参数值得说明一下它强制只能从摄像头扫码不能从相册选图避免演示时误扫到截图。而verify接口是独立于borrow接口的前置校验目的是先给用户一个反馈——「这把伞能不能借」——而不是等真正借的时候才报错。如果是普通二维码直接调 borrow 接口也行但交互体验差一点。4.3 订单列表时间格式化与状态标签订单页主要就是列表渲染。我注意到源码里有个formatTime工具函数把后端返回的2025-01-25T14:30:00格式化为01-25 14:30这种更直观的展示。千万别在后端拼好字符串返回给前端应该返回裸的时间戳或标准时间格式拆包时看到这种设计要记住——这是好习惯。订单卡片状态机的展示逻辑是在前端完成的进行中显示「扫码还伞」按钮已完成显示费用异常单显示「联系客服」。这里我建议前端只根据订单状态字段做条件渲染不要自己做任何费用计算费用一律以后端结算结果为准。原因是前端算钱容易和实际扣款对不上演示时一旦被发现会出现很尴尬的场面。4.4 微信支付与押金两种模式的区别先声明一个容易混淆的点押金退还和订单扣款是两个独立流程。押金用「微信支付-付款到零钱」接口原路退回订单费用用「小程序支付」扣款。如果项目只做演示押金可以做成模拟支付——点击「缴纳押金」按钮后直接调后端接口把deposit_status置为 1不真正走微信支付。源码里两种都实现了真实支付逻辑在wx-pay模块需要你在配置文件里填入商户号、API 密钥等参数。调试时用测试商户号回调地址必须是公网可访问的 HTTPS 地址本地开发可以用内网穿透工具把回调路由暴露出去。特别提醒微信支付回调的验签逻辑千万别省回调里拿到的金额、订单号都要和数据库比对防止伪造回调攻击。5. 避坑指南从环境配置到联调演示我踩过的 5 个坑这部分是血泪经验每一条都是毕设答辩翻车重灾区。按「现象 → 原因 → 解决」的方式记录对照源码改完基本能跑顺全流程。5.1 坑一本地能跑手机预览白屏现象微信开发者工具里一切正常真机扫码预览后页面空白或请求全部失败。原因开发者工具有「不校验合法域名」的选项所以本地用 http://127.0.0.1:5000 能通真机上微信要求所有请求域名必须是 HTTPS 且在公众平台配置过白名单。解决把后端服务部署到服务器上并配置 SSL 证书然后在微信公众平台「开发管理 → 服务器域名」把 request 合法域名加上。注意域名不能带端口且需要 ICP 备案。如果是纯毕设演示最省事的做法是租一台带备案域名的轻量服务器后端用 gunicorn 跑在 443 端口。5.2 坑二扫码借伞提示「非法二维码」现象自己生成的二维码扫出来 code 是一串数字但后端 verify 接口一直报无效。原因依赖安装不完整导致二维码工具函数解析出错或者后端生成二维码时把「伞编号」和「伞 ID」混用了。解决先在数据库里直接查一下你要测试的那把伞的rfid_code或umbrella_code到底存的是什么。再用在线二维码生成器把该值转成二维码扫码测试。如果还失败在 verify 接口打印收到的 code和前端的取值比对——很多时候是前端传参 key 不一致codevsumbrellaCode。5.3 坑三押金交了但 borrow 接口还是报「未缴纳」现象用户端显示已缴纳押金但借伞时后端判定未缴纳。原因前端把「缴纳成功」页面的跳转当成了押金状态已变更但后端deposit_status更新是异步的状态还没落库。更常见的是用户表里有多个账户测试时用 A 账户缴押金借伞用的是 B 账户的 tokenopenid 对不上。解决押金状态以后端接口查询为准前端展示用接口返回值。排查时先打印 borrow 接口拿到的 openid和缴纳押金时用的 openid 比对。在管理后台加一个「查用户」功能输入 openid 就能看押金状态这个功能做出来在答辩时展示非常实在。5.4 坑四还伞后 available_count 变负数现象站点明明只剩 2 把伞但还了 3 把伞后可用数量变成 -1。原因还伞接口没有事务保护伞状态更新成功了站点数量更新失败被回滚导致两边对不上。解决把「伞状态 站点数量」这两条 SQL 放同一个事务里且站点更新要加 0的条件判断。实际上这种情况在单用户环境中不容易复现需要同时开两个窗口操作同一把伞才会暴露调试时可以用两个浏览器后端接口并发测试来验证。5.5 坑五订单金额对不上用户账单现象用户端显示费用 5 元微信支付扣款 5.5 元对不上。原因计费接口用的时间不是同一个时钟——前端记录的是手机本地时间后端取的是服务器时间。如果用户自己改了手机时间前后端就能差出去半个小时甚至更多。解决所有时间一律以后端服务器时间为准。前端拿到订单后只展示补全后的时间不参与时长计算。如果演示时需要精确演示计费可以在管理后台提供「修改订单时间」的功能把借伞时间手动调早一些再还伞费用变化立即可见。6. 联调验证与进阶加分项怎样把环境跑通并做出「不像毕设」的效果源码包的解压说明里给了一套部署命令但真正能一次跑通的人不多。给你一条我验证过的路径先本地起 MySQL 导入schema.sql再配置config.py里的数据库连接和微信密钥运行python app.py最后在微信开发者工具中导入miniprogram目录并修改app.js里的baseUrl为本地局域网 IP。后端启动时如果报缺少依赖用pip install -r requirements.txt补齐。后端启动成功的标志是http://localhost:5000/api/health返回{code:0}。小程序端编译成功的标志是首页能拉到伞点列表。两者都通了再把手机和电脑连同一个 WiFi把baseUrl改成http://电脑IP:5000打开开发者工具的「不校验合法域名」开关扫码借伞流程就能完整走通。真机联调如果还是失败优先检查防火墙是否放行了 5000 端口以及小程序请求是否被系统拦截。用「局域网 IP 端口」调试是毕设阶段最顺的路不建议一上来就买服务器折腾 HTTPS成本高且收益低。进阶加分项可以从这三个方向任选一个一是给管理后台加一张「分时租借热度图」按小时统计各伞点的借还频次用图表展示高峰时段这份源码里留了order表的时间字段写个聚合查询即可二是给小程序首页加距离排序利用微信wx.getLocation拿到用户经纬度后端按「两点的球面距离」排序返回最近的伞点这是面试官最喜欢问的功能点三是加一个「报修拍照」入口让用户上传伞损坏照片后端用multipart/form-data接收文件并保存到服务器指定目录完整串起「用户 → 后端 → 管理端」的素材流。当初我调试还伞计费时因为时间基准不一致前后端差了 40 分钟费用怎么算都不对。后来我强制把借还时间统一记服务器时间之后才通。从那以后我每次碰这种带状态流转的项目都会先确认「时间基准、金额单位、状态字段」这三个东西是否为同一套标准再动手碰业务逻辑。这套上游的设计思路是反复验证过的照着逐步复现不会有大的逻辑出入。希望帮到你。本文还有配套的精品资源点击获取
返回列表