简介:本资源是一套完整的大学生就业服务平台微信小程序毕业设计项目,面向计算机相关专业本科生及Java全栈初学者,解决课程设计、毕设选题与小程序+后台一体化开发实践需求。压缩包含1270个文件,涵盖231个PNG/SVG图片资源、175个JS逻辑脚本、136个Vue组件、127个Java后端类、86个WXML页面结构与88个WXSS样式文件,完整覆盖小程序前端、Spring Boot后台及MySQL数据库三层架构,总大小20.02MB。已有90人学习下载,适合快速掌握微信小程序登录态管理、简历投递流程、企业面试邀约机制及管理员多角色权限控制等核心业务实现。资源提供可直接运行的前后端源码、Navicat兼容的SQL建表文件、Eclipse/IDEA工程配置说明及bat一键启停脚本,目录中可见IndexHeader.vue、update-password.vue等模块化组件与install/run/build三阶段批处理文件,结构规范,便于教学复现与二次开发。
1. 这不是又一个“毕设模板”,而是一套能跑通「学生投递→企业筛选→双向反馈」闭环的微信小程序就业平台实战方案
你手头拿到的这个压缩包,表面看是「微信小程序毕业设计」+「Java+MySQL+LW」的常规组合,但真正拉开差距的,是它把高校就业场景里最常被忽略的三个断点——学生简历不被识别、企业HR手动筛表效率低、投递后无状态追踪——用可落地的技术链串起来了。它不是纯前端展示页,后端用 Spring Boot 做了简历解析接口(支持 PDF/Word 提取关键字段),小程序端做了离线缓存投递草稿、带时间戳的投递记录页,MySQL 表结构里甚至预留了「企业查看次数」「学生撤回标记」「三方协议状态」字段。适合两类人:一是大三下刚开题、卡在「怎么让毕设看起来不像静态页面」的学生;二是想快速验证就业类小程序 MVP 的校内开发者——它不追求高并发,但每一步操作都有真实业务映射,比如「学生修改简历后,已投递岗位自动触发状态更新通知」这种细节,恰恰是答辩时最容易被追问、也最能体现工程思维的地方。别急着解压,先看清它解决什么问题,再决定怎么用。
2. 搭建前必读:为什么选这套技术栈?Spring Boot + 微信小程序 + MySQL 的协同逻辑
2.1 后端为什么必须用 Spring Boot 而非纯 Java Servlet?
很多学生用原生 Java 写后端,结果卡在跨域、JSON 解析、文件上传、JWT 鉴权上,最后答辩被问「你怎么保证登录态不被劫持」直接哑火。Spring Boot 的价值不在「写得快」,而在它把就业平台最关键的三个安全与交互环节封装成了可配置模块:
spring-boot-starter-security自动处理登录态校验,配合微信小程序code2Session返回的openid做唯一绑定,避免学生账号被冒用;spring-boot-starter-data-jpa让简历字段(如「期望城市」「技能标签」「实习经历」)能直接映射成实体类属性,省去手写 JDBC 的 SQL 拼接风险;spring-boot-starter-web内置 Tomcat,调试时直接mvn spring-boot:run就能启动,不用配 Apache 或 Nginx——这对没接触过运维的学生极其友好。
提示:源码中
application.yml里数据库密码是明文password: 123456,实际部署前必须改成环境变量或加密配置,否则会被扫描工具抓取。
2.2 小程序端为何放弃云开发,坚持调用自建 Java 接口?
云开发看似省事,但就业平台有硬性需求:企业端需对接校方教务系统学籍数据(如专业、年级、GPA),而云开发无法直连校内 MySQL。本方案用小程序wx.request()调用 Java 后端/api/student/bind接口,传入学生学号和验证码,后端通过 JDBC 查询教务库(需额外配置druid数据源),验证通过后才允许完善简历。这步看似多此一举,实则是答辩时证明「系统有真实业务约束」的关键证据——评委一眼看出你不是在模拟,而是在适配真实管理流程。
2.3 MySQL 表结构设计里的「就业业务语义」
打开schema.sql,注意三张核心表的字段命名逻辑:
t_student表中resume_status TINYINT DEFAULT 0不是简单标「0=未提交,1=已提交」,而是按就业中心规范定义:0=草稿,1=待审核,2=审核通过,3=已推荐,4=已签约;t_company_job表的apply_deadline DATETIME字段带索引,因为首页「最新岗位」列表需按该字段倒序查,避免全表扫描;t_apply_record表的is_withdrawn TINYINT DEFAULT 0和withdraw_time DATETIME NULL是为「学生反悔机制」留的伏笔——某学生投递后发现公司不招本专业,点击撤回,后端需同时更新状态并记录时间,供就业中心统计「无效投递率」。
这些字段名不是随便起的,它们对应高校《毕业生就业工作管理办法》里的术语,答辩时提到「我们按校级管理规范设计状态机」,比说「我用了 MySQL」有力得多。
3. 本地跑通最小闭环:从解压到看到「我的投递」列表的 7 步实操
3.1 解压与目录结构认知:先找到「能动」的三个根目录
压缩包解压后,你会看到三个平行文件夹:
backend_springboot:Java 后端,含pom.xml和src/main/java/com/example/job包;miniprogram:微信小程序源码,含app.js、pages/index/index.js和project.config.json;database:含schema.sql(建表)、init_data.sql(插入测试企业/学生数据)。
注意:不要试图用 HBuilder 或其他 IDE 打开整个压缩包——它不是一个项目,而是三个独立子系统。每个目录都要单独处理。
3.2 启动后端:改三处配置,5 分钟让接口活起来
进入backend_springboot目录,用 IDEA 或 VS Code 打开,重点修改以下三处(路径基于 Spring Boot 2.7.x,若版本不同请核对pom.xml中<spring-boot.version>):
# 1. 修改数据库连接(application.yml) spring: datasource: url: jdbc:mysql://localhost:3306/job_platform?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username: root password: your_mysql_root_password # ← 改成你本地 MySQL 密码// 2. 修改微信 AppID 和 AppSecret(com.example.job.config.WechatConfig.java) public class WechatConfig { public static final String APP_ID = "wx1234567890abcdef"; // ← 替换为你公众号后台的 AppID public static final String APP_SECRET = "your_app_secret_here"; // ← 替换为对应密钥 }// 3. 关闭 Spring Security 默认登录页(WebSecurityConfig.java) // 注释掉 .formLogin() 整段,只保留: http .authorizeHttpRequests(authz -> authz .requestMatchers("/api/**").permitAll() // 所有 API 免登录校验(调试用) .anyRequest().authenticated() );保存后,右键JobPlatformApplication.java→Run 'JobPlatformApplication.main()'。控制台出现Tomcat started on port(s): 8080即成功。此时访问http://localhost:8080/api/test应返回{"msg":"backend ok"}。
3.3 初始化数据库:执行 SQL 脚本的顺序不能错
MySQL 客户端(如 Navicat 或命令行)中:
- 新建数据库
job_platform,字符集选utf8mb4; - 先执行
schema.sql(建表+索引); - 再执行
init_data.sql(插入 3 家测试企业、5 名测试学生、10 个岗位)。
关键细节:
init_data.sql中学生密码是BCryptPasswordEncoder加密后的密文(如$2a$10$...),不是明文。若你手动 INSERT 学生记录,必须用 BCrypt 工具生成密文,否则登录会失败——这是新手最常翻车的点。
3.4 小程序端配置:改两个文件,让「我的」页面显示真实数据
用微信开发者工具打开miniprogram目录,修改:
// app.js 第 12 行:把 base_url 指向你的本地后端 App({ globalData: { base_url: 'http://localhost:8080/api/' // ← 确保是 http,不是 https } })// pages/my/index.js 第 35 行:替换 openid(调试用,正式上线需调 wx.login) onLoad() { this.setData({ openid: 'oABC1234567890DefghIJKLMN' }) // ← 用 init_data.sql 里某个学生的 openid }保存后点击「编译」,首页顶部导航栏应显示「我的」,点击进入后,「投递记录」列表会调用/student/apply/list?openid=xxx,返回 JSON 数据并渲染。若列表为空,检查控制台是否报net::ERR_CONNECTION_REFUSED——说明后端没启动,或base_url端口写错。
4. 避坑指南:那些让答辩老师皱眉、让代码跑不通的 5 个血泪细节
4.1 现象:小程序登录后跳转到空白页,控制台报fail net::ERR_CERT_AUTHORITY_INVALID
原因:开发者工具默认启用「不校验合法域名」,但若你在project.config.json中手动添加了https://yourdomain.com到request合法域名,而本地后端是http://localhost:8080,微信会强制拦截 HTTP 请求。
解决:删除project.config.json中所有request合法域名字段,或确保只保留localhost(微信不支持,所以必须删)。调试阶段一律用http://localhost:8080,上线前再配 HTTPS。
4.2 现象:企业端上传招聘简章 PDF,后端报java.lang.NoClassDefFoundError: org/apache/poi/xwpf/usermodel/XWPFDocument
原因:源码依赖了 Apache POI 解析 Word,但pom.xml中<artifactId>poi-ooxml</artifactId>版本是 4.1.2,而 JDK 17 不兼容——POI 4.x 需 JDK 11,JDK 17 需升级到 5.2.4+。
解决:修改pom.xml,将 POI 相关依赖全部升级:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.4</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.4</version> </dependency>然后mvn clean install重装依赖。
4.3 现象:学生修改简历后,企业端「待处理简历」列表没更新,刷新页面才出现
原因:小程序端pages/resume/edit.js中,保存按钮的wx.request()成功回调里,只执行了wx.showToast(),没触发this.onPullDownRefresh()或this.onLoad()重新拉数据。
解决:在success回调末尾加:
success: (res) => { wx.showToast({ title: '保存成功' }) // ← 补这一行,强制刷新当前页 this.onLoad() }4.4 现象:MySQL 插入中文乱码,学生姓名显示为???
原因:不仅schema.sql要指定CHARSET=utf8mb4,MySQL 服务端配置my.cnf也必须设置:
[client] default-character-set = utf8mb4 [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci重启 MySQL 服务后,再执行SHOW VARIABLES LIKE 'character_set%'确认所有值均为utf8mb4。
4.5 现象:企业发布岗位时,选择「工作城市」下拉框为空
原因:miniprogram/app.js中cityList数组是空的,而源码本应从/api/common/city接口动态加载,但该接口在后端CommonController.java中被注释掉了。
解决:取消CommonController.java中@GetMapping("/city")方法的注释,并确保其返回格式为:
[{ "code": "0010", "name": "北京市" }, { "code": "0210", "name": "上海市" }]小程序端pages/company/job-add.js的onLoad里会自动调用此接口填充下拉框。
5. 让毕设脱颖而出的 3 个进阶动作:从「能跑」到「像真的一样」
5.1 给学生端加「智能匹配度评分」:用关键词 TF-IDF 实现简易推荐
就业平台的核心价值不是信息陈列,而是降低匹配成本。源码中backend_springboot/src/main/java/com/example/job/service/ResumeService.java已预留calculateMatchScore()方法,但逻辑为空。我们可以用极简方式补全:
// 在 ResumeService.java 中 public double calculateMatchScore(String studentSkills, String jobRequirements) { // 学生技能字符串(如"Java,Python,MySQL")和岗位要求(如"Java开发,熟悉MySQL,有实习经验") String[] stuWords = studentSkills.toLowerCase().split("[,,\\s]+"); String[] jobWords = jobRequirements.toLowerCase().split("[,,\\s]+"); int matchCount = 0; for (String stu : stuWords) { for (String job : jobWords) { if (stu.trim().length() > 1 && job.trim().length() > 1 && stu.trim().equals(job.trim())) { matchCount++; } } } return Math.round((double) matchCount / Math.max(stuWords.length, jobWords.length) * 100); }然后在StudentController.java的getApplyList()方法中,循环每条投递记录时调用:
record.setMatchScore(resumeService.calculateMatchScore( student.getSkills(), job.getRequirements() ));小程序端pages/my/index.wxml中,给每条记录加一行:
<text class="match-score">匹配度 {{item.matchScore}}%</text>这个评分不追求算法精度,但能让评委直观看到「系统在思考」。答辩时可以说:「我们用轻量级关键词重合度替代复杂模型,既满足实时性,又便于解释匹配逻辑——毕竟就业中心更关心‘为什么推这个岗位’,而不是 F1 值。」
5.2 为企业端加「一键导出投递名单」Excel:用 Apache POI 避免 CSV 编码坑
学生投递后,企业 HR 最常做的操作是导出 Excel 发给部门负责人。源码中CompanyController.java有/export/applicants接口,但返回的是 CSV,中文会乱码。改成 Excel 更稳妥:
@GetMapping("/export/applicants") public void exportApplicants(HttpServletResponse response, @RequestParam Long jobId) throws IOException { List<Applicant> list = applicantService.findByJobId(jobId); XSSFWorkbook workbook = new XSSFWorkbook(); XSSFSheet sheet = workbook.createSheet("投递名单"); // 表头 String[] headers = {"姓名", "学校", "专业", "学历", "联系电话", "投递时间"}; XSSFRow headerRow = sheet.createRow(0); for (int i = 0; i < headers.length; i++) { headerRow.createCell(i).setCellValue(headers[i]); } // 数据行 int rowNum = 1; for (Applicant a : list) { XSSFRow row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(a.getStudentName()); row.createCell(1).setCellValue(a.getSchool()); row.createCell(2).setCellValue(a.getMajor()); row.createCell(3).setCellValue(a.getEducation()); row.createCell(4).setCellValue(a.getPhone()); row.createCell(5).setCellValue(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(a.getApplyTime())); } response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); response.setHeader("Content-Disposition", "attachment; filename=投递名单_" + System.currentTimeMillis() + ".xlsx"); workbook.write(response.getOutputStream()); }小程序端pages/company/job-detail.js中,给「导出名单」按钮绑定:
exportList() { wx.downloadFile({ url: getApp().globalData.base_url + 'company/export/applicants?jobId=' + this.data.job.id, success: (res) => { if (res.statusCode === 200) { wx.openDocument({ filePath: res.tempFilePath, showMenu: true }) } } }) }Excel 导出比 CSV 多写 30 行代码,但能避开「用 Excel 打开 CSV 中文变乱码」这个经典玄学问题,也让企业端显得更专业。
5.3 用小程序「订阅消息」替代站内信:让关键节点不被错过
源码中通知靠前端轮询/api/student/notice/unread,体验差且耗资源。微信订阅消息是更优解。以「企业查看简历」为例:
- 小程序端
pages/resume/detail.js中,当学生点击「查看谁看过我」时,先调用wx.requestSubscribeMessage获取模板 ID 权限; - 后端
CompanyService.java中,当企业用户点击「查看简历」时,触发:
// 调用微信订阅消息接口(需配置 token 和 aesKey) String templateId = "your_template_id_from_wechat_official_account"; String accessToken = wechatService.getAccessToken(); String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken; Map<String, Object> data = new HashMap<>(); data.put("thing1", Map.of("value", "您的简历已被【腾讯科技】查看")); data.put("time3", Map.of("value", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date()))); data.put("phrase2", Map.of("value", "已查看")); Map<String, Object> payload = Map.of( "touser", studentOpenid, "template_id", templateId, "data", data ); // 发送 POST 请求...订阅消息需要在微信公众平台申请模板,但「企业查看」、「投递成功」、「面试邀请」这三个模板审核通过率极高。加上它,你的系统就从「被动查询」升级为「主动触达」,答辩时讲「我们用订阅消息构建闭环通知体系」,比说「我写了弹窗提示」高级得多。
我带过几届学生做这类毕设,最深的体会是:评委不关心你用了多少技术,而关心你是否理解技术背后的业务约束。比如 MySQL 字段名为什么叫resume_status而不是status,比如为什么宁可多写 20 行 POI 代码也要导出 Excel 而不是 CSV——这些细节才是区分「抄模板」和「真工程」的分水岭。别急着堆功能,先把「学生投一份简历,企业收到一条通知,学生看到一个匹配度数字」这个最小闭环跑稳、讲透、调通。希望帮到你。
本文还有配套的精品资源,点击获取