ARTICLE DETAIL

资讯详情

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

SSM+微信小程序实验室预约系统毕业设计源码实战与避坑指南

SSM+微信小程序实验室预约系统毕业设计源码实战与避坑指南 简介基于SSM框架和微信小程序开发的实验室管理毕业设计项目后台页面采用Vue数据库使用MySQLJDK1.8运行环境可在Eclipse、MyEclipse、STS、IDEA等常见开发工具中直接编译导入适合计算机相关专业学生用于毕业设计选题、需求分析与功能扩展。项目完整实现管理员与用户双角色体系管理员具备个人中心、用户信息管理、教学实践管理、学生签到管理、设备信息管理、设备预约管理、课程表管理、预约课程管理、预定实验室管理、实验室信息管理与系统管理用户端可查看设备信息、课程表信息完成签到和实验室预约。资源包共1219个文件压缩后约62.68MB文件构成以png图片、js脚本、svg图标、vue页面、java源码、json配置、wxss与wxml小程序编译文件为主同时包含sql数据库脚本、doc论文与开题报告文档、mp4讲解视频、bat环境启动脚本及多个框架配置文件。除完整源码与数据库脚本外还提供环境工具包、同框架项目安装教程内容预览中可见后台管理页面组件、Vue页面备份和构建运行脚本便于本地部署、局部修改与知识梳理。目前已有107人学习下载适合需要一套可运行、可讲解、可扩展的毕设项目的初中级开发者。1. 毕业设计选“实验室管理小程序SSM”到底在交付什么临近开题很多人拿到“毕业设计java实验室管理微信小程序ssm源码含文档含教程”这类工程时第一反应是解压、导入、跑起来截图交差。真这么做大概率卡在环境上。这个题目交付的不只是源码而是三样东西一个SSM架构的Java后端、一个原生微信小程序前端、一份能支撑论文的数据库设计和接口说明。它解决的场景很典型——实验室信息展示、在线预约、管理员审核、用户管理正好覆盖CRUD、状态流转、前后端联调这些毕业设计必考的点。适合Java方向、想快速拿出可运行项目并能在答辩时把原理讲清楚的本科生。反直觉的是源码本身不难难的是把JDK版本、Tomcat、小程序域名、真机预览这些工程问题理顺。2. SSM和小程序的分工先看三层架构再决定先改哪端2.1 为什么是SSM而不是Spring Boot答辩时怎么解释SSM是Spring、SpringMVC、MyBatis三件套的缩写这个组合在2018年前后的Java Web课程里几乎是标准配置毕业设计选它不是因为技术新而是因为它每一层都“看得见”。Spring管的是对象创建和事务SpringMVC管的是请求路由MyBatis管的是SQL映射。三者的边界非常清楚答辩时老师问“一个请求进来之后经历了什么”你可以从Tomcat到DispatcherServlet到Controller到Service到Mapper到MySQL一条线讲下来。框架核心职责对应工程里的位置SpringIoC容器、事务管理applicationContext.xml、Service实现类SpringMVCURL路由、参数绑定spring-mvc.xml、ControllerMyBatisSQL映射、结果集封装mybatis-config.xml、Mapper接口与XML有人问为什么不用Spring Boot我的习惯回答是Spring Boot的自动配置确实省事但它把Bean装配、DispatcherServlet初始化这些关键步骤都包成了黑匣子。答辩老师追问“starter是怎么生效的”你得去讲条件注解和自动配置类反而把简单问题复杂化。SSM的配置是显式写在XML里的一行行能指给老师看。翻过springframework源码和mybatis源码的人在讲MapperProxy和SqlSessionTemplate时明显比只背概念的人讲得实在。这个选择还有一个现实原因这套源码里的教程和文档大多按SSM分层结构写。你换成Spring Boot文档对不上代码结构也得推倒重来毕业设计的时间耗不起。JDK版本也要留意老SSM工程一般配JDK 8和Tomcat 8.5最稳JDK 11以上偶尔会遇到cglib代理或者JAXB相关的兼容问题。2.2 小程序端和后端的分工边界谁管页面谁管数据很多人在改源码时犯的第一个错是把业务逻辑写在小程序端。比如预约时间冲突判断直接用JavaScript在前端比后端接口只做插入。这样演示时没问题但答辩老师一问“两个用户同时提交同一个实验室怎么办”前端判断就站不住脚了。小程序端该管的只有三件事页面渲染、表单校验、通过wx.request发请求。后端负责的是接口鉴权、业务规则、数据持久化。一个完整请求的链路是页面onLoad发起wx.request后端Controller接收参数Service做业务判断Mapper操作MySQL结果封装成JSON返回小程序端拿到后setData刷新页面。这条链路必须能用自己的话讲明白这是答辩的基本盘。工程目录一般长这样拿到源码先对照着看不要急着改代码lab-wx/ ├── backend/ # SSM后端工程 │ ├── pom.xml │ └── src/main/ │ ├── java/ │ │ └── com/example/lab/ │ │ ├── controller/ # 接口层接收小程序请求 │ │ ├── service/ # 业务层预约规则、审核逻辑 │ │ ├── mapper/ # MyBatis Mapper接口 │ │ ├── entity/ # 数据表对应实体类 │ │ └── common/ # Result封装、工具类 │ └── resources/ │ ├── applicationContext.xml │ ├── spring-mvc.xml │ ├── mybatis-config.xml │ ├── jdbc.properties │ └── mapper/*.xml # SQL语句 ├── frontend/ # 微信小程序原生工程 │ ├── app.js │ ├── app.json │ ├── pages/ │ │ ├── login/ │ │ ├── index/ # 实验室列表 │ │ ├── reserve/ # 预约提交 │ │ └── admin/ # 管理员审核 │ └── utils/request.js # wx.request封装 └── doc/ # 论文、数据库脚本、操作教程前端和后端之间只通过HTTP接口通信所以接口返回格式要统一。常见做法是封装一个Result对象包含code、message、data三个字段小程序端判断code等于200才继续处理。这样Controller里无论查询成功还是失败返回结构都是一致的。2.3 最小可运行工程结构拿到源码先看这几个文件不要一上来就点启动按钮先把四个关键文件找到pom.xml、jdbc.properties、spring-mvc.xml、app.js。pom.xml决定依赖能不能拉下来jdbc.properties决定数据库能不能连上spring-mvc.xml决定接口能不能扫到app.js决定小程序请求地址对不对。!-- pom.xml 关键依赖版本老工程踩坑重灾区 -- properties jdk.version1.8/jdk.version spring.version5.1.8.RELEASE/spring.version mybatis.version3.4.6/mybatis.version /properties dependencies !-- SpringMVC 依赖 -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version${spring.version}/version /dependency !-- MyBatis 与 Spring 整合包 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version1.3.2/version /dependency !-- MySQL 驱动 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version5.1.47/version /dependency /dependencies版本这里最容易翻车。Spring 5.x配合JDK 8没问题但MyBatis 3.4.x和mysql-connector-java 5.1.x这套组合是老工程默认配置。如果你把MySQL驱动换成8.0.x连接串里的驱动类名要改成com.mysql.cj.jdbc.Driverjdbc.properties也得加serverTimezone参数不然直接报“The server time zone value”错误。看app.js时重点看globalData里的baseUrl。开发工具里跑可以写localhost真机预览必须改成电脑的局域网IP否则手机请求打到手机自己身上。这个细节我会在第五章细说但拿到源码第一件事就把它记住能省半天排错时间。3. 把源码跑起来后端启动、小程序预览、数据库初始化三步3.1 后端导入IDEA并启动SSMMaven清理与Tomcat配置SSM后端不是直接双击就能跑的主类它需要部署到Tomcat里。用IDEA打开backend目录后先确认两件事IDEA里配置的JDK是1.8Maven用的是本地仓库还是阿里云镜像。老工程依赖如果拉不下来多半是Maven中央仓库访问太慢在settings.xml里加aliyun镜像能解决。这一步做完再动代码。# 在backend目录下执行先规避本地仓库里的脏jar包 mvn clean install -DskipTests -Dfile.encodingUTF-8这条命令的作用是清理target目录并重新打包skipTests跳过测试以减少时间file.encoding固定编码防止Windows中文乱码。如果你的机器上还没配过java环境变量打开cmd执行java -version确认一下没有就先去装JDK 8并配置JAVA_HOME这是最常被忽略的前置步骤。打包成功后在IDEA里配置Tomcat Server选择Tomcat 8.5Deployment里添加Artifact选war exploded方式Application context填/lab。这里有个细节war和war exploded差别在于解压方式毕业设计调试选war exploded因为它支持热部署改完Java代码不用重启整个Tomcat。启动后看到“Server startup in [xxx] milliseconds”就算成功了。最容易在这里踩的坑有两个一是端口被占用Tomcat默认8080你机器上可能跑着别的服务在server.xml里改成8081或者8082就行二是启动时提示“Unable to compile class for JSP”这是JSP编译器依赖缺失检查Tomcat的lib目录里有没有jasper.jar。3.2 小程序端用微信开发者工具打开AppID、域名与真机预览后端启动之后用微信开发者工具导入frontend目录。导入时有两个选择用测试号或者用你自己的小程序AppID。测试号不需要注册能覆盖登录、请求、本地存储这些常用能力但拿不到手机号授权因为获取手机号要求企业主体且已完成微信认证。源码里如果带了手机号登录功能你就得注册一个小程序账号个人主体无法开通这个接口这是认证费用和主体类型决定的不是代码能绕过的。导入后第一件事打开app.js把baseUrl改成后端的实际地址// app.js 小程序入口 App({ globalData: { // 开发工具里可以用localhost真机预览必须用电脑局域网IP baseUrl: http://192.168.1.100:8080/lab }, onLaunch() { // 启动时检查本地是否有登录缓存的token const token wx.getStorageSync(token) if (!token) { // 没有token就跳转登录页避免直接进首页时报401 wx.reLaunch({ url: /pages/login/login }) } } })登录逻辑缓存在本地是常见做法但不能只依赖是否存在token来判断登录态因为token可能过期。后端在返回Result时如果code是401小程序端要重新执行登录流程。这个我在第四章会展开。接下来是开发工具里的关键配置在“详情-本地设置”里勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”。这个选项只对开发工具生效真机预览时如果不做任何配置网络请求还是会因为域名不是HTTPS而失败。所以你需要把baseUrl从localhost改成电脑在局域网里的IP手机和电脑连同一个Wi-Fi才能真机调试。3.3 数据库初始化与账号体系打通jdbc连接串才是第一道坎SSM工程一般都带SQL脚本在doc目录下找.sql文件。用Navicat或者命令行执行前先建好数据库。这里有个细节数据库名、用户名、密码必须和jdbc.properties里的配置一致否则启动Tomcat时Service初始化报错但报错信息往往很晚才出现容易被误解成“项目本身有问题”。-- 实验室表毕业设计最核心的数据表 CREATE TABLE lab ( id int(11) NOT NULL AUTO_INCREMENT COMMENT 实验室主键, name varchar(100) NOT NULL COMMENT 实验室名称, location varchar(200) DEFAULT NULL COMMENT 位置, capacity int(11) DEFAULT 30 COMMENT 容量, status tinyint(4) DEFAULT 1 COMMENT 1可用 0停用, image varchar(255) DEFAULT NULL COMMENT 展示图, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT实验室信息表;字符集最好选utf8mb4而不是utf8因为utf8在MySQL里最多存3字节用户昵称里如果带了emoji表情直接插入失败。engine用InnoDB支持事务预约提交时要保证扣减名额和插入记录在同一个事务里。改jdbc.properties时连接串一定要写成这样jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/lab?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse jdbc.usernameroot jdbc.password123456serverTimezone不写MySQL 5.6以上版本会在获取连接时直接报时区异常useSSLfalse是为了避免本地开发时SSL握手警告。账号体系这里源码通常会有一个初始化管理员账号的SQL比如admin/123456但密码多半是MD5加密后的字符串。你想在数据库里手动插数据时别直接写明文密码去entity里看密码字段的类型和对应用户登录时怎么校验的照着已有数据的格式生成密文。4. 核心预约流程代码走读登录、列表、状态流转4.1 预约流程的表设计与状态机一张预约表撑起整个业务实验室预约是整个题目的业务核心大部分功能都围绕预约表的增删改查展开。预约表要包含谁约的、约哪个实验室、什么时间段、当前状态。状态用int字段比varchar更合适排序快、占空间小而且可以用状态机把整个业务流转讲清楚。CREATE TABLE reservation ( id int(11) NOT NULL AUTO_INCREMENT, lab_id int(11) NOT NULL COMMENT 实验室ID, user_id int(11) NOT NULL COMMENT 预约用户ID, reserve_date date NOT NULL COMMENT 预约日期, start_time time NOT NULL COMMENT 开始时间, end_time time NOT NULL COMMENT 结束时间, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 0待审核 1已通过 2已拒绝 3已取消, reason varchar(255) DEFAULT NULL COMMENT 使用用途/拒绝原因, create_time datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT预约记录表;status字段建议统一用数字字典前端用常量映射0待审核、1已通过、2已拒绝、3已取消。为什么这么设计因为答辩老师一旦问“预约冲突怎么控制”你可以回答在Service层做两件事先查该实验室同一时间段是否有status1的预约有就拒绝再把“查空档”和“插入预约”放到同一个事务里配合预约表加唯一索引兜底。空档查询SQL通常是这样的-- 查询某实验室在指定时间段是否已被预约 SELECT COUNT(*) FROM reservation WHERE lab_id #{labId} AND reserve_date #{date} AND status 1 AND start_time #{endTime} AND end_time #{startTime}这段SQL的判断逻辑是时间段重叠判断不是简单的等值查询。很多新手写成start_time #{startTime}漏掉了别人预约从9点到11点、你预约10点到12点这种交叉情况。4.2 微信小程序登录获取手机号code换openid的完整链路微信小程序登录获取手机号是这套系统的入口同时也是最容易卡住的功能。登录链路分两步第一步wx.login拿到临时code后端拿code去微信接口换openid和session_key第二步用户点“手机号快捷登录”按钮前端拿到加密数据后端解密获取手机号。很多源码把两步混在一起导致个人主体小程序根本跑不通。// pages/login/login.js handleLogin() { wx.login({ success: (res) { const code res.code wx.request({ url: ${getApp().globalData.baseUrl}/user/login, method: POST, data: { code }, success: (resp) { if (resp.data.code 200) { wx.setStorageSync(token, resp.data.data.token) wx.reLaunch({ url: /pages/index/index }) } } }) } }) }code这个参数只能用一次有效期五分钟。后端拿到code后调用https://api.weixin.qq.com/sns/jscode2session带上appid和secret返回openid和session_key。后端要做的不是把openid直接扔给前端而是用它查用户表新用户自动注册老用户直接登录然后生成一个自己的token返回给小程序。token可以简单用UUID也可以把userId和过期时间拼起来做签名毕业设计用UUID足够。手机号按钮需要单独处理一定要用button组件配合open-typegetPhoneNumber不能用普通input让用户输手机号微信审核会拒绝。拿到手机号后按源码里的方式解密如果源码用的是老接口getPhoneNumber的encryptedData方式需要把session_key一起传过去。这一步在个人主体小程序里测试不了因为接口权限没开放所以演示时建议做一个“账号密码登录”兜底避免答辩现场手机号登录失败。4.3 实验室列表与预约提交Controller到Mapper的调用链实验室列表是首页默认页接口设计要考虑分页和状态过滤不然实验室一多一次性返回全部数据会让小程序端渲染卡顿。Controller层要写得薄只做参数接收和结果封装业务逻辑下沉到Service。// com/example/lab/controller/LabController.java Controller RequestMapping(/lab) public class LabController { Autowired private LabService labService; // 实验室分页列表 RequestMapping(/list) ResponseBody public Result list(RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer size, RequestParam(required false) String keyword) { return labService.pageList(page, size, keyword); } }RequestParam(defaultValue 1)是防止小程序端没传page导致空指针keyword用required false允许不传。ResponseBody把返回的Result对象自动序列化成JSON注意Result实体类里要有getter/setter否则Jackson序列化出来是空对象。预约提交接口要做的校验比列表多当前用户有没有登录、实验室是否存在、时间段是否合法、是否与已有预约冲突。这些放在Service层串行检查// com/example/lab/service/impl/ReserveServiceImpl.java Transactional(rollbackFor Exception.class) public Result submitReserve(ReserveDTO dto, Integer userId) { // 1. 参数合法性结束时间必须晚于开始时间 if (dto.getEndTime().before(dto.getStartTime())) { return Result.error(结束时间不能早于开始时间); } // 2. 冲突检测同一实验室同一时间端已有审核通过的预约 int count reserveMapper.checkConflict(dto); if (count 0) { return Result.error(该时间段已被预约); } // 3. 插入新预约状态为待审核 Reserve reserve new Reserve(); BeanUtils.copyProperties(dto, reserve); reserve.setUserId(userId); reserve.setStatus(0); reserveMapper.insert(reserve); return Result.success(); }Transactional注解放在Service实现类上意思是checkConflict和insert要么都成功要么都失败。这里有个坑如果MySQL表不是InnoDB引擎事务是不生效的所以前面建表时强调engineInnoDB。BeanUtils.copyProperties可以少写几行setter但要求两个类的字段名完全一致字段名对不上时它会静默跳过你会看到插入的数据缺字段排查时先检查这一步。5. 避坑SSM小程序联调常见的6个问题5.1 真机预览时request网络请求失败的3个原因现象微信开发者工具里接口调得通数据渲染正常一用真机预览就报request:fail页面空白。原因通常是三个中的一个baseUrl写了localhost真机上localhost指向手机自身小程序真机环境默认要求域名备案且必须是HTTPS企业主体小程序还校验域名白名单不在白名单直接拦截。解决开发阶段先把baseUrl改成电脑的局域网IP手机和电脑连同一个路由器确保防火墙放行8080端口。用“不校验合法域名”选项只能让开发工具放行真机预览依然受限所以局域网IP是当下最快的解法。正式上线的话需要买一台服务器、备案域名、配HTTPS证书再把域名加到小程序后台的request合法域名列表里。日常调试时可以用Charles抓包看请求到底发到了哪个地址确认是不是域名配置问题。运行环境域名要求常见配置微信开发者工具无勾选不校验合法域名真机预览开发局域网IP可用baseUrl改192.168.x.x正式上线HTTPS且已备案配置服务器、小程序后台白名单5.2 顶部导航栏高度适配自定义导航栏的测量陷阱现象小程序页面用了自定义导航栏后在iPhone 14 Pro上标题明显偏上甚至被状态栏盖住在普通安卓机上却正常。原因导航栏设置为custom之后系统不再帮你预留状态栏高度而不同机型的状态栏高度和胶囊按钮位置都不一样。如果你在app.json里写了navigationStyle: custom就必须自己计算导航栏高度。很多人写死一个44px在非全面屏上看着没问题一到刘海屏就露馅。解决用微信官方API动态获取胶囊按钮位置再算出导航栏高度放到全局变量里供每个页面使用。// utils/navbar.js const getNavBarInfo () { const windowInfo wx.getWindowInfo() const menuButton wx.getMenuButtonBoundingClientRect() // 胶囊按钮顶部到状态栏底部的距离乘以2就是上下留白总量 const navBarHeight (menuButton.top - windowInfo.statusBarHeight) * 2 menuButton.height return { statusBarHeight: windowInfo.statusBarHeight, navBarHeight, menuButton } } module.exports { getNavBarInfo }拿到navBarHeight后在自定义导航栏组件的style里设置高度而不是在页面里写死。有一个常被忽略的点安卓和iOS的状态栏高度不同微信开发者工具里模拟的是默认机型所以必须以真机为准。改完这个工具函数后把app.js的globalData里存一份所有页面在onLoad时读取不要每个页面重新计算。5.3 微信小程序单选框与表单校验的类型坑现象预约表单里有一个radio-group选择“预约用途”用户选“实验课”后提交后端一直说缺少用途参数。原因radio-group的bindchange事件里e.detail.value拿到的是字符串比如1。而后端接口用Integer接收前端又在data里定义了purpose: 0作为初始值。提交时直接传data对象字符串1传到Java层类型转换在某些SSM配置下会直接失败或者被转成null。这是很典型的微信小程序单选框类型坑因为radio的value天然是字符串。解决在bindchange回调里手动转换类型再存到data中。// 预约表单页 onPurposeChange(e) { // radio的value是字符串后端要Integer这里必须转换 this.setData({ purpose: parseInt(e.detail.value, 10) }) } onSubmit() { const { purpose, date, startTime, endTime } this.data // 提交前做非空校验避免空表单直接打到后端 if (!purpose || !date || !startTime || !endTime) { wx.showToast({ title: 请完整填写预约信息, icon: none }) return } wx.request({ ... }) }同理表单里的日期和时间选择器返回的也是字符串提交前要么统一parseInt要么在Controller里用String接收再手动转换。用String接收是最省事的但答辩时会显得不够严谨。更好的做法是前端把所有id类字段都转成数字后端统一用Integer双端都清爽。5.4 数据库时间字段与Java Date的8小时时差现象预约记录提交成功后数据库里存的时间比页面显示的时间少了8个小时。比如页面上选的10:00数据库里变成02:00。原因MySQL连接串里没有指定serverTimezone驱动用了默认时区而Tomcat所在机器用的可能是UTC导致JDBC在转换时间时偏移了8小时。还有一种情况是JSON序列化时Jackson把Date序列化成带时区的字符串小程序端解析时又按UTC解析一次。解决统一时区配置分两层处理。第一层jdbc.properties连接串加serverTimezoneAsia/Shanghai第二层SpringMVC的Jackson配置里设置日期格式和时区// spring-mvc.xml 中配置消息转换器 bean idjacksonObjectMapper classcom.fasterxml.jackson.databind.ObjectMapper property namedateFormat bean classjava.text.SimpleDateFormat constructor-arg valueyyyy-MM-dd HH:mm:ss/ /bean /property property nametimeZone valueGMT8/ /bean这里要说明的是timeZoneGMT8是Java层的序列化时区serverTimezoneAsia/Shanghai是JDBC连接层的时区两层保持一致。如果改了连接串还差8小时多半是Tomcat启动参数里设了user.timezone去catalina.sh或IDEA的VM options里检查把-Duser.timezoneUTC删掉。5.5 Tomcat部署路径与文件上传目录不一致现象管理员在后台给实验室上传图片开发环境显示正常。重启Tomcat或者把项目打包部署到服务器后图片全部404。原因源码里的上传代码可能写了绝对路径或者相对路径比如FileUtil.uploadFile(file, /upload)。IDEA里用war exploded方式部署时应用解压在一个临时目录图片写进了临时目录下的upload重启后这个目录被清理。部署到服务器后路径更不一样所以图片丢失。解决把上传目录从Web项目目录里拆出来配置成外部绝对路径再用SpringMVC的静态资源映射暴露出去。比如在服务器上建/data/lab/upload目录然后在spring-mvc.xml里加!-- 把外部目录 /data/lab/upload 映射到URL路径 /upload/** -- mvc:resources mapping/upload/** locationfile:/data/lab/upload//这样做的好处是重启Tomcat不会清空图片backup时直接备份整个目录就行。开发环境里如果不想建Linux路径可以在项目根目录建一个本地upload文件夹然后把location改成file:../upload/注意相对路径是相对于Tomcat的工作目录不是项目根目录这点容易绕晕。5.6 教程和源码对不上先按代码反推文档现象这是一条大概率遇到的坑。doc目录里的教程文档写的是“打开LoginController”但源码里根本没有这个文件文档里截图显示菜单叫“实验室预约”实际页面叫“预约管理”。原因同一份标题的资源包经过多次转手后源码可能被改动过而文档没同步更新。教程是给人写论文时参考逻辑用的不是给你逐行对照代码用的。解决先跑通项目再以源码为准反推文档。排查时用IDEA的全局搜索快捷键直接搜Controller或接口路径关键词比如搜/user/login就能快速定位login相关代码。写论文时如果文档描述和代码不一致以代码为准因为答辩老师现场看的是项目演示不会去读文档里的细节。另一个办法是看数据库表结构表字段能反推出大部分业务逻辑文档里没写的功能从表里都能看出来。6. 从“能跑”到“能答辩”验收清单与两个加分进阶源码跑通只是第一步答辩现场才是真正的考场。我习惯在答辩前按一条固定路径完整走三遍用户登录→查看实验室列表→提交预约→管理员登录→审核通过→刷新用户端看到预约状态变成已通过。这条路径要熟练到不用看页面也能操作。同时用Postman把所有接口的边界测一遍重点测空参数、错误ID、时间段重叠这三种情况别让老师随手点出一个500报错。验收时要检查的细节很多但优先级最高的是这几个后端日志没有Exception堆栈、数据库表里没有乱码数据、小程序在开发工具和真机两种环境都能正常请求、登录token过期后能自动跳回登录页。图表相关的辅助页面可以放在最后演示核心流程必须最先演示。两个加分进阶很值得做改动量不大但答辩效果明显。第一个是把预约冲突检测从Service里的手动SQL改成数据库唯一索引加乐观锁这个能体现出你对并发控制的理解。第二个是给管理员后台加一个简单的预约统计按周展示实验室使用率小程序端用ec-canvas画一个柱状图代码量不大但答辩时“可视化”三个字能直接吸引老师注意力。我自己的深刻教训是拿到源码后不要急着改业务逻辑先原样跑通、把每条接口和表字段的关系理清楚再动手。我第一次接到这类毕设工程时觉得登录逻辑太简陋直接加了密码加盐逻辑结果改崩了整个注册流程排错用了两天后来老老实实回滚到源码做增量修改。毕设源码的价值是给你一个稳定的基线在这之上做小步改动比推翻重建稳妥得多。希望这篇实操记录能帮你少走这几步弯路把精力花在能加分的地方比如把状态机讲清楚、把并发冲突演示出来这比折腾框架本身更能让答辩老师点头。本文还有配套的精品资源点击获取
返回列表