ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于微信小程序的影院购票系统设计与实现全解析

基于微信小程序的影院购票系统设计与实现全解析 毕业设计做影院购票系统的同学不少但能把微信小程序端、后端接口、数据库表、后台管理整条链路讲清楚的文章不多。太多人拿到一套源码就开始跑跑通了就以为完事了结果一到答辩被老师问几句就卡壳——你这个座位锁定怎么实现的订单状态在哪里流转的为什么小程序要用 wx.login 而不是用户名密码答不上来分数就悬了。这篇文章就围绕基于微信小程序的影院购票管理系统这个毕业设计题目从选题定位、技术选型、数据库设计、核心功能实现、常见坑点到答辩准备完整拆解一遍。不管你是准备开题、已经跑了别人的源码想搞懂原理还是自己从零写这篇都能帮你把底层逻辑捋清楚。尤其是那些拿了现成源码却看不懂业务流转的人耐心看完你至少能跟老师聊明白为什么要这么设计。1. 项目定位与需求拆解1.1 这个题目为什么值得选影院购票管理系统是经典的信息管理 移动端 支付流程综合型题目难度适中、功能界限清晰、演示效果好而且贴近日常生活评委老师都看得懂。它比纯增删改查的图书管理系统高一个档次又比电商系统复杂度低很多非常适合本科毕业设计的时间周期。从技术覆盖面上看这个题目能把你大学四年学过的东西串起来前端微信小程序原生语法WXML、WXSS、JS、组件通信、页面生命周期后端Spring Boot 或其他 Java 框架、RESTful API、参数校验数据库MySQL 表设计、外键约束、事务处理、联表查询流程设计选座、锁座、下单、支付、出票、退票一条完整的状态机链路这个项目你哪怕只做了小程序端 后端 数据库没有做后台管理页面工作量也已经足够支撑一篇毕业论文了。如果再补一个 Web 端管理后台那就是加分项。1.2 核心业务需求梳理一套完整的影院购票系统用户能干嘛、管理员能干嘛要先列清楚。需求不梳理清楚就写代码后期改起来非常痛苦。用户端小程序核心流程首次打开微信授权登录获取用户身份浏览影片查看正在热映和即将上映的电影列表支持按类型、地区、上映时间筛选影片详情预告片、演员阵容、剧情简介、评分、用户评论选择影院和场次不同影院、不同影厅、不同放映时间的场次列表在线选座查看座位图空座可选已售/锁定不可选确认订单并支付显示票价、数量、手续费可无、总价我的订单待支付、已支付、已取消、已完成等状态取票码/二维码在我的订单里查看电子票管理员端核心流程影院信息管理影院名称、地址、影厅数量影厅管理每个影厅的座位排布行数、列数、影厅类型IMAX、普通厅影片管理上传电影海报、影片简介、上映日期、片长、类型场次管理排片某影厅某时间段放哪部电影订单管理查看所有订单、手动改状态如退款这里面最容易忽略的需求是选座和锁座。如果只是简单地让用户选座位然后下单没有考虑多人同时抢同一个座位的并发问题那系统上线就会出大问题。后面我会单独讲这块的实现。1.3 功能边界与工作量估算做毕业设计最怕什么最怕功能不够论文没东西写也怕功能太多做到一半发现做不完。所以需求边界必须提前划好。我这里给一个合理的工作量建议必做功能用户登录、影片列表、影院/场次列表、选座下单、订单管理、后端接口、MySQL 表加分功能支付流程可以用模拟支付、座位锁定、余额/优惠券、评论功能可做可不做Web 管理端如果时间充足、消息推送、扫码取票不要一上来就想做比猫眼还全的系统。猫眼光推荐算法就够好几个博士研究了。你现在要做的是把主链路跑通、逻辑自洽、答辩能讲清楚就已经比 80% 的同期项目强了。2. 技术选型与架构设计2.1 技术栈怎么选更稳妥小程序端基本没有悬念用微信官方原生框架开发。有的同学会问用 uni-app 行不行行但别用。原因很简单你用 uni-app后端接口是一样写的但小程序端代码多了一层编译出了问题你很难判断是框架的问题还是自己的问题。原生框架虽然多写几行代码但社区资料多、报错直白、方便答辩演示。毕业设计求稳原生框架是首选。后端框架看你们学校的风格。大多数学校 Java 课程教的是 Spring所以用 Spring Boot 是最稳妥的选择。如果你对 Python 更熟用 FastAPI 或 Flask 也行但要注意Spring Boot 的生态和文档更多遇到问题搜一下就有答案用 Django 写个后台管理界面还能省不少事。我自己建议的默认组合是端技术小程序端原生微信小程序WXML WXSS JS后端Spring Boot 2.x MyBatis-Plus数据库MySQL 5.7 / 8.0开发工具微信开发者工具 IntelliJ IDEA Navicat接口文档Swagger可选答辩加分项MyBatis-Plus 比原生 MyBatis 省心的地方在于单表操作不需要写 XML生成一套 CRUD 只要几行代码。但你得注意论文里最好写清楚你是基于 MyBatis-Plus 做的不要跟原生 MyBatis 混着写不然老师一眼就看出来你是跑源码的不是自己写的。2.2 前后端交互流程设计小程序不能直接连数据库所有数据都得走后端接口。这里有个很多学生不懂的点小程序请求的域名必须配置在微信公众平台的后台里而且必须是 HTTPS。你本地开发可以勾选不校验合法域名但上线或者演示给别人看的时候如果没有备案过的域名和 HTTPS 证书就只能在开发者工具里跑。前后端交互的 JSON 格式建议统一一下不要一个接口一个样。推荐这种标准返回结构{ code: 200, message: 请求成功, data: { list: [] } }code 表示业务状态码message 是描述信息data 是业务数据。这样前端只需要写一个公共请求方法统一处理 code 非 200 的情况不用每个页面都写一遍错误处理逻辑。小程序端的网络请求封装大概是这个思路拿过去直接改就能用function request(url, method, data) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL url, method: method, data: data, header: { Content-Type: application/json, token: wx.getStorageSync(token) }, success: (res) { if (res.data.code 200) { resolve(res.data.data); } else { wx.showToast({ title: res.data.message, icon: none }); reject(res.data); } }, fail: (err) reject(err) }); }); }BASE_URL 就是一个常量你本地调试时指向自己电脑的 IP 加端口比如http://192.168.1.100:8080。这里有个坑小程序的 request 请求不能直接写 localhost必须写局域网 IP 或者本机 IP模拟器上能用 localhost真机上就不行我后面会专门讲。2.3 前后端接口清单与目录规范接口清单是毕业设计里必写的部分也是你开发前要先制定的。别写一个接口想一个接口先把所有需要的数据交互列出来然后统一规划 URL。我按业务模块给你一份可以直接用的接口清单模块接口路径方法说明用户模块/api/user/loginPOST微信登录传入 code 换取 openid用户模块/api/user/infoGET获取当前用户信息影片模块/api/film/listGET影片列表支持分页和类型筛选影片模块/api/film/detailGET影片详情影院模块/api/cinema/listGET影院列表影院模块/api/cinema/detailGET影院详情及影厅信息场次模块/api/session/listGET指定影片和影院下的场次列表选座模块/api/seat/lockPOST锁定座位下单前临时占座选座模块/api/seat/unlockPOST取消锁座订单模块/api/order/createPOST创建订单订单模块/api/order/cancelPOST取消订单订单模块/api/order/listGET我的订单列表订单模块/api/order/detailGET订单详情与取票码后端项目的目录结构我用 Spring Boot 的标准三层结构Controller 只管接收参数和返回结果Service 管业务逻辑Mapper 管数据库操作。你可以参考这个包结构com.example.cinema ├── controller │ ├── UserController.java │ ├── FilmController.java │ ├── CinemaController.java │ ├── SessionController.java │ └── OrderController.java ├── service │ ├── OrderService.java │ ├── SeatService.java │ └── UserService.java ├── mapper │ ├── UserMapper.java │ ├── FilmMapper.java │ └── OrderMapper.java ├── entity │ ├── User.java │ ├── Film.java │ ├── Cinema.java │ ├── Session.java │ └── Order.java ├── common │ ├── Result.java │ └── ResultCode.java └── configuration └── WebConfig.java这套结构不是给你装样子用的是让你答辩的时候能对着项目讲清楚我的代码分层清晰、职责明确。Controller 层非常薄只做参数接收和结果包装业务逻辑全在 Service 层比如下单要校验座位是否可售、计算总价、生成订单号、更新座位状态这些不能写在 Controller 里。一旦写成面条代码你自己后期调试都找不到问题出在哪。3. 数据库设计与核心表结构3.1 数据表全景与关联关系数据库是毕业设计答辩中被问得最多的环节之一。你表设计得不好直接就是硬伤。电影院购票系统的核心表有用户表、影片表、影院表、影厅表、场次表、座位表、订单表、订单明细表。表之间的关联关系要先画清楚影院 1:N 影厅影厅 1:N 座位影片 1:N 场次影厅 1:N 场次场次 1:N 订单明细同一场次有多张票用户 1:N 订单你在论文里的 E-R 图就按这个逻辑画。需要注意的是座位和场次的关系一个影厅的物理座位是固定的但每个场次都有自己独立的座位状态。同一把椅子上午那场被选走了下午这场还是空的。所以座位状态不能只存在座位表里而是存在场次 座位的组合里。这里我给出一个比较标准的做法座位表存影厅的基础座位信息排号、列号、座位类型另建一个场次座位表记录每个场次下每个座位的实时状态0可售1锁定2已售。逻辑上用场次ID 座位ID联合查询保证每个场次独立判断。3.2 用户表与登录机制设计用户表字段不需要多复杂你系统不涉及收货地址、实名认证所以简洁为主字段名类型说明idBIGINT PK主键openidVARCHAR(64)微信用户唯一标识nicknameVARCHAR(32)用户昵称avatar_urlVARCHAR(255)头像地址phoneVARCHAR(11)手机号可空balanceDECIMAL(10,2)余额如果用余额支付create_timeDATETIME注册时间openid 是微信登录机制里最重要的字段。用户通过 wx.login() 拿到一个临时 code你把这个 code 发给后端后端拿着 code 去微信服务器换 openid 和 session_key。openid 是每个用户在同一个微信小程序下的唯一标识相当于你的用户ID。这里有个很多初学者容易犯的错后端收到 wx.login 的 code 之后要先用 code 去微信接口换 openid换完再查数据库有没有这个 openid。如果存在直接返回登录成功如果不存在先创建用户再返回。不要把 code 当用户标识存到数据库里code 五分钟内就失效了。真正的用户体系是以 openid 为唯一键建立的。登录接口核心逻辑大致长这样PostMapping(/login) public Result login(RequestBody LoginRequest req) { String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code req.getCode() grant_typeauthorization_code; String res restTemplate.getForObject(url, String.class); JSONObject json JSON.parseObject(res); String openid json.getString(openid); User user userMapper.selectByOpenid(openid); if (user null) { user new User(); user.setOpenid(openid); userMapper.insert(user); } return Result.success(user); }3.3 影片、场次与座位表设计影片表相对简单但有几个字段要提前设计好字段名类型说明idBIGINT PK主键titleVARCHAR(64)片名cover_urlVARCHAR(255)海报地址video_urlVARCHAR(255)预告片地址directorVARCHAR(32)导演actorsVARCHAR(255)主演逗号分隔typeVARCHAR(32)类型剧情/喜剧/动作等durationINT时长分钟release_dateDATE上映日期scoreDECIMAL(3,1)评分0-10descriptionTEXT剧情简介statusTINYINT1热映 2即将上映影片海报、预告片地址建议用 URL 存不要存 base64 或者文件路径的本地图片。你上传图片到服务器是没问题的但返回给小程序的时候一定要用完整的 HTTPS 域名拼接不然图片加载不出来。场次表放映计划表是连接影片、影厅、时间的桥梁字段名类型说明idBIGINT PK主键film_idBIGINT影片IDhall_idBIGINT影厅IDstart_timeDATETIME开始时间end_timeDATETIME结束时间开始时间片长priceDECIMAL(10,2)该场次的票价statusTINYINT1可售 0已结束/取消场次表里的 price 是存到每场里的这个设计要解释清楚同一部电影在不同影院不同影厅的票价可能不同IMAX 厅贵一点普通厅便宜一点所以价格挂在场次上而不是影片上。有的学生会把价格写死在影片表里这不符合实际业务答辩时容易被老师挑出来。场次座位表这是并发控制的关键单独讲一下字段名类型说明idBIGINT PK主键session_idBIGINT场次IDseat_idBIGINT座位ID关联影厅座位表statusTINYINT0可售 1锁定 2已售order_idBIGINT锁定/售出时对应订单IDupdate_timeDATETIME更新时间这个表每次选座、下单、支付都会更新。它的存在意义是解决并发问题两个用户同时选同一个座A 用户刚点进去想看B 用户已经下单了那 A 刷新后应该看到这个座位变灰。所以每次用户进入选座页面前端都要调后端接口实时获取最新的场次座位状态而不是本地缓存。3.4 订单表与订单状态机设计订单是这个系统的核心数据字段设计要支撑起整个状态流转字段名类型说明idBIGINT PK主键order_noVARCHAR(32)订单号业务编号非主键user_idBIGINT用户IDsession_idBIGINT场次IDtotal_amountDECIMAL(10,2)订单总金额statusTINYINT0待支付 1已支付 2已取消 3已过期create_timeDATETIME下单时间pay_timeDATETIME支付时间可空cancel_timeDATETIME取消时间可空订单状态是最容易出 bug 的地方必须在设计阶段定死。我的建议是这样一套状态机待支付用户选好座位、提交订单后进入的状态此时座位是锁定状态已支付用户完成支付座位变为已售已取消用户在待支付状态下主动取消订单座位需要自动释放已过期用户在 15 分钟内没有支付系统自动取消订单释放座位已完成电影放映结束一段时间后订单自动或手动设为已完成其中待支付 - 已过期这个转移你说起来简单实现起来要注意要么用定时任务轮询过期的待支付订单要么在下单时记录一个过期时间用户进入订单详情时判断是否已过了支付截止时间并更新状态。我在实际项目中用的办法是简单轮询后面会讲具体怎么写。订单明细表联表查询的核心用来记录订单里包含哪几张票字段名类型说明idBIGINT PK主键order_idBIGINT订单IDsession_idBIGINT场次IDseat_idBIGINT座位IDrow_noINT排号冗余字段方便前端显示column_noINT列号冗余字段为什么明细表里要冗余排号和列号因为前端展示订单信息时如果明细表只存 seat_id你就要去 join 座位表再查一次排号和列号。多一次联表没必要直接把排号列号冗余到明细表查询效率高逻辑也简单。这就是典型的空间换时间思路答辩时可以提一下。4. 核心功能实现与关键代码逻辑4.1 用户登录与手机号获取微信小程序的登录流程和传统用户名密码登录不一样它不需要你设计注册页面。用户打开小程序前端调用 wx.login() 获取 code然后传递给后端后端再向微信服务器发起请求换取 openid。这个流程要能够在答辩时非常流畅地讲出来。实际代码如下wx.login({ success: (res) { wx.request({ url: BASE_URL /api/user/login, method: POST, data: { code: res.code }, success: (resp) { if (resp.data.code 200) { wx.setStorageSync(userInfo, resp.data.data); } } }); } });注意新版微信对获取手机号的接口做了调整——从 2023 年开始通过button open-typegetPhoneNumber获取用户手机号需要小程序主体完成微信认证且必须使用企业主体注册的小程序个人开发者的小程序没有这个权限。所以如果你做毕设想实现获取手机号功能要么就用测试号模拟要么在后端写一个 mock 接口直接返回138xxxx8888然后在系统说明里写清楚正式上线时需通过微信官方接口申请。千万别自己编一套绕过微信认证的方式这就是不讲武德了也没有必要。4.2 影片列表与首页展示逻辑小程序首页的常见结构是顶部搜索框 轮播图 热映列表。轮播图的数据可以来自一个单独的 banner 字段也可以直接取评分最高的几部影片。影片列表接口我建议做一个分页 筛选 关键字搜索的通用接口。分页这个点很多毕设项目会忽略但没有分页的话数据量一上来页面就卡了。接口逻辑长这样GET /api/film/list?page1size10type喜剧keyword流浪后端用 MyBatis-Plus 分页插件实现前端用小程序的分页机制onReachBottom 触底时加载下一页isLoading 标志位防止重复请求hasMore 标志位判断是否还有更多数据。这套逻辑是通用的你在任何列表页都能用。前端列表页面还需要注意一个细节小程序 setData 不能频繁操作大数组。如果你一次性 setData 100 条数据页面会卡顿。正确做法是每次只 setData 新增的那一页数据用数组拼接的方式更新this.setData({ filmList: this.data.filmList.concat(newPageData), page: this.data.page 1, hasMore: newPageData.length 0 });4.3 选座页与座位锁定机制选座是整个系统最复杂的页面也是最容易出并发 bug 的地方要重点讲。小程序端选座页面的核心逻辑进入选座页向后端请求场次座位状态渲染座位图灰色代表已售/锁定白色代表可售用户点击座位座位高亮进入待选状态用户点击确认前端先在后端锁定座位调用 /api/seat/lock锁座成功后跳转到确认订单页面下单前检查座位是否仍被自己锁定防止多人抢座为什么要在用户点确认座位时先锁座而不是等用户下单时才检查座位因为看电影选座位是有心理预期的用户选了 5 排 6 座结果下单时提示该座位已被选走体验很糟糕。所以主流做法是用户临时选座后先占座给你 5~10 分钟的确认时间超过时间未下单则自动释放。锁座接口的数据库操作我用的是条件更新 影响行数判断的思路Transactional public boolean lockSeat(Long sessionId, Long seatId, Long userId) { // 原子更新只有 status 0可售时才允许改成 1锁定 int rows sessionSeatMapper.updateStatus( sessionId, seatId, 1, 0); return rows 0; }关键在 updateStatus 的 SQL 里加一个条件AND status 0这样在高并发下两个用户同时锁同一个座位时数据库只能让一个 update 成功另一个更新 0 行。这就是乐观锁的思想不依赖数据库行锁通过条件更新来实现并发控制。你写完这个逻辑在答辩时几乎必被问到并发问题这就算你答上来了。4.4 下单与支付流程的设计下单接口是业务逻辑最密集的地方一个标准的下单流程应该是这样的校验用户登录状态检验场次是否存在且未结束校验传入选中的座位列表是否都处于当前用户锁定状态计算订单总金额场次价格 × 座位数生成唯一订单号插入订单表和订单明细表更新场次座位状态锁定改为已售返回订单号和支付参数这个流程里步骤 3 和 7 是重点。步骤 3 要防止一种情况用户 A 锁了两个座位但其中一个座位被系统判定超时释放了此时 A 没重新锁座就直接下单不能让他下单成功。步骤 7 要在事务里完成保证订单插入成功的同时座位状态也更新成功否则会出现钱扣了座位没占上或者座位被占但订单没生成的问题。Spring Boot 里这个过程用一个 Transactional 注解就能搞定Transactional public Order createOrder(OrderCreateRequest req) { ListSessionSeat seats sessionSeatMapper.selectForUpdate(req.getSessionId(), req.getSeatIds()); // 校验所有座位都是锁定状态且锁定的 userId 是当前用户 for (SessionSeat seat : seats) { if (seat.getStatus() ! 1 || !seat.getLockUserId().equals(req.getUserId())) { throw new RuntimeException(座位状态异常请重新选座); } } // 计算金额、生成订单、更新座位... return order; }支付部分毕设阶段不要真的去接微信支付因为微信支付要求商户号、企业资质、签约流程个人开发者根本弄不了。标准做法是做一个模拟支付点击模拟支付按钮前端调支付接口后端把订单状态从待支付改为已支付座位状态从锁定改为已售。如果你想让系统看起来更真实可以加一个钱包余额支付的功能用户账户有余额下单时直接用余额支付。这样既模拟了支付流程又把 User 表里的 balance 字段用上了比纯模拟支付更有说服力。4.5 待支付订单超时释放的定时任务座位不能被无限期锁定否则别人想看都看不了。我设定的是 15 分钟未支付自动取消释放座位。实现方式用 Spring 的定时任务Scheduled(fixedDelay 30000) // 每30秒执行一次 public void releaseExpiredOrders() { ListOrder expiredOrders orderMapper.selectExpiredLockOrders(); for (Order order : expiredOrders) { // 取消订单释放座位 orderMapper.updateStatus(order.getId(), 2); sessionSeatMapper.releaseSeatsByOrderId(order.getId()); } }这个任务很简单但你要想清楚一个点释放座位和取消订单必须在一个事务里。只取消了订单但没释放座位那个坑就永远被别人占不到了只释放了座位但没取消订单用户会发现订单还在那点进去却已经查不到座位信息数据就对不上了。如果你在答辩时把这个定时任务的执行逻辑讲清楚老师会认为你考虑到了数据一致性这是加分项。5. 环境部署与联调实录5.1 本地环境搭建先列一下你需要准备的开发环境JDK 8 或 11Java 后端Maven 3.6MySQL 5.7 或 8.0微信开发者工具最新稳定版IntelliJ IDEA社区版就够用Navicat 或 DataGrip数据库可视化工具后端启动步骤# 1. 创建数据库 CREATE DATABASE cinema CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 2. 导入 SQL 脚本项目里自带的 cinema.sql 或类似文件 # 3. 修改 application.yml 的数据源配置 spring: datasource: url: jdbc:mysql://localhost:3306/cinema?useUnicodetruecharacterEncodingutf-8serverTimezoneAsia/Shanghai username: root password: 你的密码 # 4. 启动项目 mvn spring-boot:run启动成功后浏览器访问http://localhost:8080/doc.html如果你集成了 Swagger能看到接口文档页面Spring Boot 控制台也会打印启动成功的日志。5.2 小程序端连接后端接口这一步是大量新手翻车的地方。你数据库配了后端启动了小程序模拟器一看页面空白控制台报request:fail或者url not in domain list。原因分两类第一类域名校验问题。工具右上角详情 - 本地设置 - 勾选不校验合法域名。这是开发阶段必要的操作。但你要记住真机预览时真机上同样需要开启调试模式才不校验域名。如果你要做演示给别人看可以用真机预览模式 调试模式这样不需要域名也能跑。第二类localhost 和局域网 IP 的问题。小程序模拟器里请求http://localhost:8080没问题但真机上 localhost 指向的是手机自己不是你的电脑。必须在后端接口路径里改成你电脑在局域网里的 IPconst BASE_URL http://192.168.31.245:8080; // 用 ipconfig (Windows) 或 ifconfig (Mac) 查本机IP同时手机和电脑要连同一个 WiFi手机才能访问这台电脑上运行的 Spring Boot 服务。另外Windows 防火墙可能会拦截端口需要放行 8080 端口。后端代码里也要允许跨域访问。Spring Boot 下加一个配置类Configuration public class WebConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }5.3 演示数据怎么准备空数据库跑起来页面一片空白演示效果很差。建议你在库里提前准备一套演示数据5~10 部电影海报图片直接放外部链接比如豆瓣的图片地址注意防盗链问题也可以自己找图床2~3 个影院每个影院 2~4 个影厅座位图从 6 排 × 8 列到 10 排 × 12 列不等每个影厅排 8~15 个场次覆盖今天、明天、后天三个日期订单数据手动造几单不同状态的待支付、已支付、已取消都有这样你在我的订单页面能展示所有状态演示数据要像真实的影片名称别写什么影片1影片2评分别全是 9 分场次间隔要有逻辑一场 120 分钟的电影下一场最早得在 2 小时后。像真数据演示效果就好数据全是假的老师一眼就看穿。6. 常见坑点排查与答辩准备6.1 高频问题排查速查表我把自己做这个项目时踩过的坑和指导过的学生常遇到的问题整理成了一张表你遇到类似情况直接对号入座现象原因解决办法小程序显示不在以下 request 合法域名列表中未配置合法域名或未勾选不校验域名开发阶段勾选不校验合法域名上线前配 HTTPS 域名真机预览接口报 500后端接口异常或 IP 不通先用电脑浏览器访问接口看返回值确保手机电脑同一网络请求能通但数据是空的数据库没导入 SQL 或查错库检查 application.yml 的 url 是否有useSSLfalse小程序图片加载不出来图片是 HTTP 地址或域名不在白名单用 HTTPS 图片地址开发阶段使用不校验合法域名选座页面出现该座位已被选走座位锁定状态被其他用户占用了刷新座位状态正常业务逻辑下单成功但订单列表看不到user_id 没对上检查订单表里的 user_id 是否是当前登录用户的 ID支付后座位还是锁定状态事务没提交或状态更新逻辑写错了检查 order 表和 session_seat 表是否在同一事务里更新定时任务没有执行缺少 EnableScheduling 注解在启动类上加 EnableScheduling分页数据重复前端没判断 hasMore 继续请求加 hasMore 标志无更多数据时不触发请求接口报 404Controller 路径和前端请求路径不一致对照接口清单逐条核对路径6.2 答辩前必须弄懂的几个为什么毕设答辩最怕的是项目是你跑的别人源码但是老师一问原理你就蒙。以下是这个项目里几乎必问的问题你提前把答案背熟为什么用微信小程序不用 App答微信小程序开发门槛低、不需要用户安装、适合电影院这种低频但刚需的场景后端技术栈是统一的 Java 生态小程序端用原生框架即可满足需求。数据库为什么有订单表和订单明细表两张表答一个订单包含多张票多人购票订单表存支付相关的整体信息明细表存每一张票对应的座位信息是典型的一对多关系。这样设计可以方便地支持部分退票虽然毕设可能没做和座位查询。座位并发是怎么防的答场次座位表有一个 status 字段锁座和下单都用条件更新的方式SQL 里带上WHERE status 0数据库同一个时刻只能让一个事务更新成功。加事务保证多张座位同时操作的原子性。你这个模拟支付和真实微信支付有什么区别答真实微信支付需要商户号流程是前端调 wx.requestPayment 拉起支付面板后端接收支付回调校验签名然后更新订单状态。毕设里用模拟支付走的是同一个业务状态流转逻辑只是没有真实的微信支付交互可以把支付回调的部分用接口模拟掉。图片资源放在哪答开发阶段用公网 HTTP/HTTPS 图片链接或后端静态资源目录正式上线需要配 CDN 或云存储。小程序有个限制业务域名和 downloadFile 合法域名都要配。6.3 毕业论文结构参考论文结构不需要我在这里面面俱到但开题和毕设说明书里一般要有绪论背景、国内外研究现状注意别在知网上搬太多写清楚为什么做这个题就好需求分析功能性需求 非功能性需求性能、安全、易用性系统设计总体架构图、技术选型说明、功能模块图、数据库 E-R 图和表结构系统实现每个核心模块的实现思路 核心代码片段 运行截图系统测试测试环境、功能测试用例表、结论截图素材要提前准备小程序首页、影片详情、选座页面、订单详情、后端 Swagger 接口文档、数据库表结构图。演示的时候先把模拟器窗口调好、数据准备好别现场手忙脚乱。这个项目做完我最大的体会是毕业设计不一定非要多高深但一定要主线清晰、逻辑自洽。你不需要做一个猫眼出来你需要的是一个能跑通浏览影片 - 选座 - 锁定 - 下单 - 支付 - 出票全流程的系统外加一整套说得清楚的设计理由。把每个模块的为什么想明白了代码是自己写的也好、参考的也好答辩的时候你都能从容应对。最后再分享一个对我帮助很大的习惯把接口文档、数据库表结构、核心代码逻辑、运行截图按模块整理成一个项目说明文档从第一天写代码就开始维护。等到写论文的时候你会发现这个文档几乎就是论文的技术实现部分。不用临时翻代码回忆自己写过什么论文进度会快一倍。
返回列表