每年三四月份,都会有一批学弟学妹跑来找我帮看毕业设计选题,我做过的二三十个里,被问得最多的就是“SpringBoot + 员工工资管理系统”。这个题目看着普通,但恰恰是普通题目里最能拉开分数的那一类:业务逻辑清晰、技术栈主流、可扩展性强,只要做扎实了,答辩老师基本挑不出大毛病。如果你正打算做这个题目,或者已经选了但还在懵着,这篇文章就是写给你的。
我会从选题逻辑、技术选型、数据库设计、后端实现、微信小程序对接、答辩PPT准备,到真实踩过的坑,一条线讲完。内容偏向“照着做就行”的实战打法,适合Java初学者,也适合需要快速完成毕设的同学们。
1. 为什么“员工工资管理系统”是毕业设计的稳妥选择
1.1 这个选题解决了什么真实问题
工资管理是每一家企业都绕不开的核心事务,它不只是算钱那么简单,背后牵扯着员工档案、考勤数据、社保公积金、个税、奖金扣款、工资条发放、财务报表等多个环节。选这个题目,首先是因为业务场景足够真实,你们可以在任何一个公司的薪酬流程里找到原型,需求合理,答辩时说“这个系统能解决什么问题”非常容易被老师接受。
其次,它不是一个纯增删改查的“玩具系统”。真正打磨过的工资管理系统,需要有权限分层(管理员、财务/人事、普通员工)、需要处理计算逻辑(应发、扣款、个税、实发),需要做数据校验(重名员工、身份证号、银行卡号),需要生成工资条和报表,甚至要考虑工资数据的不可篡改性。这些点随便挑两三个深入展开,都能明显提高项目的技术含量。
1.2 题目难度如何拿捏:千万别一上来就做大而全
我见过很多同学一听说做工资系统,就把视野铺得特别开:要智能排班、要人脸考勤、要钉钉对接、要复杂的社保计算器、要做App……这些功能单独拉出来都是一篇毕业论文的工作量,堆在一起只会让你手忙脚乱,最后每个模块都浅尝辄止,答辩被问到底层细节时一问三不知。
我的建议是:以最核心的“工资核算闭环”为主线,向外扩展2到3个辅助功能即可。主线是:员工信息维护 -> 考勤/工时数据录入 -> 工资项目配置 -> 月工资核算 -> 工资条生成/确认 -> 财务报表统计。辅助功能可以做微信小程序员工端(查工资条)、部门/岗位管理、公告通知。做到这个规模,论文容量够、系统演示路径清晰、答辩深度也足够。
1.3 工作量分配:前端和后端的比例怎么算
如果是个人独立完成,建议把时间按“4:4:2”切分:40%做后端和数据库,40%做前端页面,20%专门用于测试、写论文和答辩PPT。很多同学栽在最后一步,项目明明做好了,但没留时间做演示环境、准备答辩讲稿,导致展示时各种翻车。后文我会专门讲答辩PPT怎么准备,这里先记一句:项目完成度很重要,但让老师“看懂你的完成度”同样重要。
2. 技术选型:SpringBoot为主,微信小程序到底该不该安排
2.1 后端框架:为什么坚定选SpringBoot
现在Java后端毕业设计的主流基本就是SpringBoot,原因很现实:生态成熟、资料多、上手成本低。SpringBoot最核心的价值是自动配置——你不需要像早期SSH那样写一堆XML配置,只要引入starter依赖,常用的数据源、ORM、Web框架就能自动整合好,这极大降低了起步门槛。
基于SpringBoot的典型分层结构是:
controller -> 接收前端请求,参数校验,返回统一响应 service -> 业务逻辑,事务控制 mapper -> 数据访问,与数据库交互 entity/dto -> 数据实体与传输对象 config -> 统一配置(跨域、拦截器、异常处理)这套结构清晰,答辩时用这张分层图就能讲明白整体架构。我个人建议哪怕项目简单,也一定要保持分层规范,这会让代码可读性高很多,后期查Bug也方便。
2.2 前端方案:Web管理端 + 微信小程序员工端
这个题目天然有两种角色需求:管理员/人事要处理数据,普通员工要看自己的工资条。于是前端就分成两块:
- 管理端:用Layui、ElementUI或直接Thymeleaf模板渲染都可以。如果你的前端基础一般,我推荐先用Bootstrap + Thymeleaf做一套服务端渲染页面,逻辑直接、容易控制,也不容易出现前后端分离下跨域和Token那一堆问题。
- 员工端:做一个微信小程序,员工登录后可以查看自己最近几个月的工资条、请假/考勤数据、公司公告。小程序轻量、入口方便、界面速度快,作为员工自助查询的载体很合适。
标题里带了“微信小程序毕业设计”,说明这个项目大概率希望有一个小程序端。我的判断是:管理端为主,小程序端为辅,因为工资核算、员工档案维护这种高频复杂操作必须放在大屏管理端完成,小程序只做面向普通员工的轻量查询,工作量可控,又能展示“多端适配”的能力。
2.3 数据库与中间件:够用就好
数据库直接用MySQL,版本5.7或8.0都可以。ORM用MyBatis-Plus,它省去了大量单表CRUD代码,自带分页插件,统计报表时也能用LambdaQueryWrapper快速组装条件查询。缓存可以做一层Redis,用来存登录Token、字典配置、高频查询的工资条数据,但注意别为了用Redis而用,一定要能说出“它解决了什么性能或状态问题”。
下面这张表是我推荐的技术栈搭配,可以直接照抄进论文的技术选型章节:
| 层次 | 选型 | 使用场景 |
|---|---|---|
| 后端框架 | SpringBoot 2.7.x | 系统主框架 |
| ORM | MyBatis-Plus | 数据持久化、分页查询 |
| 数据库 | MySQL 8.0 | 存储业务数据 |
| 缓存 | Redis | 登录Token、接口缓存 |
| 前端管理端 | Bootstrap + Thymeleaf | 后台管理页面 |
| 小程序端 | 原生微信小程序 / uni-app | 员工自助查询 |
| 接口文档 | Knife4j | 后端接口调试与演示 |
3. 核心功能模块拆解:从员工入职到拿到工资条
3.1 员工信息管理:基础数据质量决定后面所有计算
员工模块是整个系统的基础,员工数据不准确,后面的考勤、工资、报表全都会出问题。设计员工表时,至少要包含:工号、姓名、性别、身份证号、手机号、部门ID、岗位、入职日期、银行卡号、基本工资、状态(在职/离职)。
这里有两个容易低估的细节:
一是工号不要用自增数字,建议用可读性强的编码,比如部门前缀+年份+序号,如“HR2025001”。这样管理端显示更直观,以后对接考勤机、外部系统也不容易冲突。
二是重复员工问题。现实中同名同姓很常见,判断唯一性要联合身份证号或手机号,而不是只看姓名。我在项目里通常会把身份证号设为逻辑唯一键(配合加密存储),并且在新增员工时做校验,减少后续工资发放串人的风险。
3.2 工资项设计:把计算规则做成配置,而不是写死在代码里
工资系统的核心难点不是“算数”,而是工资规则经常变。这个月加个交通补贴,下个月调社保基数,如果这些规则都写死在Java代码里,每次变更都要改代码重新部署,显然不现实。
所以我在设计时会把工资项拆成一张配置表:
工资项ID | 工资项名称 | 计算方式(固定/按公式) | 计算公式/值 | 生效月份常见的工资项有:基本工资(固定值)、岗位工资(固定值)、绩效奖金(按绩效系数计算)、加班费(按加班工时*时薪)、交通补贴(固定值)、社保个人部分(按基数比例)、缺勤扣款(按天扣减)、个税(按累计预扣法)。
核算时,系统读取该月份启用的工资项配置,逐项计算。这样以后要调整补贴标准,只需在页面上修改配置,不需要动代码,答辩时这个设计非常加分,因为它体现了“可配置化”的思想。
3.3 工资核算与审核:加一道“确认”环节
工资这种事,算错了影响非常大,所以流程上不能是“算完就发”。我建议加入审核状态机:草稿 -> 待审核 -> 已审核 -> 已发放。管理员核算后生成草稿工资单,财务人员审核确认,最后标记发放,员工端小程序才能看到工资条。
这个流程的价值在于:第一,让系统逻辑更贴近真实业务;第二,为事务和权限设计提供了很好的应用场景,比如“只有审核人才能调用审核接口”“审核后工资数据不允许修改”,这些都是答辩时可以展开讲的业务约束。
3.4 统计报表:用图表让项目看起来完成度更高
工资系统如果只有数据录入和查询,还是比较单薄。建议在管理端加一个统计模块,展示:月度工资总额趋势、部门工资占比、平均薪资对比、人员变动情况。用ECharts画几张折线图、柱状图,数据从工资表和员工表中聚合而来。
这些图表不用做得很复杂,但一定要保证数据逻辑正确。很多同学在图表上翻车就是因为图做得很炫,老师随口问一个“这个月的工资总额是哪些部门汇总来的”,结果回答说不上来。
4. 数据库设计与关键实现细节
4.1 核心数据表设计:五张表就能跑通闭环
不是表越多越好,而是每张表都有清晰的职责。一个能跑通全流程的最小表集合是:
-- 员工表 CREATE TABLE `employee` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `employee_no` varchar(32) NOT NULL COMMENT '工号', `name` varchar(50) NOT NULL, `id_card` varchar(18) DEFAULT NULL COMMENT '身份证号', `phone` varchar(20) DEFAULT NULL, `department_id` bigint(20) DEFAULT NULL, `position` varchar(50) DEFAULT NULL, `basic_salary` decimal(10,2) DEFAULT NULL, `hire_date` date DEFAULT NULL, `status` tinyint(1) DEFAULT '1' COMMENT '1在职 0离职', PRIMARY KEY (`id`), UNIQUE KEY `uk_employee_no` (`employee_no`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 工资项配置表 CREATE TABLE `salary_item` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `item_name` varchar(50) NOT NULL, `calc_type` tinyint(1) DEFAULT '0' COMMENT '0固定 1公式', `calc_value` decimal(10,2) DEFAULT NULL, `is_active` tinyint(1) DEFAULT '1', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 月度工资表 CREATE TABLE `salary_record` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `employee_id` bigint(20) NOT NULL, `salary_month` varchar(7) NOT NULL COMMENT '格式2025-03', `base_salary` decimal(10,2) DEFAULT NULL COMMENT '应发工资', `deduction` decimal(10,2) DEFAULT NULL COMMENT '扣款合计', `tax` decimal(10,2) DEFAULT NULL COMMENT '个税', `net_salary` decimal(10,2) DEFAULT NULL COMMENT '实发工资', `status` tinyint(1) DEFAULT '0' COMMENT '0草稿 1待审核 2已审核 3已发放', PRIMARY KEY (`id`), UNIQUE KEY `uk_employee_month` (`employee_id`, `salary_month`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 工资条明细表 CREATE TABLE `salary_detail` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `record_id` bigint(20) NOT NULL, `item_name` varchar(50) DEFAULT NULL, `amount` decimal(10,2) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;这套表结构的核心思路是:工资主表记录每个员工每月最终结果,工资明细表记录每个工资项的组成明细,工资项配置表控制计算规则。这样一条工资记录能够完整地解释“实发工资是怎么算出来的”,程序可读性高,审计也方便。
4.2 工资计算逻辑:用BigDecimal,千万不要用浮点型
工资计算是钱的事,精度问题必须较真。Java里的float和double在二进制存储下会有精度损失,算出来的结果可能出现0.1+0.2不等于0.3这种奇怪问题,所以所有涉及金额的字段都用BigDecimal,数据库里也统一用decimal(10,2)。
核算单个员工月工资的伪代码如下:
// 读取启用中的工资项配置列表 List<SalaryItem> items = salaryItemMapper.selectList( new LambdaQueryWrapper<SalaryItem>() .eq(SalaryItem::getIsActive, 1)); BigDecimal baseSalary = employee.getBasicSalary(); // 基本工资 BigDecimal performance = BigDecimal.ZERO; // 绩效奖金 BigDecimal overtimePay = BigDecimal.ZERO; // 加班费 BigDecimal deduction = BigDecimal.ZERO; // 扣款 for (SalaryItem item : items) { switch (item.getItemName()) { case "基本工资": // 来源于员工档案 performance = performance.add(baseSalary); break; case "绩效奖金": BigDecimal factor = getPerformanceFactor(employeeId); performance = baseSalary.multiply(factor); break; case "加班费": overtimePay = getOvertimePay(employeeId, salaryMonth); break; case "缺勤扣款": BigDecimal absentDays = getAbsentDays(employeeId, salaryMonth); BigDecimal dailyWage = baseSalary.divide(BigDecimal.valueOf(21.75), 2, RoundingMode.HALF_UP); deduction = deduction.add(dailyWage.multiply(absentDays)); break; } } BigDecimal grossSalary = baseSalary.add(performance).add(overtimePay); BigDecimal tax = calculateTax(grossSalary.subtract(deduction)); BigDecimal netSalary = grossSalary.subtract(deduction).subtract(tax);这里有三个细节值得注意:
第一,加班费按小时算,时薪 = 月基本工资 / 21.75 / 8,这是劳动法里常见的标准工时算法,用21.75作为月计薪天数,比直接除以30更专业,答辩时能讲出依据。
第二,缺勤扣款按天扣,日工资同样用21.75计算。这里要把“出勤天数”和“应出勤天数”管理好,否则跨月、节假日会导致计算结果不稳定。
第三,个税计算建议用“累计预扣法”,这是目前国内工资计算常用的方法。逻辑是:累计收入减累计减除费用、累计专项扣除、累计专项附加扣除,得到累计应纳税所得额,再对照月度税率表计算。虽然毕设里可以用简化算法:应纳税所得额 = 月收入 - 5000起征点 - 五险一金个人部分,然后按超额累进税率计算。但如果你在答辩中被问到“个税在实际中怎么算”,能说出累计预扣法会更加分。
个税的简化计算可以参考这个方法:
private BigDecimal calculateTax(BigDecimal taxableIncome) { // 采用简化月度计算,实际项目可按累计预扣法扩展 if (taxableIncome.compareTo(BigDecimal.ZERO) <= 0) { return BigDecimal.ZERO; } // 不超过3000部分:3% // 3000-12000部分:10%,速算扣除210 // 12000-25000部分:20%,速算扣除1410 // 超过25000部分继续累进... if (taxableIncome.compareTo(new BigDecimal("3000")) <= 0) { return taxableIncome.multiply(new BigDecimal("0.03")) .setScale(2, RoundingMode.HALF_UP); } if (taxableIncome.compareTo(new BigDecimal("12000")) <= 0) { return taxableIncome.multiply(new BigDecimal("0.1")) .subtract(new BigDecimal("210")) .setScale(2, RoundingMode.HALF_UP); } // 更多区间省略 return BigDecimal.ZERO; }4.3 工资条的生成与导出:Excel导出是答辩演示的加分项
工资条除了在系统里看,还要支持导出。常见方式是导出一整个月的工资Excel表,包含每名员工的应发工资、扣款、个税、实发工资,并要求金额列使用数字格式,方便财务二次核对。
用EasyExcel导出时,注意“表头”和“字段映射”要一致。我遇到过很多同学自定义样式的Excel模板,结果列名对不上,导出的文件有一堆空列。建议用注解方式直接映射实体字段:
@ExcelProperty("工号") private String employeeNo; @ExcelProperty("姓名") private String name; @ExcelProperty("月份") private String salaryMonth; @ExcelProperty("应发工资") private BigDecimal baseSalary; @ExcelProperty("扣款合计") private BigDecimal deduction; @ExcelProperty("个税") private BigDecimal tax; @ExcelProperty("实发工资") private BigDecimal netSalary;导出接口要考虑数据量大时的内存问题,一般毕设不会遇到几万条数据,直接一次全量导出也能扛住,但你要知道分页导出的思路,答辩时可以提一句“后续可以优化为流式导出”。
5. 微信小程序端:员工自助查询工资条怎么实现
5.1 页面规划:别贪多,三五个页面就够了
小程序端定位是“员工自助”,所以页面尽量精简。我建议这样规划:
- 首页:展示当前登录员工的基本信息 + 最近一个月的工资概览(实发工资)
- 工资条列表页:按月列出历史工资记录
- 工资条详情页:展示某个月份的工资明细(应发、扣款、个税、实发)
- 我的:员工登录状态、退出登录
页面少不代表工作量小,精简页面更需要把每个页面做得完整:加载态、空态、异常态都要处理。比如工资条列表没有数据时,不能白屏,要给一个“暂无工资记录”的提示;请求失败时,要给重试按钮。
5.2 登录鉴权:wx.login拿到code,后端换openid
小程序不能直接使用账号密码登录,标准做法是:
- 前端调用
wx.login()获取临时code - 后端拿着code调用微信接口换取 openid 和 session_key
- 用openid去员工表匹配或自动创建员工账号
- 服务端生成自定义登录态(Token),返回给小程序
- 小程序后续请求在 header 里带 Token,后端通过拦截器验证身份
后端核心接口如下:
@RestController @RequestMapping("/api/wx") public class WxLoginController { @Autowired private WxService wxService; @PostMapping("/login") public Result login(@RequestBody WxLoginDTO dto) { // 1. 调用微信接口,用code换openid String openid = wxService.code2Session(dto.getCode()); // 2. 在employee表中通过openid查询员工,没有则绑定 Employee employee = employeeMapper.selectOne( new LambdaQueryWrapper<Employee>().eq(Employee::getOpenid, openid)); if (employee == null) { return Result.error("员工信息未绑定,请联系管理员"); } // 3. 生成token并缓存 String token = UUID.randomUUID().toString().replace("-", ""); redisTemplate.opsForValue().set("wx:token:" + token, employee.getId(), 2, TimeUnit.HOURS); return Result.success(token); } }这里有一个经验:openid是同一个用户在同一个小程序下的唯一标识,但不同小程序之间不通用。也就是说,你新的小程序上线后,老用户的openid是会变的。所以千万别把openid当成全局员工ID来用,它只是身份关联的索引。
5.3 列表加载更多:onReachBottom触底加载
小程序的工资条记录一般不会很多,但“页面列表加载更多”是面试和答辩中经常被追问的点,所以我还是实现了它,主要思路是:
- 维护一个
pageNum和pageSize - 请求时带上分页参数,后端返回 total 和 records
- 页面触底时(
onReachBottom),如果pageNum * pageSize >= total,就提示“没有更多了” - 加载中加一个开关
loading,避免重复请求
核心js片段:
Page({ data: { salaryList: [], pageNum: 1, pageSize: 10, total: 0, loading: false, hasMore: true }, async loadSalaryList(reset = false) { if (this.data.loading) return; if (reset) { this.setData({ pageNum: 1, salaryList: [], hasMore: true }); } if (!this.data.hasMore) return; this.setData({ loading: true }); const res = await request.get('/salary/my-list', { pageNum: this.data.pageNum, pageSize: this.data.pageSize }); const list = this.data.salaryList.concat(res.records); this.setData({ salaryList: list, total: res.total, pageNum: this.data.pageNum + 1, loading: false, hasMore: list.length < res.total }); }, onReachBottom() { this.loadSalaryList(); } });这里有一个细节容易忽略:分页的排序必须稳定。如果不同页码的数据乱序,会出现重复或漏掉记录的问题。我的处理是后端接口统一按salary_month DESC排序,而不是按id倒序,这样数据在翻页时不会乱。
5.4 小程序与后端的接口风格
前后端接口名要统一规范,方便自己也方便做接口文档。我推荐RESTFul风格:
| 功能 | 请求方式 | 路径 |
|---|---|---|
| 小程序登录 | POST | /api/wx/login |
| 获取当前员工工资列表 | GET | /api/salary/my-list?pageNum=1&pageSize=10 |
| 获取工资条详情 | GET | /api/salary/detail/{recordId} |
| 员工信息查询 | GET | /api/employee/my-info |
所有接口统一返回结构{ code: 200, message: "success", data: ... },前端判断code做统一处理,后端用全局异常处理器捕获业务异常,返回友好提示,这会让整个项目看起来非常规范。
6. 毕业答辩PPT的讲法:怎么把项目讲成高分
6.1 PPT结构:不要照抄论文目录
很多同学的答辩PPT就是论文目录的复制粘贴,背景、意义、技术、功能、总结,老师听得昏昏欲睡。我的经验是PPT要按“问题-方案-实现-效果”的逻辑来讲,控制在12到15页以内:
- 第1页:项目名称 + 一句核心价值
- 第2页:你解决了什么业务痛点(员工工资核算不准、查询麻烦、报表统计困难)
- 第3页:系统整体架构图(前后端分离?单体?模块划分)
- 第4页:技术选型及为什么这么选(SpringBoot生态成熟、MyBatis-Plus提高效率)
- 第5页:功能模块图(按角色划分功能)
- 第6-7页:核心业务逻辑讲解(重点讲工资计算规则和审核流程)
- 第8-9页:数据库设计(核心表关系,不用全放,放你们引以为傲的表)
- 第10页:系统演示截图/录屏二维码
- 第11页:难点与解决方案
- 第12页:不足与后续扩展
这里最忌讳的是“照着代码贴一大段上去”。PPT上的代码最多放10行以内,只放最能体现核心思想的片段,剩下的口头展开,老师最想听你用语言把逻辑讲清楚,而不是看你读代码。
6.2 高频提问怎么接招:提前准备五类送分题
答辩本质上是一次“说服”,老师问到你不会的问题时,只要能展示思考路径,通常也能过关。下面这几类问题我建议提前准备:
为什么用SpringBoot不用SSH/SSM?答:SpringBoot自动配置简化了开发,项目结构更清晰,适合快速迭代;同时它本身就是基于Spring生态的,没有丢掉依赖注入和AOP的能力。
工资的精度为什么用BigDecimal?答:float和double浮点运算会丢失精度,工资计算涉及金钱,必须精确到分,BigDecimal可以精确控制小数位和舍入规则。
你的事务是怎么控制的?答:在service层利用@Transactional,比如生成工资单时,需要同时写入salary_record和salary_detail,任何一个步骤失败就整体回滚,保证工资数据一致。
员工查询工资条你怎么做权限控制?答:小程序登录后拿到token,后端拦截器校验登录状态并解析出员工ID,查询时强制带上employeeId条件,防止通过修改参数越权访问别人的工资条。
如果公司有5000名员工,月工资核算怎么优化?答:可以考虑批量生成、异步任务、分页处理,而不是在循环中逐条查库,还可以引入分布式任务调度,将核算任务拆分执行。你能答出这几个方向就够了。
6.3 演示环节的保命操作
答辩现场最怕的是“运行环境挂了”“数据库连不上”“WiFi太差打不开小程序”。我的建议是:
- 提前录好一段演示视频放在优盘里,或者准备一个录屏MP4,万一系统现场扑街,直接放录屏。
- 数据库和项目部署在本地笔记本,不要依赖云端服务器,演示前最好断网测试一遍。
- 准备一套演示专用数据:至少10个员工、最近3个月的工资记录、各类状态(草稿、已审核、已发放)都要有。
- 小程序真机预览提前缓存一次,避免现场编译超时。
7. 实操踩坑记录:这些坑我替你们趟过了
7.1 金额字段类型不一致导致的对账错误
我见过一个同学,数据库amount字段用double,Java实体用BigDecimal,查询出来的数据看上去没问题,但求和时出现了0.01的差异。排查半天才发现数据库字段是float,存储的精度已经丢了。统一BigDecimal + decimal(10,2)之后问题才消失。这个坑很隐蔽,但也很好解释:金额一旦通过浮点方式存储,误差就是永久性的。
7.2 生成本月工资时没处理“重复生成”
如果用户在页面上点了两次“生成上月工资”,又没有做唯一约束,工资记录就会出现两条,明细也会翻倍。最简单的规避方式是用数据库的唯一索引对(employee_id, salary_month)做约束,同时在生成逻辑里先查一次已存在的记录,存在则返回“该月已生成”。这两种方式同时做,才能保证线下维护时不容易破坏数据。
7.3 小程序端请求域名必须加入白名单
开发的时候大家都会开启“不校验合法域名”,但真正发布上线时,小程序请求的接口域名必须提前在微信公众平台配置。如果你的毕设只做本地演示,可以把“不校验合法域名”打开。如果想上线体验,一定记得买域名、做SSL证书、配置合法域名,这个步骤至少提前一周准备,因为域名备案可能需要几天时间。
7.4 跨域和Session问题
如果管理端选择了前后端分离(Vue等),就逃不开跨域和登录状态问题。我的经验是:与其在Filter里处理CORS,不如在后端统一配置跨域,同时用JWT或Token机制替代HttpSession,避免Session在多端下不互通的问题。毕设阶段用简单方案即可,但一定要能解释清楚“为什么不用Session”。
7.5 数据库初始化数据要先规划好
很多同学把项目跑起来后,发现工资列表是空的,临时手动算工资录入又花了很多时间。建议在开发初期就写好初始化SQL脚本,包括10个员工、6个月工资记录、完整的工资项配置、用户账号和绑定关系。这样每次重置数据库后,系统一启动就有内容可以演示,也方便你随时截图写论文。
写在最后:我的真实体会
带过这么多毕业设计,最大的体会是:这个题目拼的不是炫技,而是“完整”二字。能用SpringBoot把员工、工资、报表、小程序这几个环节串成一个闭环,逻辑自洽、数据准确、文档清晰,就已经是优秀的毕业设计了。
如果你只剩两周时间,我会建议你优先保住主线:先把管理端的员工管理和工资生成做通,再补小程序的查询功能,最后整理答辩PPT。那些锦上添花的功能,宁可砍掉也不要让主线出现毛刺。
最后送大家一个小技巧:做完系统后,自己从头到脚完整演示三遍,每次都用“公司财务月底要给三百名员工算工资”这个场景带入操作。三遍下来,你会发现很多平时没注意的异常情况,改掉之后,项目的稳定程度会有质的提升。这个习惯,不止用在毕业设计,以后工作做任何项目都同样受用。