简介:这份资源是面向计算机相关专业学生与Java学习者的微信小程序毕业设计完整项目包,以大学生就业平台为主题,可直接用于毕设、课程设计或期末大作业。项目采用微信小程序开发工具搭配Java后端与MySQL数据库,实现了学生、企业、管理员三大功能模块:学生端涵盖招聘信息、简历、收藏与留言板;企业端支持招聘发布、求职信息、面试邀请管理;管理员端负责学生、企业、企业类型及系统管理。压缩包共1274个文件,约37.51MB,包含231个png、175个js、136个vue、127个java、88个wxss、86个wxml及2个sql脚本等,覆盖前端页面、后端逻辑与数据库脚本。资源内含项目源码、数据库脚本、运行教程、LW文档与演示录像,项目已通过严格调试,确保可运行。目前已有95人学习,适合需要完整实战案例与排错参考的读者。
1. 从一份 .rar 说起:大学生就业平台小程序到底交付了什么
每年三四月,计算机专业的群里总会冒出同一类消息:谁有大学生就业平台的微信小程序源码,最好带文档和演示视频。表面看是在找一份能交差的毕业设计,实际痛点很具体——招聘类小程序涉及学生、企业、管理员三种角色,登录鉴权、岗位检索、简历投递、状态流转这几块一个都不能少,自己从零写,光把微信登录和手机号获取跑通就得耗掉一周。这份标题里的 .rar 交付物,核心就是一套可运行的微信小程序前端加配套后端,覆盖就业平台最常见的岗位发布、简历管理、投递跟踪三条主线,外加一份能照着走的运行教程。它适合两类人:一是时间紧、需要快速跑通毕设全流程的学生,二是想拿一个完整业务闭环练手小程序全栈的开发者。下面我不谈这份压缩包里到底有几个文件,而是把这类就业平台从环境搭建到上线演示的完整路径拆开讲,你照着做,换成自己的数据也能跑起来。
2. 就业平台小程序的技术选型:为什么是原生加 Java 后端
2.1 前端为什么优先选微信小程序原生而不是 uniapp
拿到这类项目,第一个要定的是前端框架。热搜里 uniapp 微信小程序打包、uniapp 微信小程序开发者工具插件出现频率很高,说明不少人想一套代码多端跑。但就业平台这个场景,我一般建议先用微信小程序原生开发,理由有三条。第一,登录链路最短。微信小程序的wx.login换 code、后端换 openid、再拿手机号,这套流程原生 API 最直接,uniapp 中间多一层编译,出问题时排查链路变长。第二,岗位列表和简历表单大量用到scroll-view、picker、form这些基础组件,原生写法在开发者工具里调试所见即所得,不用等编译。第三,毕设答辩时老师看的是功能完整度,不是跨端能力,原生能把精力集中在业务上。当然,如果你明确要求同时出 H5 或 App,那 uniapp 更合适,但那是另一个选题了。
选原生之后,目录结构要心里有数。典型的小程序工程分pages(页面)、components(自定义组件)、utils(请求封装、时间格式化)、api(接口定义)四块。就业平台的页面至少包括:首页岗位推荐、岗位列表(带搜索和筛选)、岗位详情、简历编辑、投递记录、个人中心、企业端发布岗位、管理员审核。页面多,所以路由和 tabBar 要提前规划,别写到一半发现投递记录没地方放。
2.2 后端为什么常见 Java SpringBoot 加 MySQL
热搜里基于 java 的毕业设计选题、java 课程设计案例源码反复出现,就业平台这类管理系统用 Java 后端是主流。原因不复杂:SpringBoot 起步快,MyBatis 或 MyBatis-Plus 写 CRUD 省事,MySQL 建表直观,答辩时讲三层架构(Controller-Service-Mapper)也顺。具体到就业平台,后端要提供的接口大致分四组:认证类(登录、获取手机号、刷新 token)、岗位类(列表、详情、发布、下架)、简历类(创建、编辑、查询)、投递类(投递、撤回、状态更新)。每组接口对应一张或几张表,表设计我在下一章展开。
这里有个选型细节值得说:token 用 JWT 还是 session。小程序没有传统浏览器的 cookie 环境,JWT 更省心,前端把 token 存wx.setStorageSync,每次请求放 header。但 JWT 有个坑,过期时间设太长不安全,设太短用户老要重登,常见做法是 access token 两小时、refresh token 七天,刷新逻辑放在请求封装里自动处理。这个点后面避坑章节还会提。
2.3 数据库表设计:五张核心表撑起整个就业平台
就业平台的表不用多,但字段要想清楚。下面这张表是我做这类项目时常用的最小集合,你可以直接照着建,字段类型按 MySQL 8 写。
| 表名 | 作用 | 关键字段 |
|---|---|---|
| user | 存学生、企业、管理员三类账号 | id, openid, phone, role, nickname, avatar |
| job | 岗位信息 | id, company_id, title, salary, city, description, status |
| resume | 学生简历 | id, user_id, name, education, skills, experience |
| delivery | 投递记录 | id, job_id, user_id, resume_id, status, create_time |
| company | 企业信息 | id, user_id, name, industry, scale, verified |
user表的role字段用枚举值区分身份,比如 0 学生、1 企业、2 管理员,登录后前端根据 role 决定进哪个首页。delivery表的status是状态机核心,常见取值:已投递、已查看、邀面试、已拒绝、已录用,每次状态变更记一条日志更好,但毕设阶段直接改字段也能演示。job表的status控制上下架,管理员审核通过才置为可投递。建表时注意给openid、phone加唯一索引,给job_id、user_id加普通索引,否则数据一多列表查询会明显变慢。
3. 把项目跑起来:从导入源码到微信开发者工具出画面
3.1 后端启动:改配置、建库、跑 SQL
拿到源码后第一步不是急着开小程序,而是先把后端跑通,因为前端所有数据都依赖接口。假设后端是 SpringBoot 工程,操作顺序如下。
# 1. 用 IDEA 或 Eclipse 导入后端工程,等待 Maven 依赖下载完成 # 2. 找到 application.yml,改数据库连接spring: datasource: url: jdbc:mysql://localhost:3306/job_platform?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver改完配置,在 MySQL 里新建一个空库job_platform,字符集选utf8mb4,然后执行源码里带的.sql文件把表和初始数据建好。初始数据一般会塞一个管理员账号和几条测试岗位,方便你登录后立刻看到内容。启动类跑起来,控制台出现 Tomcat started on port 8080 就说明后端通了。这时候别关,后面小程序要连它。
参数说明:serverTimezone必须写,不然 MySQL 8 连接会报时区错误;characterEncoding=utf8保证中文不乱码;端口如果被占用,改server.port即可,但前端请求地址要同步改。
3.2 小程序端导入与请求地址配置
打开微信开发者工具,选择导入项目,目录指向源码里的小程序文件夹,AppID 可以先用测试号。导入后第一件事是改请求基地址,通常在utils/request.js或config.js里。
// utils/request.js 请求封装示例 const BASE_URL = 'http://localhost:8080'; // 本地调试用这个 function request(options) { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + options.url, method: options.method || 'GET', data: options.data || {}, header: { 'content-type': 'application/json', 'token': wx.getStorageSync('token') || '' // 每次请求带 token }, success: (res) => { if (res.data.code === 401) { // token 失效,跳登录 wx.navigateTo({ url: '/pages/login/login' }); return; } resolve(res.data); }, fail: reject }); }); } module.exports = { request };这段封装做了三件事:拼基地址、自动带 token、统一处理 401。逻辑说明:wx.getStorageSync('token')从本地缓存取登录后存的 token,如果后端返回 401 说明过期,直接跳登录页,避免每个页面都写一遍判断。参数说明:BASE_URL本地调试写http://localhost:8080,但真机预览时 localhost 不通,要换成电脑局域网 IP,比如http://192.168.1.100:8080,并且开发者工具里勾选「不校验合法域名」。
3.3 微信登录与手机号获取的完整链路
这是就业平台最关键的鉴权环节,也是热搜里微信小程序登录获取手机号问得最多的点。流程分四步:小程序调wx.login拿 code,后端用 code 换 openid 和 session_key,小程序调getPhoneNumber拿加密数据,后端解密拿手机号。注意,getPhoneNumber必须由用户点击按钮触发,不能自动调。
// pages/login/login.js 登录按钮逻辑 Page({ // 第一步:获取 code 并传给后端换 token handleLogin() { wx.login({ success: (res) => { if (res.code) { request({ url: '/api/auth/login', method: 'POST', data: { code: res.code } }).then((data) => { wx.setStorageSync('token', data.token); wx.setStorageSync('openid', data.openid); }); } } }); }, // 第二步:用户点击授权按钮后获取手机号 handleGetPhone(e) { if (e.detail.errMsg !== 'getPhoneNumber:ok') { wx.showToast({ title: '需要授权才能登录', icon: 'none' }); return; } request({ url: '/api/auth/phone', method: 'POST', data: { encryptedData: e.detail.encryptedData, iv: e.detail.iv } }).then((data) => { wx.setStorageSync('phone', data.phone); wx.switchTab({ url: '/pages/index/index' }); }); } });逻辑说明:handleLogin只负责拿 openid 建账号,handleGetPhone负责补全手机号。后端解密用 session_key,所以 session_key 要跟 openid 一起存服务端,不能下发到前端。参数说明:encryptedData和iv是微信返回的加密串,后端用 AES-128-CBC 解密,密钥就是 session_key。常见翻车点是 session_key 过期,用户登录后放太久再点获取手机号会解密失败,解决办法是解密失败时让前端重新走一遍wx.login。
4. 岗位检索与简历投递:把业务闭环写通
4.1 岗位列表的分页、搜索与筛选实现
岗位列表是用户停留最久的页面,性能和数据准确性都重要。后端接口设计成GET /api/job/list?page=1&size=10&keyword=&city=&salaryRange=,前端用scroll-view或页面onReachBottom做上拉加载。
// pages/job/list.js Page({ data: { list: [], page: 1, hasMore: true, keyword: '' }, onLoad() { this.loadJobs(); }, loadJobs() { if (!this.data.hasMore) return; request({ url: '/api/job/list', data: { page: this.data.page, size: 10, keyword: this.data.keyword } }).then((res) => { this.setData({ list: this.data.list.concat(res.rows), page: this.data.page + 1, hasMore: res.rows.length === 10 // 返回不足 10 条说明到底了 }); }); }, onReachBottom() { this.loadJobs(); }, onSearchInput(e) { this.setData({ keyword: e.detail.value }); } });逻辑说明:hasMore用返回条数判断是否还有下一页,比查总数再算页数省一次查询。concat把新数据拼到旧列表后面,实现无限滚动。参数说明:size建议 10 到 20,太大首屏慢,太小请求频繁。搜索关键词后端用LIKE '%keyword%'匹配岗位标题和公司名,但数据量大时LIKE前置通配符走不了索引,毕设数据量小无所谓,真上线要换全文索引或搜索引擎。
4.2 简历投递的状态流转与防重复投递
投递功能看着简单,坑不少。核心逻辑是:同一学生对同一岗位只能有一条有效投递记录,重复投递要拦截。后端在插入前先查delivery表有没有user_id + job_id且状态不是已拒绝的记录。
-- 投递前检查是否已投递 SELECT id FROM delivery WHERE user_id = ? AND job_id = ? AND status NOT IN ('已拒绝', '已撤回'); -- 没有记录才允许插入 INSERT INTO delivery (job_id, user_id, resume_id, status, create_time) VALUES (?, ?, ?, '已投递', NOW());逻辑说明:状态用中文枚举存虽然直观,但建议实际开发用数字或英文常量,避免编码问题。status NOT IN排除已拒绝和已撤回,意味着被拒后可以重新投,这是合理的产品逻辑。参数说明:resume_id取当前用户默认简历,如果用户没建简历要先引导去建。防重复还可以在数据库加唯一索引(user_id, job_id),但那样被拒后就不能重投,所以更推荐应用层判断。
4.3 企业端发布岗位与管理员审核
企业端和管理员端可以放在同一个小程序里用角色区分,也可以单独做管理后台。毕设常见做法是管理员用 Web 后台,企业用小程序。企业发布岗位后状态置为待审核,管理员审核通过才在列表可见。
// 企业发布岗位提交 submitJob() { const { title, salary, city, description } = this.data.form; if (!title || !salary || !city) { wx.showToast({ title: '请填写完整', icon: 'none' }); return; } request({ url: '/api/job/publish', method: 'POST', data: { title, salary, city, description, status: '待审核' } }).then(() => { wx.showToast({ title: '已提交审核' }); wx.navigateBack(); }); }逻辑说明:前端做必填校验只是体验优化,后端必须再校验一遍,防止绕过。status由后端根据当前用户角色决定,企业发布一律待审核,管理员发布可直接上架。参数说明:salary建议存区间字符串如8k-12k,比存两个数字字段简单,展示也方便。
5. 这类项目最容易翻车的五个地方
5.1 真机预览接口全部 404
现象:开发者工具里一切正常,手机扫码预览后所有请求失败。原因:BASE_URL写的是localhost,手机访问不到电脑本地服务。解决:改成电脑局域网 IP,确保手机和电脑同一 WiFi,开发者工具详情里勾选「不校验合法域名、web-view 域名、TLS 版本以及 HTTPS 证书」,后端防火墙放行对应端口。
5.2 手机号解密报 -41003 或解密为空
现象:点获取手机号后后端解密失败。原因:session_key过期或前后端用的不是同一次登录的 session_key。解决:确保wx.login和getPhoneNumber在相近时间完成,后端把 session_key 按 openid 缓存,解密失败时返回特定错误码让前端重新登录再试。注意 session_key 绝不能下发到前端。
5.3 列表上拉加载重复数据
现象:快速滑动时同一岗位出现两次。原因:onReachBottom触发多次,请求还没回来就又发了一次。解决:加一个loading标志位,请求中不重复触发。
loadJobs() { if (this.data.loading || !this.data.hasMore) return; this.setData({ loading: true }); request({ /* ... */ }).then((res) => { // 处理数据 this.setData({ loading: false }); }).catch(() => { this.setData({ loading: false }); }); }5.4 中文乱码与时间差八小时
现象:岗位描述里的中文变问号,创建时间比实际早或晚八小时。原因:数据库字符集不是utf8mb4,或 JDBC 连接没配时区。解决:建库时指定CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci,连接串加serverTimezone=Asia/Shanghai,实体类时间字段用java.util.Date或LocalDateTime并确认序列化格式。
5.5 token 过期后页面白屏
现象:放一晚上再打开小程序,页面空白无数据。原因:token 过期,接口返回 401,但页面没处理跳转。解决:在请求封装里统一拦截 401 跳登录,同时登录页onLoad时检查本地 token 是否存在,存在就直接进首页,避免每次都要重新授权。
6. 让答辩加分的一个技巧:把投递状态做成可视化时间轴
跑通基本功能后,如果想让演示效果更抓人,我建议把投递记录页做成时间轴样式。学生能看到自己的简历从「已投递」到「已查看」再到「邀面试」的完整轨迹,这比干巴巴的列表有说服力得多。实现上不复杂,后端在delivery表加一个status_log字段存 JSON 数组,每次状态变更追加一条带时间戳的记录。
// 投递详情页渲染时间轴 Page({ data: { timeline: [] }, onLoad(options) { request({ url: '/api/delivery/detail', data: { id: options.id } }) .then((res) => { // res.statusLog 形如 [{status:'已投递',time:'2024-03-01 10:00'}, ...] this.setData({ timeline: res.statusLog }); }); } });<!-- 时间轴 wxml 结构 --> <view class="timeline"> <view class="item" wx:for="{{timeline}}" wx:key="time"> <view class="dot {{index === 0 ? 'active' : ''}}"></view> <view class="content"> <text class="status">{{item.status}}</text> <text class="time">{{item.time}}</text> </view> </view> </view>逻辑说明:statusLog用 JSON 存历史,查询时直接返回,不用额外建日志表,毕设够用。index === 0给最新状态加高亮样式,视觉上突出当前进度。参数说明:时间格式在后端统一格式化成yyyy-MM-dd HH:mm再返回,前端不做转换,减少出错。样式上竖线用border-left,圆点用绝对定位,具体 CSS 按自己审美调。
这个技巧的价值在于,它把「数据流转」变成了「用户能看懂的故事」,答辩时老师一眼就能看出你理解了业务闭环,而不只是堆功能。我自己做这类项目时,早期也犯过只关注接口通不通、忽略展示效果的毛病,后来发现演示环节的观感直接影响评价。把状态可视化这一步加上,成本不高,效果立竿见影。希望帮到你。
本文还有配套的精品资源,点击获取