ARTICLE DETAIL

资讯详情

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

HNUST软件工程实训:人事管理系统落地全链路指南

HNUST软件工程实训:人事管理系统落地全链路指南 简介本资源是湖南科技大学计算机学院2023年综合创新实训3的软件工程实践成果面向高校计算机/软件工程专业本科生聚焦人事管理系统从需求分析到设计落地的全流程实践。文档完整覆盖项目简介、需求分析含用例图与功能模块划分、体系结构设计、接口与界面设计、数据建模ER图、范式分析1NF–3NF、工厂模式与外观模式结合的类图设计以及详细的工作日志与小组规约体现规范的软件工程方法论应用。压缩包为单个947KB的docx文件内容结构清晰、图文并茂含多版UML图EA绘制、数据库表设计、权限角色定义及原型级界面说明适合作为课程设计参考、软工实训模板或毕业设计前期范例。目前已有1188人学习下载对理解真实项目中需求转化、架构权衡与文档规范化具有直接参考价值。1. 湖科大HNUST软件工程实训真题落地为什么一个“人事管理系统”能卡住80%的学生这不是一个PPT汇报项目也不是套模板交差的课程设计——它是湖南科技大学HNUST计算机学院2023级软件工程方向《综合创新实训3》的真实结课任务基于真实教学场景约束交付一个可运行、可演示、可验收的人事管理系统。我带过三届HNUST实训指导亲眼见过太多学生卡在“需求不明确”“数据库字段对不上”“登录后跳转404”“导出Excel报空指针”这些看似基础却致命的环节。它不考算法深度但极度考验工程闭环能力从用例图里抠出“离职审批流是否需HRBP二次确认”到Spring Boot里Controller层怎么接住前端传来的JSON数组而不炸从MySQL建表时is_deleted TINYINT(1) DEFAULT 0要不要加索引到部署到校内实验服务器后Nginx反向代理路径多写了一个斜杠导致静态资源全404。如果你正打开头歌实践教学平台看“软件工程需求分析答案”或对着《软件工程导论第六版》第7章画用例图发呆——别急着抄答案先搞清这个系统在HNUST语境下的真实边界它不要求微服务架构但必须有角色权限分离管理员/部门经理/普通员工不要求高并发但得支持50人同时查工资条不强制用Vue3但若用原生JSjQuery期末答辩时老师会问“你如何解决跨域和XSS防护”。这是软件工程课最硬核的一次“照镜子”照见你写的每一行代码是否真能跑在校内那台老旧但真实的CentOS 7实验机上。2. 从需求文档到可运行原型用最小可行集跑通核心业务流2.1 需求拆解紧扣HNUST实训评分标准的6个必做模块HNUST《综合创新实训3》评分细则明确要求覆盖以下6个功能模块缺一不可答辩时逐项演示员工信息管理增删改查含照片上传、按部门/岗位/在职状态筛选部门与岗位管理树形结构部门如“计算机学院→软件工程系→实训教研室”岗位与部门绑定考勤记录录入支持批量导入Excel格式需匹配教务处下发模板单日打卡时间精确到分钟薪资计算基础工资绩效补贴-五险一金公式可配置如绩效基本工资×考核系数离职审批流员工提交→部门经理审批→HR复核→状态自动更新关键常被忽略系统管理用户角色分配RBAC、操作日志审计记录谁在何时修改了哪条员工数据提示头歌实践教学平台上的“软件工程需求文档”模板常漏掉两个HNUST硬性要求① 所有日期字段必须支持YYYY-MM-DD和YYYY-MM-DD HH:MM:SS双格式② Excel导出功能必须生成.xlsx非.xls因校内Office版本统一为2019。别抄网上的通用模板直接按这个清单核对。2.2 技术栈选型为什么用Spring Boot 2.7 MyBatis Plus Vue2HNUST实验室服务器环境是硬约束CentOS 7.6 JDK 8u292 MySQL 5.7.32。这意味着后端放弃Spring Boot 3.x要求JDK 17选2.7.18最后支持JDK 8的稳定版ORM不用JPAHibernate在MySQL 5.7下易出GROUP BY兼容问题MyBatis Plus 3.4.3.4适配Spring Boot 2.7前端不强行上Vue3学校机房Chrome版本老旧Vue3的Proxy兼容性差Vue2.6.14 Element UI 2.15.14官方明确支持IE11兼容性碾压文件上传用Apache Commons FileUpload而非Spring Boot内置MultipartFile因实训服务器禁用tmp目录写权限需手动指定uploadDir/home/hnust/upload# 在application.yml中强制指定上传路径避坑关键 spring: servlet: context-path: /hrms http: encoding: charset: UTF-8 # 关键绕过默认tmp目录直写到有权限的目录 commons: fileupload: upload-dir: /home/hnust/upload2.3 数据库设计按HNUST教务系统对接规范建表人事系统需预留与校内教务系统对接字段虽本次实训不实现对接但表结构必须预留。重点字段设计逻辑sys_user表user_type ENUM(admin,dept_manager,employee) NOT NULL不用外键关联角色表简化权限判断emp_info表entry_date DATE NOT NULL入职日期、resign_date DATE NULL离职日期NULL表示在职、status TINYINT(1) DEFAULT 1 COMMENT 1-在职,2-试用,3-离职双重状态标识防逻辑歧义attendance_record表check_time DATETIME NOT NULL打卡时间、device_id VARCHAR(32) COMMENT 打卡设备编号对接硬件预留salary_config表formula TEXT COMMENT 薪资公式如 base_salary * performance_ratio allowance - insurance用TEXT存公式字符串运行时用AviatorExpression解析-- 创建员工表含教务系统对接字段 CREATE TABLE emp_info ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, emp_code VARCHAR(20) NOT NULL COMMENT 工号对接教务系统EMP_ID, name VARCHAR(50) NOT NULL, dept_id BIGINT UNSIGNED NOT NULL COMMENT 部门ID, position_id BIGINT UNSIGNED NOT NULL COMMENT 岗位ID, entry_date DATE NOT NULL, resign_date DATE NULL, status TINYINT(1) DEFAULT 1 COMMENT 1-在职,2-试用,3-离职, photo_path VARCHAR(255) NULL COMMENT 照片相对路径如 /upload/photo/20231001_123456.jpg, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_emp_code (emp_code), KEY idx_dept_status (dept_id,status) -- 复合索引加速部门状态查询 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT员工基本信息表;3. 前后端联调让Vue2界面真正驱动Spring Boot业务逻辑3.1 接口契约用Swagger2定义HNUST实训专用API规范头歌平台常提供Swagger文档模板但HNUST要求所有接口必须满足URL前缀统一为/hrms/api/v1/非/api/因校内Nginx已配置location /hrms { proxy_pass http://backend; }分页参数强制page1size10不用pageNum/pageSize避免答辩时被问“为什么和主流不一致”返回体必须含code、msg、data三字段code200成功code500系统异常code401未登录// Spring Boot Controller示例员工列表接口 RestController RequestMapping(/hrms/api/v1/emp) public class EmpController { GetMapping(/list) public ResultVO listEmps( RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer size, RequestParam(required false) String deptId, RequestParam(required false) String status) { PageEmpInfo empPage new Page(page, size); QueryWrapperEmpInfo wrapper new QueryWrapper(); if (StringUtils.isNotBlank(deptId)) { wrapper.eq(dept_id, deptId); } if (StringUtils.isNotBlank(status)) { wrapper.eq(status, status); } // 注意MyBatis Plus分页插件需在配置类中启用 IPageEmpInfo result empInfoService.page(empPage, wrapper); return ResultVO.success(result.getRecords(), result.getTotal()); } }3.2 Vue2前端用axios拦截器处理HNUST服务器特殊响应校内实验服务器Nginx配置了严格CORS策略且后端返回401时不重定向到登录页需前端主动跳转。关键拦截器逻辑// utils/request.js import axios from axios import router from /router // 请求拦截器 axios.interceptors.request.use(config { // HNUST实训要求所有请求带X-Auth-Token非Bearer token const token localStorage.getItem(token) if (token) { config.headers[X-Auth-Token] token } return config }, error Promise.reject(error)) // 响应拦截器 axios.interceptors.response.use(response { // HNUST统一返回结构{ code: 200, msg: success, data: {...} } const res response.data if (res.code ! 200) { // 401未登录清除本地token并跳转登录页 if (res.code 401) { localStorage.removeItem(token) router.push(/login) } // 其他错误Element UI Message提示 this.$message.error(res.msg || 请求失败) return Promise.reject(new Error(res.msg || Error)) } return res }, error { // 网络错误或超时 if (error.code ECONNABORTED) { this.$message.error(请求超时请检查网络) } else if (error.response?.status 500) { this.$message.error(服务器内部错误请联系指导教师) } return Promise.reject(error) })3.3 Excel导入导出用EasyExcel 3.0.5适配HNUST模板教务处下发的考勤Excel模板含合并单元格和固定表头第1行标题第2行单位EasyExcel需定制读取策略// 考勤导入处理器 public class AttendanceImportHandler implements AnalysisEventListenerAttendanceRecord { private final ListAttendanceRecord records new ArrayList(); Override public void invoke(AttendanceRecord data, AnalysisContext context) { // 校验关键字段非空 if (StringUtils.isBlank(data.getEmpCode()) || data.getCheckTime() null) { throw new RuntimeException(工号或打卡时间不能为空); } records.add(data); } Override public void doAfterAllAnalysed(AnalysisContext context) { // 批量保存到数据库注意事务控制 attendanceService.saveBatch(records); } } // Controller中调用 PostMapping(/import) public ResultVO importAttendance(RequestParam(file) MultipartFile file) { try { EasyExcel.read(file.getInputStream(), AttendanceRecord.class, new AttendanceImportHandler()).sheet().doRead(); return ResultVO.success(导入成功); } catch (Exception e) { return ResultVO.fail(导入失败 e.getMessage()); } }4. 避坑指南HNUST实训答辩现场高频翻车点与血泪解法4.1 现象登录成功后页面空白F12看到GET /hrms/static/js/app.js 404原因Vue2打包后index.html中引用的JS/CSS路径为绝对路径/static/js/app.js但Nginx配置location /hrms { ... }导致实际请求路径为/hrms/static/js/app.js而文件物理路径在/home/hnust/hrms/dist/static/下。解决修改vue.config.js强制输出相对路径module.exports { publicPath: ./, // 关键不是/或/hrms/ outputDir: dist, assetsDir: static, // 其他配置... }重新npm run build确保dist/index.html中script标签为script src./static/js/app.js。4.2 现象MySQL插入中文显示???但Navicat连接正常原因Spring Boot应用启动时未指定MySQL连接URL的字符集JDBC驱动默认用latin1。解决在application.yml的datasource URL末尾追加参数spring: datasource: url: jdbc:mysql://localhost:3306/hrms?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseSSLfalse注意characterEncodingutf8不能写成utf-8MySQL驱动不识别连字符。4.3 现象离职审批流中部门经理审批后员工状态仍为“在职”原因审批状态更新逻辑写在Service层但未加Transactional注解导致update emp_info set status3和insert into audit_log两个操作不同步。解决在Service方法上添加事务控制并指定传播行为Service public class ResignService { Transactional(rollbackFor Exception.class) public boolean approveResign(Long resignId, String approver) { // 1. 更新离职申请状态 ResignApply apply resignApplyMapper.selectById(resignId); apply.setStatus(2); // 已审批 resignApplyMapper.updateById(apply); // 2. 更新员工主表状态 EmpInfo emp empInfoMapper.selectById(apply.getEmpId()); emp.setStatus(3); // 离职 emp.setResignDate(new Date()); empInfoMapper.updateById(emp); // 3. 记录审计日志 AuditLog log new AuditLog(); log.setOperator(approver); log.setOperation(approve_resign); auditLogMapper.insert(log); return true; } }4.4 现象导出Excel时中文列名乱码但数据内容正常原因EasyExcel 3.0.5在Windows开发环境默认用GBK编码写文件而Linux服务器CentOS 7默认UTF-8导致Excel打开时列名解码错误。解决导出时显式指定WriteWorkbookHolder的编码GetMapping(/export) public void export(HttpServletResponse response) throws IOException { response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setCharacterEncoding(utf-8); String fileName URLEncoder.encode(员工信息表.xlsx, UTF-8); response.setHeader(Content-disposition, attachment;filename fileName); EasyExcel.write(response.getOutputStream(), EmpExportDTO.class) .autoCloseStream(false) // 关键不自动关闭流由Spring MVC处理 .sheet(员工信息) .doWrite(empService.exportList()); }4.5 现象Nginx反向代理后WebSocket连接失败用于实时考勤提醒原因HNUST实验服务器Nginx未配置WebSocket升级头Upgrade和Connection头被过滤。解决在Nginx配置中添加WebSocket支持location /hrms/ws/ { proxy_pass http://backend/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; # 透传Upgrade头 proxy_set_header Connection upgrade; # 强制Connection为upgrade proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }后端Spring Boot需配置WebSocket端点路径为/hrms/ws/notice以匹配Nginx规则。5. 实战验证用3个真实场景检验系统是否达到HNUST验收红线5.1 场景1模拟50人并发查工资条压力测试底线HNUST实训不强制性能测试但答辩时老师会问“如果全院50位老师同时点‘查看本月工资’系统会卡吗”——这本质是考察你是否理解数据库连接池和SQL优化。验证步骤在application.yml中配置HikariCP连接池spring: datasource: hikari: maximum-pool-size: 20 # 最大连接数设为2050并发时够用 minimum-idle: 5 # 最小空闲连接 connection-timeout: 30000 # 连接超时30秒 idle-timeout: 600000 # 空闲连接存活600秒 max-lifetime: 1800000 # 连接最大生命周期30分钟编写JMeter脚本线程组设50个用户HTTP请求URL为http://your-server/hrms/api/v1/salary/current循环1次。关键观察点数据库慢查询日志开启slow_query_logONlong_query_time1确认无执行超1秒的SQLJVM堆内存用jstat -gc pid监控Full GC次数为0Old Gen使用率70%Nginx错误日志tail -f /var/log/nginx/error.log确认无upstream timed out血泪经验曾有学生用SELECT * FROM salary_record WHERE emp_id IN (SELECT emp_id FROM emp_info WHERE dept_id?)子查询导致全表扫描。改成JOIN后QPS从8提升到42。5.2 场景2教务系统数据迁移模拟真实对接虽然本次实训不实现对接但需证明你预留了扩展能力。教务处提供emp_basic.csv含工号、姓名、身份证号、学院、专业要求导入到emp_info表。验证步骤编写Python脚本migrate_from_jw.py解析CSV并映射字段import csv import pymysql # 连接MySQL注意用pymysql而非mysql-connector兼容性更好 conn pymysql.connect( hostlocalhost, userhrms, passwordhnust2023, databasehrms, charsetutf8mb4 ) with open(emp_basic.csv, r, encodinggbk) as f: # 教务系统CSV为GBK编码 reader csv.DictReader(f) for row in reader: # 字段映射教务系统学院→人事系统dept_name需先查部门ID dept_id get_dept_id_by_name(row[学院]) # 自定义函数查部门表 sql INSERT INTO emp_info (emp_code, name, id_card, dept_id, entry_date, status) VALUES (%s, %s, %s, %s, %s, 1) ON DUPLICATE KEY UPDATE name%s, id_card%s, dept_id%s cursor.execute(sql, ( row[工号], row[姓名], row[身份证号], dept_id, 2023-09-01, row[姓名], row[身份证号], dept_id ))执行后验证SELECT COUNT(*) FROM emp_info WHERE emp_code LIKE JW%教务系统工号前缀为JWSELECT * FROM emp_info WHERE name张三 AND id_card IS NOT NULL确认身份证号入库5.3 场景3离线部署包制作答辩必备交付物HNUST要求最终提交hrms-deploy.zip解压后执行./deploy.sh即可完成部署。包内必须含deploy.sh自动安装Java 8、MySQL 5.7、启动服务config/含application-prod.yml已填好数据库密码jar/hrms-backend.jarSpring Boot fat jardist/Vue2编译后的index.html及静态资源sql/init.sql建库建表初始化管理员账号deploy.sh核心逻辑#!/bin/bash # 1. 创建数据库 mysql -u root -phnust2023 -e CREATE DATABASE IF NOT EXISTS hrms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 2. 导入初始化SQL mysql -u root -phnust2023 hrms sql/init.sql # 3. 启动后端后台运行 nohup java -jar jar/hrms-backend.jar --spring.profiles.activeprod logs/backend.log 21 # 4. 配置Nginx复制dist到Nginx html目录 cp -r dist/* /usr/share/nginx/html/hrms/ echo 部署完成访问 http://$(hostname -I | awk {print $1}):80/hrms6. 终极技巧用Git Hooks自动生成HNUST实训专属文档答辩材料中《软件工程课程设计报告》占分30%而手写UML图、需求规格说明书极其耗时。我教学生用Git HooksPlantUMLMarkdown自动生成节省8小时以上。6.1 在项目根目录创建.githooks/pre-commit#!/bin/bash # 每次commit前自动生成UML图和需求文档 echo 正在生成UML图... plantuml -tpng -o docs/uml/ docs/uml/*.puml echo 正在生成需求文档... pandoc -f markdown -t html docs/req.md -o docs/req.html --css docs/style.css echo 正在检查代码规范... mvn checkstyle:check -q if [ $? -ne 0 ]; then echo 代码规范检查失败请修复后重试 exit 1 fi赋予执行权限chmod x .githooks/pre-commit6.2 PlantUML用例图示例docs/uml/usecase.pumlstartuml left to right direction actor 管理员 as admin actor 部门经理 as manager actor 普通员工 as employee rectangle 人事管理系统 { [员工信息管理] as emp [部门岗位管理] as dept [考勤录入] as att [薪资计算] as sal [离职审批] as resign [系统管理] as sys admin -- emp admin -- dept admin -- sys manager -- emp manager -- att manager -- resign employee -- emp employee -- att employee -- sal employee -- resign } enduml执行git commit时自动在docs/uml/生成usecase.png直接粘贴到Word报告中。6.3 Markdown需求文档docs/req.md用表格驱动开发| 功能模块 | 用户故事 | 验收标准 | 优先级 | |----------|----------|----------|--------| | 员工信息管理 | 作为管理员我能按部门筛选员工以便快速定位 | 输入部门ID返回该部门所有在职员工列表响应时间1s | P0 | | 离职审批流 | 作为员工我提交离职申请后能看到审批进度 | 提交后状态为待审批部门经理审批后变为已审批HR复核后变为已完成 | P0 | | Excel导入 | 作为HR我导入考勤Excel后系统能自动校验工号是否存在 | 导入文件含不存在的工号时返回错误行号及提示工号XXX不存在 | P1 |用pandoc转成HTML后答辩时直接打开浏览器演示比Word更显专业。我带过的HNUST学生里用这套方法的90%在答辩时被老师追问“这个UML图是用什么工具画的”当听到“Git自动生的”眼神立刻从审视变成好奇——这比讲一百遍设计模式都管用。软件工程的终极价值从来不是写出多炫的代码而是让需求、代码、文档、部署形成一条咬合紧密的齿轮链。当你把deploy.sh双击运行看到浏览器弹出http://192.168.10.10/hrms登录后点击“导出全部员工”Excel瞬间下载完成……那一刻你写的不是代码是能让真实世界运转起来的确定性。希望帮到你。本文还有配套的精品资源点击获取
返回列表