ARTICLE DETAIL

资讯详情

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

基于SpringBoot+Vue的毕业生实习与就业管理系统开发实践

基于SpringBoot+Vue的毕业生实习与就业管理系统开发实践 每年的毕业季前后高校就业办、二级学院教务科、还有企业HR手里都有一堆剪不断理还乱的实习和就业数据学生签了哪家公司、实习到岗没有、周报交没交、三方协议盖没盖章、最终就业率怎么统计这些信息长期分散在Excel表格、微信群聊天记录和各个老师私人的小本本里。毕业生实习与就业管理系统就是要把这条断掉的信息链重新接起来。这篇文章围绕基于SpringBootVueMyBatis架构、MySQL数据库的完整项目把从需求梳理、数据库设计、前后端实现到部署排错的完整思路拆开讲清楚既可以当作毕业设计项目的参考范本也可以直接对标中小型企业管理系统的开发套路适合正在做相关开发、或者准备入门Java全栈项目的同学收藏。1. 系统定位与需求拆解先别写代码把业务流程画明白很多人拿到这个题目第一反应是建表、写接口、画页面但真正在企业里被反复使用的实习就业管理系统第一步一定不是技术选型而是搞清楚“谁在用、用哪些功能、数据在哪些角色之间流转”。这套系统的典型使用方至少有四类角色管理员、学生、教师辅导员或校内导师、企业端HR。四类角色对系统的诉求完全不同功能模块自然也不能混在一起。1.1 四类角色的业务痛点与功能诉求管理员关心的是全校或全院的宏观数据总共有多少学生参与实习、实习单位分布在哪、专业对口率如何、最终就业率是多少。这些数据以前靠辅导员逐班汇报再人工汇总周期长、口径还不统一。系统里必须给管理员提供看板和自定义报表比如按院系、按专业、按年级统计实习率和就业率能一键导出Excel上报。学生端就简单直接核心是找岗位、投简历、签协议、提交实习周报、登记就业信息。学生最怕的是“投了没下文”所以流程上必须让每个申请都有明确状态待审核、面试中、已通过、已拒绝每一步都留痕。教师端则是审核和跟进审核学生提交的实习申请、批阅周报、对实习过程进行评价同时能快速看到自己所带班级的实习进度和异常情况。企业端发布实习岗位、查看学生投递记录、确认录用以及后续对实习生的评价反馈。1.2 核心业务闭环从岗位发布到就业确认梳理这套系统的主线业务会发现它是一条完整的闭环企业发布岗位、学生浏览岗位并投递简历、企业审核并录用、学生和企业在线上确认实习关系、实习期间学生提交周报、企业导师给出评价、实习结束之后学生登记就业信息、管理员统计就业数据。任何一个环节断掉前面的数据就失去了价值。所以做技术方案的时候我在设计上特别强调“状态机”思想。比如投递申请的状态要经历“已投递→企业已查看→面试中→已录用/未通过”实习记录的状态要经历“待开始→进行中→已完成/已终止”就业信息的状态则是“待确认→已确认”。状态字段用tinyint整数存储配合数据字典表做中文解释既节省存储空间又方便扩展。很多刚入行的同学喜欢直接存中文状态看起来方便后面改状态名称、加国际化、做统计筛选的时候就会非常痛苦。1.3 功能模块边界划分具体到功能模块可以拆成系统管理、企业信息管理、岗位管理、实习申请管理、实习过程管理、就业管理、统计报表七个大模块。系统管理模块包含用户管理、角色权限、菜单管理企业信息管理包含企业注册、资质审核、企业信息维护岗位管理包含岗位发布、上下架、截止日期预警实习申请管理是学生投递和企业审核的交互区实习过程管理包含协议管理、周报提交与批阅、实习评价就业管理包含就业信息登记、就业协议上传、审核确认统计报表则是用图表把多维度的数据展示出来。这里有一个容易被忽略的模块操作日志。管理员改了什么配置、老师审核了哪个学生的申请、企业下架了哪个岗位最好都记录在案。虽然开发阶段多花一点时间但系统上线后出现纠纷时日志就是最有力的证据。2. 技术选型逻辑为什么是SpringBootVueMyBatisMySQL这套技术组合在国内的中小企业级项目里属于绝对主流选择它不是因为它多先进而是因为它能在“开发效率、维护成本、招聘人才、部署难度”四个维度上取得很好的平衡。SpringBoot负责后端服务的快速搭建内置Tomcat容器打包成Jar就能跑Vue负责前端交互组件化开发方式让多人协作时互不干扰MyBatis负责数据库操作灵活控制SQLMySQL则作为数据存储的底座免费、云上云下到处都能跑。2.1 后端为什么选SpringBoot而非SSH或SpringMVC早年间做这种项目常用SSHStruts2SpringHibernate或者SpringMVCJPA现在再这么做显然不明智。SpringBoot把繁琐的XML配置改成了自动配置和注解驱动一个main方法就能启动整个Web服务。做实习就业管理系统这种包含大量增删改查和业务状态流转的项目SpringBoot的starter机制能极大简化依赖管理比如spring-boot-starter-web内置了SpringMVC和Jacksonspring-boot-starter-security可以做认证授权mybatis-spring-boot-starter则把MyBatis无缝接进Spring容器。SpringBoot 2.7.x和3.x之间有个坑需要提醒3.x从javax包迁移到了jakarta包很多老项目代码直接升级会编译报错。如果选择拥抱新版本需要在依赖里把旧的starter换成官方新坐标同时注意mybatis-spring-boot-starter要用2.3.x以上甚至3.x版本以兼容SpringBoot 3。对业务型项目来说如果团队不熟悉新生态稳稳用2.7.x反而是务实的选择。2.2 前端为什么选Vue而不是其他框架Vue在国内的统治力毋庸置疑尤其是Element UI或Element Plus配合起来做后台管理界面一周之内就能搭出像样的页面。和React相比Vue的模板语法更贴近传统HTML学习曲线平缓后端工程师临时顶前端开发也不会太难。我选择Vue 2 Element UI还是Vue 3 Element Plus关键看团队已有组件库和生态积累新项目建议直接用Vue 3Composition API让逻辑复用能力提升不少但如果只是做快速实现Vue 2的写法也足够稳妥。做这个项目的时候前端目录直接按业务模块划分比如views/admin、views/student、views/teacher、views/enterprise每个页面一个文件夹里面放index.vue和配套的api.js。这样做的最大好处是权限控制容易做登录后根据用户角色动态加载路由表不同角色根本看不到不属于自己的页面入口比单纯用v-if在页面上控制要安全得多。2.3 MyBatis为什么比JPA更适合这种业务场景实习就业管理系统免不了大量报表查询、多表关联、条件动态拼接MyBatis把SQL完全交给开发者掌控写出的查询可以精确到每一个字段。JPA的Hibernate确实能做自动建表和对象关系映射但一旦业务查询复杂起来自动生成的SQL往往不可控调优非常痛苦。MyBatis配合XML文件管理SQL既保留了SQL的直观性又能用动态标签解决多条件查询的难题。另外MyBatis和MySQL的配合有一个天然优势可以用Mapper接口扫描方式省去大量DAO实现类配合MyBatis-Plus的话还能获得内置的单表CRUD、分页插件和代码生成器。如果标题里的“MyBatis架构”指的是原生MyBatis我建议在项目里适当引入MyBatis-Plus做单表操作复杂查询仍然走XML这样开发效率直接翻倍。3. 数据库设计整套系统的底盘直接决定报表好不好写数据库表设计是这个项目里最不能赶工的部分。我的经验是先把ER图和表结构画出来对着业务流程图逐条核对确认无误后再动代码。如果表结构一开始就歪了后续十有八九要返工。3.1 核心业务表拆分与关联关系整个系统围绕“人员”和“过程”两条主线展开。人员线是用户表、角色表、用户角色关联表、学生信息表、教师信息表、企业信息表过程线是岗位表、投递申请表、实习记录表、周报表、就业信息表。两条线通过外键关联用户表的主键ID关联学生信息表的student_id岗位表的enterprise_id关联企业信息表的id投递申请表同时关联student_id、position_id、enterprise_id三个关键外键。用户表的设计我建议直接用逻辑删除不要物理删除因为用户一旦关联了投递记录、实习记录它的历史数据必须保留。表里加deleted字段查询时统一加deleted 0条件。学生、教师、企业这些扩展信息可以单独建表通过user_id与主用户表关联这样角色扩展时主表不用动。CREATE TABLE sys_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 主键, username VARCHAR(50) NOT NULL COMMENT 登录账号, password VARCHAR(100) NOT NULL COMMENT BCrypt加密后的密码, real_name VARCHAR(50) COMMENT 真实姓名, phone VARCHAR(20) COMMENT 手机号, email VARCHAR(100) COMMENT 邮箱, avatar VARCHAR(255) COMMENT 头像URL, status TINYINT DEFAULT 1 COMMENT 状态1启用 0禁用, deleted TINYINT DEFAULT 0 COMMENT 逻辑删除标记, create_time DATETIME COMMENT 创建时间, update_time DATETIME COMMENT 更新时间, UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户表;角色表里存role_code和role_name然后通过user_role表把用户和角色关联起来。这样设计比在用户表直接存一个role_code字段更规范将来如果出现一个用户既是学生又是助管的情况也能轻松支持。实际项目里我遇到过直接在用户表加角色字段的情况当时觉得省事后来要做细粒度权限的时候只能重构。3.2 状态字段、数据字典与枚举规范状态字段是业务系统最容易混乱的地方。我的做法是状态一律用整数存储然后在Java代码里定义枚举常量比如投递申请状态0已投递、1已查看、2面试中、3已录用、4未通过、5已撤回。这样数据库里存的是紧凑整数查询和索引效率高Java代码里通过枚举解释界面上再通过数据字典转成中文显示。数据字典表dict_type和dict_data要尽早做进去。岗位类型、专业方向、实习单位性质、就业形式、学院名称等等这些“可枚举但可能变化”的数据都放进数据字典而不是写死在代码里。举个例子企业的行业分类今天是“互联网”明天可能新增“人工智能”如果写死在代码里就得发版放进数据字典管理员在后台自己就能维护。实习记录表的状态也需要重点设计CREATE TABLE internship_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_id BIGINT NOT NULL, position_id BIGINT NOT NULL, enterprise_id BIGINT NOT NULL, school_tutor_id BIGINT COMMENT 校内指导教师ID, company_tutor_name VARCHAR(50) COMMENT 企业导师姓名, company_tutor_phone VARCHAR(20) COMMENT 企业导师电话, start_date DATE COMMENT 实习开始日期, end_date DATE COMMENT 实习结束日期, status TINYINT DEFAULT 0 COMMENT 状态0待开始 1进行中 2已完成 3已终止, evaluate_score DECIMAL(4,2) COMMENT 实习评分, evaluate_content VARCHAR(500) COMMENT 实习评价, create_time DATETIME, update_time DATETIME, KEY idx_student (student_id), KEY idx_enterprise (enterprise_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT实习记录表;3.3 报表统计的SQL设计思路管理员最关心的就业率报表如果数据库设计不合理SQL会写得非常痛苦。我在设计时会在就业信息表里冗余一个student_id和college_id字段避免多表关联太深。统计SQL使用GROUP BY配合CASE WHENSELECT college_name, COUNT(*) AS total_students, SUM(CASE WHEN employment_status 1 THEN 1 ELSE 0 END) AS employed_count, ROUND(SUM(CASE WHEN employment_status 1 THEN 1 ELSE 0 END) / COUNT(*) * 100, 2) AS employment_rate FROM employment_info WHERE graduation_year #{year} GROUP BY college_name;这里要提醒一点不要在where条件里对字段做函数运算比如WHERE YEAR(create_time) 2025这样会导致索引失效。正确的做法是传日期范围。我在项目里也遇到过统计时要把状态枚举转成中文的情况用JOIN数据字典表或者CASE WHEN都可以数据量小的时候无所谓数据量大就优先考虑在SQL里转换还是代码里转换避免多层嵌套子查询。4. 后端核心功能实现认证、权限、业务流程、动态SQL后端编码阶段我会按照Controller→Service→Mapper的结构自上而下地实现业务。这个项目最核心的公共能力是登录认证和权限校验所有接口都要过这一层所以先把它做扎实后面写业务接口就是水到渠成的事。4.1 JWT登录认证与接口权限控制现在的VueSpringBoot前后端分离项目基本都用JWT做认证。用户在登录接口输入账号密码后端校验通过后生成一个包含用户ID、用户名、角色编码的Token返回给前端前端存在localStorage里每次请求在Authorization头带上Bearer Token后端过滤器解析Token后把用户信息放入ThreadLocal。JWT的HS256签名需要配置一个密钥注意不能写死在代码里要放在application.yml里甚至用Jasypt对yml里的敏感信息进行加密。SpringBoot的yml密文配置可以参考这个思路引入jasypt-spring-boot-starter把数据库密码等敏感信息加密后配置运行环境通过环境变量传入解密密钥。拦截器的核心逻辑是判断请求路径是否为白名单如果是登录、验证码、文件下载等接口就放行否则解析Token无效或过期则返回401。权限控制上简单项目可以用自定义注解RequireRole(ADMIN)加在Controller方法上拦截器里读取方法注解并比对当前用户角色比引入完整的Spring Security配置要轻量得多。public class JwtAuthenticationInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { HandlerMethod method (HandlerMethod) handler; RequireRole requireRole method.getMethodAnnotation(RequireRole.class); String token request.getHeader(Authorization); if (token null || !token.startsWith(Bearer )) { throw new BusinessException(401, 未登录或登录已过期); } // 解析token并校验角色 Claims claims JwtUtil.parseToken(token.replace(Bearer , )); Long userId Long.valueOf(claims.get(userId).toString()); String roleCode claims.get(roleCode).toString(); UserContext.set(new LoginUser(userId, roleCode)); if (requireRole ! null !requireRole.value().equals(roleCode)) { throw new BusinessException(403, 无权限访问); } } return true; } }4.2 实习业务流程的状态机设计与实现实习申请流程是系统的核心业务。学生端提交申请后生成一条待审核记录企业端HR看到投递列表可以标记“已查看”然后走面试流程录用通过后系统自动生成实习记录状态为“待开始”到了开始日期转为“进行中”这时候学生才可以提交周报。状态流转必须只能按预定顺序走不能让学生从“已投递”直接跳到“已完成”。实现状态机时我用了Service层校验状态流转方法的方式每个状态变更都对应一个独立的Service方法比如apply()、review()、sign()、start()、complete()。方法内部先校验当前状态是否符合条件再更新状态字段。这样写出来的代码逻辑清晰后续加“撤回”“终止”等操作也只需要新增方法不会影响已有逻辑。还要考虑并发问题。如果学生同时提交两次申请或者企业和学生同时操作同一条记录不加锁可能产生脏数据。这里用乐观锁最省事在投递申请表加version字段更新时带上WHERE version #{oldVersion}如果影响行数为0则提示“操作冲突请刷新后重试”。比数据库行锁实现简单而且对性能影响小。4.3 MyBatis动态SQL多条件岗位筛选实战岗位列表页要支持按关键词、工作城市、岗位类型、薪资范围、发布日期等多条件筛选并且这些条件都可以留空。如果给每个条件组合写一个SQL工作量爆炸且难维护。MyBatis的 和 标签就是为这种场景设计的。组合查询时需要注意如果使用List接收数据量较大分页不能只用MySQL的LIMIT需要配合PageHelper或者手写分页参数。我建议统一用一个PageQuery对象接收页码、每页条数、排序字段返回PageResult 前端表格和分页组件直接对接。select idselectPositionPage resultMapPositionResultMap SELECT p.*, e.enterprise_name, e.enterprise_type FROM job_position p LEFT JOIN enterprise_info e ON p.enterprise_id e.id where p.deleted 0 if testkeyword ! null and keyword ! AND (p.position_name LIKE CONCAT(%, #{keyword}, %) OR e.enterprise_name LIKE CONCAT(%, #{keyword}, %)) /if if testcity ! null and city ! AND p.city #{city} /if if testpositionType ! null and positionType ! AND p.position_type #{positionType} /if if testminSalary ! null AND p.salary_max gt; #{minSalary} /if /where ORDER BY p.publish_time DESC /select新手在写这种SQL时最容易犯的错误是and拼接位置错了。用 标签能解决第一个条件前多余的AND但要注意 里的条件不要写WHERE关键字。另外区间条件尤其要小心筛选薪资时可能遇到没有上限或者没有下限的数据最好在SQL里加NULL判断。4.4 文件上传简历、协议、实习证明统一管理学生投递简历、上传三方协议、企业上传营业执照都离不开文件上传功能。SpringBoot的MultipartFile可以直接接收文件我建议在项目里封装一个统一的FileService支持本地存储和对象存储两种模式通过配置文件切换。开发环境用本地存储生产环境切OSS或者MinIO业务代码不用改动。文件上传有两个容易踩的坑一个是上传大小限制SpringBoot默认单个文件最大1MB需要手动调大另一个是文件存储路径的安全不能把上传目录放在前端dist目录下否则别人直接访问路径就能下载文件。我把上传文件统一放到/opt/files目录通过一个download接口做访问控制只有登录用户才能下载既方便权限控制也好做后续的病毒扫描和审计。批量上传Excel导入学生信息也是一个高频需求。用EasyExcel读Excel比传统POI简单很多定义一个StudentImportDTO配上ExcelProperty注解一行代码就能读取整个Sheet。导入逻辑要先做数据校验学号是否重复、姓名是否为空、格式是否正确把错误行和错误原因收集起来返回前端而不是导入到一半直接报错。5. 前端Vue端实现要点从页面骨架到权限收敛前端这块我采用标准的Vue CLI或Vite工程配合Vue Router、Vuex或Pinia、Axios、Element UI整体分成API模块、路由模块、状态管理模块、页面组件四层。目录结构从开始就按业务域划分好学生端、教师端、企业端、管理端的页面分开存放路由懒加载保证首屏加载速度。5.1 动态路由与页面权限控制权限控制不能只靠后端拦截前端也要做对应收敛。用户登录后拿到角色编码前端根据角色编码动态注册该角色可见的路由。在Vue Router里meta字段标记路由需要的角色列表router.beforeEach里判断当前用户角色是否有权限进入目标路由。动态路由的实现要小心一个问题刷新页面后路由表会丢失。解决办法是把用户信息持久化到localStorage或Pinia并配合持久化插件刷新后重新从localStorage加载用户信息和动态路由。这个坑我踩过好多次如果不做持久化用户一刷新就被踢回登录页体验非常糟糕。5.2 Axios封装统一处理Token、错误码和下载前端的Axios实例需要一个统一封装请求拦截器负责追加Token响应拦截器负责处理业务错误码和HTTP 401状态。我的项目里约定后端返回统一结构{code: 200, message: success, data: ...}前端拦截器遇到code 200才返回data遇到401就清除本地Token并跳转登录页。文件下载也是一个容易出错的地方。如果直接用axios的responseType: blob下载文件后端返回错误信息时前端无法正常读取JSON。我的做法是在响应拦截器里先判断Content-Type如果是application/json说明后端返回了错误对象需要解析错误信息并提示用户如果是application/octet-stream说明是文件流直接触发浏览器下载。5.3 ECharts数据可视化就业看板实现管理员首页的就业数据看板是整个系统最直观的亮点。我用ECharts做三个核心图表就业率趋势折线图、实习单位行业分布饼图、薪资区间条形图。原则上后端返回统计好的JSON数据前端只负责渲染不要在ECharts的回调里再做数据聚合那样性能差且逻辑混乱。图表数据接口的设计要注意维度扩展。管理员可能按学院、按专业、按年级看数据所以接口参数里预留一个groupBy字段后端通过Switch或策略模式决定按哪个字段分组前端下拉切换时重新请求数据。这种设计在需求评审时可能觉得很麻烦但上线后老师们要各种维度报表时就会感谢当初的远见。5.4 路由参数传递与页面状态保持学生在岗位列表页点击某一岗位跳转到详情页需要把岗位ID传给详情页。Vue Router可以用路径参数或query参数传递比如/position/detail/:id在详情页通过route.params.id获取。这里要注意刷新页面时参数会不会丢路径参数通常不会丢query参数会保留在URL里也不会丢但如果是通过内存状态传递刷新后就没了必须避免。列表页到详情页再返回列表页经常需要保持之前的搜索条件和页码。最简单的方案是用KeepAlive缓存列表页组件配合vue-router的meta.keepAlive标记。做的时候也要注意不同角色进入同一个列表页的缓存问题避免管理员看了一班数据切到二班还是旧数据必要时在离开页面时清除缓存。6. 项目部署与常见问题排查从本地到服务器项目开发完成后要落地运行部署环节最容易出幺蛾子。我整理了一份本地与服务器的环境准备清单和典型问题排查记录照着走能省去不少时间。6.1 本地环境搭建与项目启动顺序开发环境需要Node.js 14、JDK 1.8或17、Maven 3.6、MySQL 8.0。MySQL安装完之后要注意字符集设置为utf8mb4否则中文乱码。导入数据库脚本时用source命令或者客户端执行init.sql。后端启动前先确认application.yml里的数据库账号密码、端口配置正确。实际启动顺序是先启动MySQL然后启动后端SpringBoot应用最后启动前端。如果用的是Vue CLI前端通过npm run serve启动开发服务器配置devServer.proxy把/api开头的请求转发到后端的8080端口从而避免开发环境跨域问题。如果直接把前端打包后的dist目录放到Nginx就要在Nginx里配置反向代理。6.2 跨域、端口占用、数据库连接的经典报错跨域是前后端分离项目最常见的第一个拦路虎。开发阶段可以用前端代理解决但生产环境部署后如果前后端在不同域名下就必须在后端配置CORS。我建议写一个全局CorsFilter允许的域名不要用*应该限定为公司自己的前端地址否则存在安全隐患。端口占用也是常见问题。8080被占了报错信息会很明确Port 8080 was already in use。Windows下用netstat -ano | findstr 8080找到占用进程然后taskkill /pid 进程号 /fLinux下用lsof -i:8080kill掉就行。MySQL连接还有一个高频问题时区导致的报错。连接串里不加serverTimezone参数驱动会报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized。解决办法是连接串写成jdbc:mysql://localhost:3306/internship?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai。顺便把useSSL设置成false避免本地环境证书报错。6.3 MyBatis配置与SQL排查技巧MyBatis的mapper接口和XML文件绑定不上的报错一般是namespace写错或者接口方法名与XML里的id不一致。排查时先看启动日志MyBatis每次启动都会打印加载了哪些mapper XML如果没打出来就是扫描路径配置有问题。开发调试阶段强烈建议开启MyBatis的SQL日志在application.yml里配置mapper层日志级别为debug控制台就能打印出完整SQL和参数。看到一个很实用的技巧用IDEA的MyBatis Log插件能把带?占位符的预编译SQL直接还原成带真实参数的SQL复制到Navicat里就能执行排查问题效率高很多。logging: level: com.example.internship.mapper: debug6.4 部署方案SpringBoot打包与Nginx静态资源托管后端打出可执行Jar包mvn clean package -DskipTests。服务器上直接java -jar internship.jar启动生产环境建议用systemd守护进程管理日志统一输出到指定文件崩溃后自动重启。dist目录是前端构建产物放到Nginx站点目录下并配置将/api路径反向代理到后端本地端口。server { listen 80; server_name your-domain.com; root /opt/internship/dist; index index.html; location /api/ { proxy_pass http://127.0.0.1:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { try_files $uri $uri/ /index.html; } }Vue是单页应用刷新子路由时如果没有try_files配置Nginx会返回404这是个部署界经久不衰的经典坑。把try_files $uri $uri/ /index.html这个配置加上所有前端路由都回退到index.html由前端路由自己解析。6.5 其他值得记录的常见问题我在测试过程中还遇到过这些常见问题。学生上传的简历文件名包含中文在部分浏览器下载时出现乱码需要对Content-Disposition里的文件名做URL编码处理。前端导出Excel表格如果数据量超过Excel的单sheet行数上限要分sheet导出或者提示用户筛选条件后重新导出。角色权限方面学生账号异常情况下可能看不到已投递的岗位大多因为前端动态路由缓存了旧的用户信息退出登录时必须清空localStorage里的所有用户相关key然后跳转登录页。管理员修改了用户的角色后如果用户已经登录需要提示重新登录才能生效。密码安全问题也不能忽视。数据库里的密码不能明文存储用BCrypt加密后再存。用户首次登录后建议强制要求修改初始密码否则设置一个“用户管理”时如果有人用自己的手机号注册注册成功后的初始密码如果是固定值很容易被爆破。7. 规避重复造轮子项目后续扩展与二次开发建议项目做到这个程度核心闭环已经完整但离“企业级商用”还有一段距离。如果这个系统要在更严格的业务环境里落地以下方向值得继续投入也会让项目含金量明显提升。消息通知机制是第一个值得扩展的点。学生投递简历后企业HR没有及时查看系统可以在24小时后自动给企业端推送提醒学生提交的周报到了截止时间未交给辅导员推送预警。实现上可以用SpringBoot的定时任务扫描待办数据通过邮件或短信渠道推送。我把这套机制做成了单独的通知服务和业务模块解耦后续接入企业微信、钉钉机器人也很方便。移动端适配是第二个方向。实习期间学生和HR都经常在外面不可能一直盯着电脑。更理想的方案是在现有Vue项目的基础上用Vant或NutUI做一套移动端H5页面针对性砍掉复杂报表保留岗位浏览、投递、周报提交、审核审批这些高频操作。这样数据和权限模型完全复用现有后端接口开发量会小很多。自动建表与定时备份也值得考虑。开发环境频繁调整表结构时可以在项目启动时用MyBatis检查表是否存在不存在就自动执行建表脚本。生产环境则建议开启MySQL的binlog配合mysqldump做每日全量备份和实时增量备份。数据库是系统的命根子备份这件事再怎么做都不为过。这个项目从头到尾做完我最大的体感是真正的复杂度不在一个接口怎么写得花哨而在业务状态怎么流转、数据怎么沉淀、角色权限怎么收敛。把这几点想清楚SpringBootVueMyBatis这套组合能稳定承接大多数中小型管理系统而且源码结构清晰、可维护性高后续往大型架构演进也有明确方向。
返回列表