很多计算机专业的学生大四上学期就开始头疼毕业设计选题了,找了一圈发现题目不是太简单(比如做个静态网页)就是太难(比如搞什么深度学习平台)。如果你正在找“既能过盲审、又好实现、还能在答辩时拿得出手”的题目,“基于微信小程序的学生信息管理系统”确实是个很经典也很稳的选择。它既不用像做后台管理系统那样弄一堆复杂的权限流程,又能靠小程序这块招牌体现出你用了移动端、云开发或者接口对接这些当前比较主流的技术点。
我自己前后带过好几届毕设,也帮着改过不少类似项目,这个选题最大的好处就是“麻雀虽小五脏俱全”。登录鉴权、角色划分、数据增删改查、列表搜索、图表统计,这些在真实企业项目里天天用的功能它全都有,而且每一块都可以在校期间独立验证。哪怕你之前只是会用点 HTML 和 Java,跟着这篇文章的思路走一遍,也能把它做成一个逻辑完整、能演示、能答上来的系统。这篇文章我就按我实际带项目的经验,把从需求拆解到答辩演示的完整路径给你捋一遍,包括哪些坑必须避开、哪些功能是评委眼中的加分项,全部讲透。
1. 项目整体设计与技术选型思路
1.1 核心需求拆解:先画清楚边界再动手
很多同学毕设翻车不是因为代码写不出来,而是需求根本没想清楚就开始写。学生信息管理系统听起来很简单,但如果你把“学生信息”和“管理”这个概念放大,它可以包含学籍档案、选课退课、成绩录入、教师信息、班级管理、宿舍分配、考勤统计等等一大堆东西。你如果全做,那工作量足以让你从九月忙到次年四月,关键是你还做不完。
我建议你按“角色—功能”矩阵来拆需求。这个系统一般就三种用户:学生、教师、管理员。学生能查看个人信息、查看自己的成绩、修改部分个人资料;教师能录入和修改成绩、查看所带班级的学生列表;管理员拥有最高权限,可以做学生的增删改查、教师账号管理、班级和专业信息维护、数据统计。这个矩阵画出来之后,你会发现功能其实就四个大的模块:登录鉴权、学生信息管理、成绩管理、数据统计。后面所有开发都围绕这四块进行,不跑偏。
我见过不少同学在系统里硬塞一个“课程表”功能,说是看到别人的系统里有。结果课程表牵扯到排课算法,短期内根本做不完,最后还是砍掉了。毕设不是越炫越好,而是“你的系统能完整解决一个真实场景里的小闭环”,这个闭环跑通了,答辩就赢了一半。
1.2 技术栈选型对比:别盲目堆新技术
技术栈的选择直接决定你后续开发的顺利程度。我之前看过一个同学的代码,用了 Spring Cloud 微服务架构来做毕设,理由是“简历上好看”,结果服务注册、负载均衡、远程调用这些概念他还没完全吃透,光是调试环境就花了一个多月,最后系统没跑起来,差点延毕。
你选技术栈的时候要记住一个原则:老师考察的是你有没有掌握一项技术的核心用法,而不是你堆了多少名词。目前主流的搭配有两种:
第一种:微信小程序原生前端 + Spring Boot + MyBatis Plus + MySQL。这是最稳妥的组合。小程序端用微信官方原生语法,不引入 uni-app 这类框架,能避开很多底层兼容问题;后端的 Spring Boot 是 Java 方向学生的基本盘,资料也多,遇到问题一搜就有答案。
第二种:微信小程序原生前端 + uni-app 或 Taro。如果你的前端功底不错,想一套代码多端复用,可以选择 uni-app,把代码编译成小程序端和 H5 端。不过这会让项目多一层编译链路,调试时要多留意小程序端的样式兼容问题。
我的建议很明确:如果你求稳,直接选第一种;如果你想要加分项,可以在第一种基础上把“云开发”加上,用微信云开发的数据库和云函数来代替自建后端,这样你甚至不用自己买服务器。不过要注意,云开发的免费额度有限,如果数据量大或者请求频繁,注意控制一下成本。我倾向于推荐你自建后端,因为答辩时老师更认可你能讲清 HTTP 接口和数据库表结构,这是计算机专业的基本功。
2. 环境准备与项目初始化
2.1 开发环境搭建:从注册到真机预览
这块看起来琐碎,但卡住的概率反而最高。你需要准备这几样东西:一个微信小程序账号(个人或企业主体都行)、微信开发者工具(稳定版即可)、以及后端开发环境(JDK 1.8 及以上、Maven、MySQL 5.7 及以上)。
说两个容易出问题的地方。
第一个是 AppID。小程序开发和网页开发不一样,它必须有 AppID 才能调用 wx.request 发请求。你可以先用测试号,但测试号不支持获取手机号等部分高级能力,所以我建议你直接用个人主体注册一个小程序账号。注册流程不复杂,用身份证信息验证就行,注意每个身份证只能注册一个小程序账号,不要填错。
第二个是开发者工具的“不校验合法域名”选项。本地调试时,你的后端跑在http://localhost:8080,而小程序正式环境要求所有请求域名必须是 HTTPS 并且在小程序后台配置白名单。你在开发阶段可以在“详情—本地设置”里勾选“不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书”,这样本地联调就不会被拦截。很多同学不知道要勾这个,结果第一晚就被报错劝退了。
后端项目我用 Spring Boot 来演示。你创建一个 Spring Boot 项目,引入spring-boot-starter-web、mybatis-plus-boot-starter、mysql-connector-java、lombok这些依赖。数据库连接配置写在application.yml里,基本长这样:
server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/student_system?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: yourpassword jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: auto这里的serverTimezone=Asia/Shanghai一定别丢,否则数据库连接经常会报时区错误。jackson的日期格式化也很重要,如果你不配,返回给前端的时间格式就是一串数字(时间戳),前端还得自己转换一遍,非常麻烦。
2.2 微信小程序端的页面框架与底部导航栏配置
小程序端的初始化相对简单。你在开发者工具里新建项目之后,系统会自动生成pages、utils、app.js、app.json、app.wxss这些核心文件。app.json是全局配置文件,你在里面注册页面路径、窗口样式和底部导航栏。
底部导航栏我建议这样配置:登录后进入系统,主页面分三块,分别是“首页”“功能页”“我的”。首页放统计数据入口和快捷功能,功能页放学生列表和成绩管理入口,我的页面放个人信息和退出登录。配置写在tabBar字段里,注意pagePath必须对应真实存在的页面路径,iconPath和selectedIconPath可以自己用 PNG 图片,大小限制在 40kb 以内。
这里有一个很典型的坑:你用一个非 tabBar 页面作为启动页(比如登录页),但是又在app.js的onLaunch里直接跳转,会导致页面栈混乱。正确做法是把登录页注册在pages/login/login,首页和功能页注册为 tabBar 页面,然后在小程序启动时通过wx.reLaunch切换页面。reLaunch会清空所有页面栈,能避免返回键跳到登录页的尴尬情况。
顶部导航栏的高度问题近期讨论也比较多。不同型号手机上,微信小程序的胶囊按钮位置不一样,导致导航栏的可视高度不同。如果你想做沉浸式自定义导航栏,可以在页面级别的json文件里配置"navigationStyle": "custom",然后自己计算状态栏高度和导航栏高度。状态栏高度可以通过wx.getWindowInfo()获取statusBarHeight,菜单按钮的位置可以通过wx.getMenuButtonBoundingClientRect()获取。
我实测过,小程序的个性化顶部导航栏在 iPhone 和 Android 上差异很明显。如果你只想先把功能做完,建议不要一开始就做自定义导航栏,先用系统默认的导航栏,等核心功能稳定了再考虑。毕竟你是做毕设,不是做商业产品,把时间花在核心业务上收益更高。
3. 登录鉴权与权限控制的完整实现
3.1 微信登录与获取手机号:新版接口有变化
登录是整个系统的入口,也是最容易被答辩老师追问的模块。
在小程序中实现登录,有两种常用方案。一种是传统的wx.login获取 code,然后传给后端,后端用 code 换取 openid。另一种是用“手机号快速验证组件”,直接获取用户手机号。
我重点说一下手机号获取的新变化。微信官方在 2023 年之后调整了接口规范,老的getPhoneNumber直接返回明文手机号的方式已经被逐步收紧,现在推荐的是开放平台提供的“手机号快速验证”组件。你需要在小程序后台申请开通这个能力,然后在前端页面使用<button open-type="getPhoneNumber" bindgetphonenumber="handlePhoneNumber">。在回调事件里,你拿到的detail.code是一个动态令牌,需要把它传给后端,后端再调用微信接口换取手机号。
这个流程有一个容易踩的坑:很多同学以为前端可以直接用encryptedData解密,结果不需要。正确链路是:
handlePhoneNumber(e) { if (e.detail.code) { wx.request({ url: 'http://localhost:8080/api/login/phone', method: 'POST', data: { code: e.detail.code }, success: (res) => { // 后端返回登录凭证 token wx.setStorageSync('token', res.data.data.token); } }); } }后端的处理逻辑里,你的 controller 接收 code 之后,用HttpClient或RestTemplate去调用微信接口地址,带上你自己的 appid 和 secret 换取手机号和 openid。然后在数据库的用户表里按 openid 查用户,如果没查到就自动注册一个新账号,默认角色为“学生”;查到了就直接更新最后登录时间。登录成功后用 JWT 生成一个 token,返回给前端。后续所有需要权限的请求,前端都在 header 里带Authorization: Bearer <token>。
整个链路你面试的时候也说得上话:这是标准的 OAuth 2.0 授权码模式在微信场景下的简化应用,你把 code、openid、token 生命周期这几句话讲清楚,老师就知道你真的跑通过。
3.2 三层角色权限:后端拦截器 + 前端条件渲染
角色权限在毕设里属于“中等难度、高分值”的模块。很多同学做权限的时候喜欢在后端每个接口里硬编码判断,比如if(role.equals("admin")),这样虽然能用,但代码一多就乱成麻。
我建议这样做:用 Spring Boot 的拦截器(HandlerInterceptor)统一拦截请求,校验 token 解析出的用户角色。你写一个AuthInterceptor类,重写preHandle方法。在这个方法里,你从请求头里取 token,解析出用户 ID 和角色,放进去ThreadLocal或 request attribute 里,后续 controller 直接取用。
角色与接口的对应关系,在配置里写清楚:
registry.addInterceptor(authInterceptor()) .addPathPatterns("/api/**") .excludePathPatterns("/api/login/**", "/api/register/**");然后你可以自定义一个@RequireRole("admin")注解,加在部分 Controller 方法上,拦截器里检查用户角色是否满足注解要求。这样写的好处是扩展性很强,以后再加角色只要改注解就行,不用改动每个接口的逻辑。答辩的时候如果老师问“权限是怎么做的”,你答“基于拦截器 + 自定义注解实现了角色级访问控制”,这一个点就足够体现你的工程能力。
前端也要做配合,不能只靠后端。你在app.js里把用户信息和角色存到全局变量里,然后在 wxml 中用wx:if判断按钮是否显示。比如“新增学生”按钮只有管理员能看到,学生和教师角色就不渲染。需要注意,前端隐藏只是体验优化,真正的安全保障在后端,这个逻辑不要搞反了。答辩的时候就算老师问“前端把按钮显示出来能不能绕过权限”,你就可以直接答“前端只是做了展示层控制,后端每一层接口都做了鉴权”。
登录还有一个小细节要注意,就是 session 过期。JWT 如果过期时间太长会有安全隐患,太短用户体验又差,我建议设成 7 天,小程序端在请求返回 401 时,自动清掉本地 token 并跳转登录页。这个逻辑你在wx.request的封装方法里统一处理。
4. 学生信息管理的增删改查与核心页面实现
4.1 数据库表设计:字段不要拍脑袋拍出来
学生信息管理是本系统的核心模块,数据库表设计直接决定你后续写代码是舒服还是难受。我把表和核心字段列一下,你可以照着建。
学生表(student)核心字段:id、学号(stu_no)、姓名(name)、性别(gender)、出生日期(birth_date)、班级ID(class_id)、专业ID(major_id)、入学年份(enroll_year)、手机号(phone)、邮箱(email)、状态(status,0表示在读,1表示离校)、创建时间(create_time)、更新时间(update_time)。
班级表(class)核心字段:id、班级名称(class_name)、年级(grade)、班主任ID(teacher_id)、所属专业ID(major_id)。
专业表(major)核心字段:id、专业名称(major_name)、所属学院ID(college_id)。
教师表(teacher)核心字段:id、工号(teacher_no)、姓名(name)、性别(gender)、手机号(phone)、所属学院ID(college_id)。
成绩表(score)核心字段:id、学生ID(student_id)、课程ID(course_id)、平时成绩(usual_score)、考试成绩(exam_score)、总评成绩(final_score)、学期(semester)。
你一定注意几个细节。学号和工号这类业务编号一定要加唯一索引,否则同一个学号录入两次,系统就乱套了。外键关系不用在数据库层面强制建,MyBatis Plus 里用逻辑关联就行了,这样删数据的时候不会因为外键约束被卡住。时间字段统一用datetime,Java 端用LocalDateTime映射,配合 Jackson 的日期格式化,前端拿到的时间字符串就很规整。
我在一个项目里见过同学把学生照片直接以 base64 字符串形式存在数据库里,一张照片几十 KB,一张表存几百条数据,数据库瞬间膨胀。正确做法是前端把图片上传到服务器或云存储,数据库只存图片的访问 URL。答辩的时候老师问到数据存储的合理性,你就可以提这一点,算是加分项。
4.2 列表页:搜索、分页与下拉刷新
学生列表页面是一个信息管理系统里最核心的界面。你需要实现的功能包括:按姓名、学号、班级搜索,分页加载,下拉刷新,以及列表数据的渲染。
小程序端的页面结构我用原生语法写。onLoad生命周期里调用列表接口,onPullDownRefresh里做下拉刷新,onReachBottom里做触底加载下一页。这部分逻辑不难,但有一个需要注意的地方:分页参数要维护好,当前页码和每页条数要在 data 里保存,避免请求返回后页面数据错乱。
前端发请求时,用wx.request封装一层。我通常把baseUrl配置在一个单独的文件里,比如config.js。后续所有请求都用封装好的request方法,自动带 token、统一处理错误状态。这样做的好处是代码干净,项目结构清晰,答辩的时候老师翻代码也容易看懂。
后端的列表接口用 MyBatis Plus 的Page对象分页,查询条件用 LambdaQueryWrapper 拼接:
LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>(); if (StringUtils.hasText(query.getName())) { wrapper.like(Student::getName, query.getName()); } if (StringUtils.hasText(query.getStuNo())) { wrapper.eq(Student::getStuNo, query.getStuNo()); } if (query.getClassId() != null) { wrapper.eq(Student::getClassId, query.getClassId()); } wrapper.orderByDesc(Student::getCreateTime); Page<Student> page = studentMapper.selectPage(new Page<>(query.getPageNum(), query.getPageSize()), wrapper);这个方法能模糊搜索姓名/学号、按班级精确筛选,并按创建时间倒序排列。返回给前端的结构我用统一 Result 类包装,比如Result.ok(data)返回{ code: 0, data: {...}, msg: "success" }。统一返回结构的好处是前端处理响应非常统一,不用每个接口单独判断。
4.3 新增与编辑学生信息:表单校验的细节
新增学生信息的页面是一个表单页。字段可能包括姓名、学号、性别、出生日期、班级、专业、入学年份、手机号、邮箱。这些字段里,学号、姓名、班级、专业一般是必填项,其他可以选填或选填后加校验。
前端表单校验我建议分两层。第一层是表单级校验,比如学号不能为空、手机号格式是否正确、邮箱格式是否正确。原生小程序没有像 Vue 里el-form那样现成的校验组件,自己写一个校验函数也不难。或者你直接用微信小程序官方自带的form组件里required属性,结合button的form-type="submit"来收集数据。
第二层是后端校验,用@Validated注解配合实体类上@NotBlank、@Email等注解实现。这一层很多人会忽略,结果就是前端绕过校验直接传脏数据,系统报错。后端校验一定要做,答辩如果老师刻意传几个异常参数,你系统能稳得住就是加分。
新增和编辑走同一个接口还是两个接口?我建议分开:新增走POST /api/student,编辑走PUT /api/student/{id}。RESTful 风格更清晰。后端更新时,要注意只更新非空字段,避免覆盖已有值。MyBatis Plus 的updateById默认会忽略 null 字段,正好符合要求,你只要确认下全局配置里没有把字段策略设成always。
我遇到过一个问题:学生修改出生日期之后,页面显示的时间和数据库存的时间差了 8 个小时。这个问题的根源是时区不一致。解决方式就是在 JDBC 连接串上加上serverTimezone=Asia/Shanghai,以及后端返回 JSON 时用统一的GMT+8时区。这个坑我在前面已经提过,这里再强调一次是因为它出现的频率实在太高了。
4.4 删除与批量操作:别一删到底
删除学生信息在教学管理系统里属于敏感操作,如果学生已经存在成绩,直接物理删除会导致成绩表里的数据变成孤儿数据。稳妥的方案是逻辑删除:表里加一个deleted字段,删除操作本质上是一次更新,把deleted置为 1。
MyBatis Plus 对逻辑删除支持得很好,你只需在实体类的deleted字段上加@TableLogic注解,后续所有查询都会自动带上deleted=0条件。这个方案最大的好处是你的业务代码完全不用改,框架自动帮你过滤掉已删除的数据,而且数据还在库里,可以恢复。
管理员通常还需要一个“已删除数据恢复”的功能。你可以单独写一个接口,查询时用Wrapper的last("and deleted = 1")绕过逻辑删除条件,实现恢复或彻底清理。这一步做出来,整个系统的数据层设计就比较完整了。
批量删除也是常见需求。我建议不要用delete by ids这种一次性传数组的方式,而是前端循环调用单条删除接口,或者后端用deleteBatchIds,注意控制事务边界。加@Transactional注解确保要么全部成功,要么全部失败,避免删到一半报错留下脏数据。
5. 成绩管理与数据可视化
5.1 成绩录入与计算规则
成绩管理模块是教师角色的核心功能。一个老师登录后,应该能看到自己教的学生列表,然后录入成绩。成绩字段包括平时成绩、考试成绩、总评成绩。总评成绩不一定是手工填的,往往是一个加权公式,比如平时成绩占 30%、考试成绩占 70%。
这个公式怎么实现呢?我建议在新增接口里,后端接收平时成绩和考试成绩,自动计算总评并存储。这样避免了前端每次手动算,也保证了规则统一。计算逻辑写在 service 层,不写在 controller 里,保证接口层只负责参数校验和数据传递:
BigDecimal finalScore = usualScore.multiply(new BigDecimal("0.3")) .add(score.multiply(new BigDecimal("0.7")));用BigDecimal算浮点数,不要用double,是因为double在计算 0.1 + 0.2 时会得到 0.30000000000000004 这种结果,直接展示给用户会对成绩精确性造成影响,数据库存精度高的金额和分数,都应该用 decimal 类型。
成绩查询页面还要支持按学期筛选、导出功能。导出用 EasyExcel 或 POI 都能实现。答辩的时候展示一个“导出 Excel”功能,视觉效果很好,老师会觉得你的系统已经有点真实产品样了。
5.2 数据统计:学生数量、专业分布和成绩分析图
数据统计模块的加分意义大于实际业务意义,但它能直观展示系统的价值。
我用小程序端引入echarts-for-weixin来画图,这个插件是 ECharts 官方团队为小程序适配的版本,提供了ec-canvas组件。你只需要在 wxml 里引入ec-canvas,在 JS 里配置 option 就可以了。
比较常用的图表有几种。学生人数按专业分布的柱状图或饼图;每个学期平均成绩的折线图;班级成绩对比的横向柱状图;男女生比例饼图。后端接口把统计数据查出来,拼成前端需要的结构:
{ "categories": ["软件工程", "计算机科学", "网络工程"], "values": [120, 90, 60] }统计数据用 SQL 聚合查询很高效。举例,统计各专业学生人数:
select m.major_name, count(s.id) as student_count from student s left join major m on s.major_id = m.id where s.deleted = 0 group by m.major_namecount统计的时候注意被逻辑删除的数据不要混进来。如果你在实体类上配置了@TableLogic,自定义 SQL 里不会自动带上deleted条件,需要手动加。这个小坑我踩过,统计出来的数总是跟列表页对不上,查了半天才发现是逻辑删除的数据没过滤。
5.3 首页工作台:让数据一目了然
首页工作台可以作为登录后的默认落地页。展示内容建议包含:欢迎语(比如“欢迎回来,张三老师”)、今日待办(比如待审核的班级信息)、统计数据卡片(学生总数、教师总数、本学期录入成绩人数)、以及待处理的低学生平均分预警。
这个页面的设计思路,参考了真实后台管理系统的“仪表盘”,虽然开发量不大,但整体完成度和答辩展示效果能提升很多。数据和接口都是现成的,你只需要在首页onLoad时并行请求几个统计接口,然后渲染数据卡片即可。建议用Promise.all并行请求,避免串行等待拖慢页面响应速度。
6. 常见问题排查与答辩经验
6.1 开发中高频踩坑清单
我直接给你列一个我实战中遇到频率最高的坑清单,每一条都是真金白银的教训。
第一,小程序真机预览白屏。大概率是app.json里注册的页面路径不对,或者首屏页面里用到了不存在的组件。解决方法是用开发者工具的“编译模式”逐页排查,看看 console 有没有报错。
第二,wx.request请求超时或失败。一是检查域名是否在小程序后台配置白名单,二是检查本地设置的“不校验合法域名”有没有勾上,三是确认后端 CORS 跨域配置正确。很多同学用 Spring Boot 时会漏掉跨域处理,前端请求就发不过去,报一个“url not in domain list”,其实不是域名问题,是浏览器跨域拦截。解决方式是在后端加一个 CorsFilter 配置类。
第三,token 无效导致的循环跳转。如果 token 过期后前端每次都发起请求,每次请求都返回 401,然后前端每次都跳登录页,就会形成循环。处理办法是在收到 401 时先判断当前页面是否是登录页,是则不跳转,不是则清空缓存再跳转。
第四,分页数据重复或丢失。原因是前端维护了页码参数,但下拉刷新时没有把页码重置为 1。正确逻辑是:onPullDownRefresh时重置 pageNum=1,onReachBottom时 pageNum++,并且保证两次请求不会同时进行,否则会出数据错乱。你可以用一个loading布尔值做防重入。
第五,图片上传失败。小程序wx.chooseMedia选图后,要用wx.uploadFile上传,需要走一个独立的接口,不能和普通表单一起提交。上传成功后再把返回的 URL 拼到表单数据里提交。如果用的云开发,就调用wx.cloud.uploadFile。
6.2 “我改了一个下午,还是找不出 bug 怎么办”
这个问题基本每个写毕设的人都会遇到。我给你一个我自己的排查顺序参考。先看后端日志,确认请求有没有到达 Controller。没有到达说明问题出在拦截器或者路由配置;到达了但返回报错,就顺着 Service 层往下一层层看。前端先看 Network 面板里请求状态和响应体,不要一上来去翻页面代码。
如果是数据库相关的报错,用下面的思路快速定位:把日志里打印的 SQL 复制到 Navicat 里手动执行,看能不能执行成功。能成功就说明 SQL 没问题,问题出在参数传递;不能成功就检查表名、字段名、数据类型。
如果页面渲染不对,优先看 console 的报错信息,小程序端报错信息一般比较明确,比如“Cannot read property ‘xxx’ of undefined”,这通常意味着接口返回的数据结构和页面里取用的字段名不一致。你用console.log打印一下接口返回值,一眼就能看出来。
6.3 答辩演示的准备与加分话术
很多同学系统做得不错,但答辩时要么紧张讲不清,要么只演示不解释,结果被老师问住了。答辩演示的核心逻辑是“场景驱动 + 冲突引入”。
我建议你准备一个 8 到 10 分钟的演示脚本。开场不急着点功能,而是先交代背景:“我做一个面向高校日常教务管理场景的小程序端管理系统,解决学生信息分散、查询效率低的问题。”然后沿角色主线走一遍:先用管理员身份登录,演示学生信息录入编辑和删除;切换教师账号,演示成绩录入和统计图表;最后用学生账号,演示查看成绩和个人信息。
容易被追问的点和对应的回答思路,我提前给你列一下。
问:为什么选微信小程序?答:相对于传统网页,小程序有免安装、即点即用的特点,更符合移动端办公场景,而且微信生态内分享方便,适合高校日常使用。
问:安全性怎么保证?答:登录用 code 换手机号,通过 openid 识别用户,后端用 JWT 管理登录态;每个接口经过拦截器统一鉴权,关键操作有角色校验;数据库存密码(如果有密码场景)用 BCrypt 加密。
问:为什么用逻辑删除不用物理删除?答:物理删除会丢失数据和关联关系,逻辑删除可以保留可追溯的历史数据,通过 deleted 字段过滤,并且 MyBatis Plus 原生支持,不影响查询性能。
答辩的时候最忌讳的是你只介绍“我用了什么技术”,而讲不清“为什么用这个技术、解决了什么问题”。每次引入一个技术点,都按“背景—方案—收益”这个小结构来讲,几句话就能把技术在真实场景中的价值讲明白。
这里多说一句:答辩前一定提前准备一个“一页纸速查表”,把你系统里每个接口的 URL、方法、参数、返回值写下来放在手边。老师现场提问时你一边查一边答,沉着很多。
7. 一点个人体会与扩展建议
我带过的同学里,真正能把毕业设计做得像样的人,大多不是技术最强的,而是规划最清楚的。拿到题目先花一周做需求分析和表结构设计,再花三周做后端接口,再花两周做小程序端页面,最后留一周联调和打磨演示,这个过程我全程看着是很顺的,反而是那些想着“先写代码再说”的人,后期反复改需求、改表结构,进度一拖再拖。
这个系统后续想扩展的话,方向非常多。比如加一个消息通知模块,成绩录入后自动推送到学生端;接入人脸识别做考勤打卡;或者把成绩数据对接校园门户做统一认证。你现在把基础框架打好,后续想往哪个方向走都方便。
如果让我再给你一个比较中肯的建议,那就是多写注释,尤其是 controller 层每个接口的功能注释和 service 层核心方法的逻辑注释。代码写得像菜市场一样乱,答辩老师翻几页就失去了兴趣;代码清晰规整,哪怕功能简单点,也都愿意多给几分印象分。自己再回头维护,也不至于对着三个月前的代码发呆。祝你顺利。