尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于SSM的科研课题征集与发布系统:全流程实战与避坑指南

基于SSM的科研课题征集与发布系统:全流程实战与避坑指南 又到了毕业设计选题的季节“基于SSM的科研课题征集与发布系统”这类标题在各类毕设平台上一搜一大把乍看之下平平无奇但真正动手做过的人会发现这个题目恰好踩中了前后端分离、角色权限、状态流转、动态查询、文件上传这几个最常被考核的高频知识点。我当初就是冲着“业务闭环完整、演示起来不空洞”这个理由选的它从需求分析到最终跑通上线前后折腾了将近两个月中间踩过的坑和想明白的取舍我觉得比项目本身更值得拿出来聊聊。这篇文章会按照我实际推进的顺序把科研课题征集与发布系统从需求梳理、技术选型、数据库设计到后端接口、前端页面、排错实录、论文答辩准备这一整条链路拆开来讲适合正在做相关毕设的同学也适合想拿一个完整前后端项目练手、搞清楚Spring Boot和Vue配合套路的人参考。1. 课题征集系统到底解决什么问题业务流程、角色划分和选题价值1.1 科研课题征集的一整套业务闭环很多同学拿到这个题目后第一反应是“不就是做个增删改查吗”表面看确实是这样但如果你真正去了解高校科研处的日常工作会发现课题征集与发布并不是简单的信息登记它涉及到一条完整的业务链条科研处需要在每年固定时间向各院系教师征集课题选题教师们提交自己愿意指导的课题内容科研处审核这些选题是否合规、是否具备研究价值审核通过后统一发布给学生学生根据兴趣和方向进行申报最后再由教师或科研处确定立项名单。如果把这个流程落到系统里就变成了教师登录后填写课题征集信息保存草稿或直接提交审核管理员查看待审核的课题通过后对外发布学生在已发布的课题列表中选择感兴趣的方向在线提交申报材料教师在课题截止后查看申报列表初步筛选合适的申报者管理员进行最终立项确认形成可导出的立项清单。所以哪怕这个系统不像电商项目那样有复杂的交易环节它的业务闭环依然非常完整覆盖了从内容生产到审核发布再到后续申报的多个阶段每一条数据都有明确的状态变化和归属方这就让整个项目在论文里、在答辩演示中都非常有话可说。1.2 三种角色的权限边界权限设计是这类系统最核心的骨架。我这个项目里一共设计了三种角色分别是管理员、课题负责人教师、学生申报者它们之间的边界非常清晰管理员系统的最高权限方负责用户管理、课题审核、公告发布、立项确认。管理员能看所有课题和所有申报记录但不能代替教师填报课题也不能代替学生提交申报。课题负责人通常是教师角色可以发起课题征集、编辑自己的课题草稿、查看自己课题下的申报情况、推荐立项人选。只能操作自己创建的课题不能看到其他教师的申报细节。学生浏览已发布的课题、筛选学科方向、在线提交申报、查看自己的申报状态。学生没有审核权限也不能随意修改已提交的申报内容。这样的权限边界不复杂但足够形成真实的数据隔离需求后端在写接口时必须在Service层做用户身份和资源归属校验这比单纯靠前端隐藏按钮要严谨得多也是答辩时一个非常容易被追问的点。1.3 为什么这个题目值得做从我自己的实际体验来说选这个题目有几个隐性的好处。首先是业务场景不偏门评审老师一听就懂不需要花太多时间解释业务背景其次是技术点覆盖得很均匀既有CRUD又有状态机流转、多条件分页查询、角色权限控制前端部分也涉及路由守卫、动态表单、组件通信这些面试常问的东西。还有一个很重要的原因是它的边界非常可控哪怕时间紧张先把核心流程跑通后面再慢慢补公告、统计、导出这些锦上添花的功能项目随时可以收尾不容易烂尾。所以如果你正在犹豫要不要选这个题目我的建议是放心选但前提是你必须把业务流程想透再做设计否则就容易变成纯套模板的“空壳系统”演示时经不起问。2. “基于SSM”和Spring Boot不冲突技术选型时最容易被问晕的一个点2.1 SSM与Spring Boot的关系标题写的是“基于SSM”技术栈又出现了Spring Boot很多同学在开题报告里都不知道该怎么表述这两者之间的关系。我先把这个概念理清楚SSM是Spring、SpringMVC、MyBatis三件套的组合称呼而Spring Boot并不是一个取代SpringMVC的新框架它更像是一套自动配置和开箱即用的启动器把Spring和SpringMVC原本繁琐的XML配置全部简化掉同时可以非常方便地整合MyBatis。所以一个“基于SSM”但使用Spring Boot实现的项目本质上仍然是在使用Spring SpringMVC MyBatis这套体系只是把传统SSM整合时那套XML配置改成了Spring Boot的自动配置和注解风格。答辩时如果老师问“你这到底是SSM还是Spring Boot”你可以这样回答项目的底层架构是Spring SpringMVC MyBatis也就是SSM框架Spring Boot负责对这些组件进行自动装配和统一管理所以两种说法都对前者说的是业务框架体系后者说的是开发脚手架。2.2 后端技术栈的具体落地我当时选择的是Spring Boot 2.7.x MyBatis MySQL 8.0数据库连接池用Druid安全认证用JWT加拦截器方案没有引入Spring Security。这样做有很实际的原因Spring Security虽然功能强大但配置复杂、概念多对于毕设这类中小型系统来说学习成本比较高用JWT配合自定义拦截器反而更轻量逻辑也更透明出了问题自己就能控制住。Druid的选择则是冲着它的监控页面去的本地开发时打开监控面板可以看到SQL执行情况排查慢查询会方便很多。还需要注意一个很现实的问题Spring Boot版本不要盲目追新。国内很多教程和资料是基于2.x版本写的直接用3.x可能会遇到javax和jakarta命名空间切换、部分依赖不兼容的问题折腾一轮下来容易心态崩掉。如果是毕业设计选一个社区资料最丰富的版本比选一个最新版本明智得多。2.3 前端选Vue2还是Vue3前端部分我用了Vue2 Element-UI Axios Vue Router的经典组合。为什么不用Vue3主要是因为Vue2的生态配合Element-UI已经非常成熟网上资料最多遇到问题大概率能直接搜到解决方案。Vue3配合Element Plus当然也完全可以而且Vue3的Composition API写起来确实更现代化如果你平时写代码已经习惯了Vue3的写法那直接用Vue3也没有问题。关键不在于选哪个而在于你能不能把项目跑起来、把数据填进去。毕设评审时老师更看重功能演示是否通畅技术栈新旧并不是核心衡量指标。我当时也考虑过要不要用Vue3的组合式API炫一下后来想想还是求稳毕竟Vue2的代码模板一搜一大堆关键时刻能救命。2.4 项目结构与联调方式前后端分离是这个项目的基础形态。我本地开发时前端单独跑一个Node服务端口8080后端跑在8081前端通过Vue CLI的devServer代理把/api开头的请求转发到后端地址这样就避免了浏览器直接跨域访问后端的问题。打包部署时前端执行npm run build生成dist目录既可以扔到Nginx里做静态托管并把接口反向代理到后端也可以直接放到Spring Boot的src/main/resources/static下由后端进程托管。这个项目结构看起来常规但在论文的“系统架构”和“系统部署”章节里非常好写一张前后端分离架构图加一段部署说明就足够了。3. 核心数据模型设计五张表把课题状态机说清楚3.1 用户表与角色设计用户的字段设计直接影响后面所有业务逻辑我这边保留了业务核心字段user_id、username、password、role、real_name、department、email。password字段务必加密存储不要明文写入数据库。很多同学为了演示方便直接存明文虽然系统跑得通但一旦论文被要求代码审查这是很容易被挑毛病的地方。项目中我用的加密方案是Spring Security自带的BCryptPasswordEncoder但并没有引入完整Spring Security框架而是单独把它的加密工具类拿过来用这样既满足了安全要求又不增加额外复杂度。role字段直接存字符串比如MANAGER、TEACHER、STUDENT查询时用字符串比对必要时配合常量类或者枚举统一管理避免魔法值散落各处。3.2 课题表与状态字段课题表是整个系统的核心核心字段包括topic_id、title、summary、field学科方向、requester_id创建课题的教师ID、status、apply_start_time、apply_end_time、create_time、update_time。其中最重要的就是status状态字段我在项目里用Integer存储定义如下0草稿教师保存但未提交1待审核教师提交给管理员2已发布管理员审核通过学生可以申报3已截止超过申报结束时间4已立项所有申报处理完毕5已驳回管理员审核不通过带驳回原因。这个状态机是我在设计阶段花时间最多的地方因为每个状态对应一组允许执行的操作。比如草稿状态只能编辑和提交待审核状态下教师自己不能再改内容管理员只能审核不能编辑已发布状态下不能修改申报时间如果需要延期只能走“修改申请”。这些规则映射到后端Service层就是每一组状态常量的判断代码。3.3 申报表与去重约束申报表字段包括apply_id、topic_id、student_id、content、attachment_path、status、apply_time。status只有两类0已提交、1已通过、2未通过逻辑比较简单。但这张表有一个非常关键的约束同一个学生不能对同一个课题重复申报。这个逻辑既可以在前端做展示层拦截已经申报过的课题显示“已申报”也可以在后端Service层做唯一性校验但最终最可靠的还是数据库层面的约束。我在topic_id和student_id两个字段上加了联合唯一索引这样哪怕前端被绕过、两个请求同时过来数据库也会主动拒绝第二条重复记录这个设计在论文数据库设计章节里是个很好的加分点。3.4 公告表与统计信息公告表字段包括notice_id、title、content、create_by、create_time主要用于科研处向全体用户推送课题征集通知、申报截止提醒等信息。这张表本身逻辑很简单但前台首页和登录后工作台都需要展示最新的几条公告写一个按时间倒序取前五条的接口就够了。统计信息部分我没有单独建统计表而是通过SQL聚合查询实时生成。比如首页的仪表盘需要显示各状态课题数量、各院系申报人数都是对课题表和申报表做GROUP BY统计数据量小的时候性能完全没问题。3.5 状态机设计中的常见错误这个部分是我做了几个小项目之后才总结出来的经验新手非常容易踩状态码设计过于随意。有些人直接用字符串“待审核”“已发布”看起来直观但数据库存储占用大、比对容易拼写出错而且不好加索引。用整数加常量/枚举映射是更稳妥的做法。状态流转没有收敛。没有明确每个状态允许流转到哪些状态导致代码里任何地方都可以随便改状态后期排查问题会怀疑人生。建议把状态变迁收敛到同一个Service方法中所有变更走统一入口。忽略截止时间与状态联动。课题的申报截止时间到了如果没有人去手动点击关闭系统里的状态会一直停留在“已发布”学生还能继续申报。我当时的处理是在查询接口里实时判断当前时间是否超过apply_end_time超过的即使数据库还是2也不允许新的申报写入同时提供一个定时任务把过期课题统一刷新为“已截止”。4. 后端接口落地从征集、审核、发布到申报的完整链路4.1 统一返回结果与全局异常处理项目里的接口返回格式从第一个接口开始就要统一不然前后端联调会非常痛苦。我定义了ResultT类包含code、message、data三个字段正常返回时code200业务异常时code为自定义错误码并且配合RestControllerAdvice做全局异常处理把参数校验异常、业务异常、兜底异常分别映射成对应的Result返回。这样做最直接的好处是前端axios拦截器只需要关注一次响应结构登录过期统一的401处理业务错误统一弹出提示。如果每个接口都各写各的返回格式前端就要埋无数个if else去判断字段是否存在后期维护成本会高到一个难以接受的程度。4.2 JWT登录与拦截器鉴权登录接口逻辑比较常规查询用户校验密码生成JWT返回给前端。关键点在后端如何保护那些需要登录才能访问的接口。我用的是拦截器加自定义注解的方式Component public class JwtInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行预检请求 if (OPTIONS.equalsIgnoreCase(request.getMethod())) { return true; } String token request.getHeader(Authorization); if (token null || !token.startsWith(Bearer )) { throw new BizException(401, 未登录); } // 解析token, 获取userId和role, 存入ThreadLocal LoginUser user JwtUtil.parseToken(token.replace(Bearer , )); UserContext.set(user); return true; } }拦截器注册时我会给不同路径配置不同的规则/api/auth/login和/api/topic/page这类公开接口直接放行/api/admin/**要求必须有管理员角色/api/teacher/**要求教师或管理员角色。学生申报相关接口则要求登录即可。这种做法的好处是权限控制集中、代码清晰而且答辩时你可以把从客户端发来的每个请求都讲出“经过了哪几层处理”这也是面试官非常喜欢听到的细节。4.3 课题征集与审核接口实现课题征集接口的核心不只是把字段插入数据库更重要的是状态机的校验。教师保存草稿走的是POST /api/topic/saveDraft这个接口允许随时调用、不限制次数但一旦提交走的是POST /api/topic/submit/{id}提交前我必须检查这个课题是否存在当前登录用户是不是这个课题的创建人当前状态是否是0草稿否则不允许提交。管理员审核接口类似POST /api/admin/topic/review/{id}请求参数包含approve布尔值和reason驳回原因。状态不是1待审核时直接抛业务异常。审核通过则把状态置为2同时设置申报的开始时间和截止时间驳回则置为5并保存驳回原因教师端课题列表里可以直接看到原因。这套逻辑看起来不复杂但它就是整个系统最核心的业务规则一定要保证状态判断的严密性。4.4 课题申报接口与重复校验学生端的核心接口是POST /api/apply/submit参数包括topicId和content。我在Service层做了三个校验课题必须存在且状态必须是2已发布这个判断实时进行防止时间窗口绕过前端提示当前时间必须在apply_start_time和apply_end_time之间同一学生对同一课题不能重复申报先查数据库再靠数据库唯一索引兜底。前两个校验是业务正确性的底线第三个校验则是体验和一致性的双保险。写这三个校验的时候我发现真正考验后端水平的往往不是接口有多么高大上而是你能否把真实业务中的各种异常情况考虑周全。4.5 MyBatis动态SQL实现多条件分页查询课题列表页是系统里访问量最高的接口它需要支持按标题模糊搜索、按学科方向筛选、按状态筛选、按发布时间排序再加上分页。这个功能用MyBatis动态SQL实现非常顺手select idselectTopicPage resultTypecom.example.entity.Topic SELECT * FROM tb_topic where if testtitle ! null and title.trim() ! AND title LIKE CONCAT(%, #{title}, %) /if if testfield ! null and field ! AND field #{field} /if if teststatus ! null AND status #{status} /if /where ORDER BY create_time DESC /select这里有一个非常隐蔽的坑会在下一章专门展开讲status为0草稿时如果if条件里写的是status ! null and status ! 和Integer的0比较在MyBatis的OGNL表达式中不会报错但会出现你查不到草稿数据的情况。很多同学在这里浪费了两三个小时才发现问题我想说这不是个例几乎每个做这类动态查询的人都会遇到。分页我使用的是PageHelper插件配置好Dialect后只需要在Mapper调用前写一句PageHelper.startPage(pageNum, pageSize)就行后面紧跟的查询方法会自动执行分页返回结果用PageInfo包装给前端。前端拿到total、list、pages等字段渲染表格和分页组件。5. 前端页面与接口联调Vue项目里最重要的几件事5.1 页面与路由规划前端页面的规划跟后端角色一一对应核心路由我设计为/login登录页/layout主框架内部嵌套各功能页面/layout/topic/list课题浏览页所有登录用户可见/layout/topic/detail/:id课题详情页学生在这里申报/layout/myTopics我的课题教师查看自己创建的课题/layout/topic/edit/:id课题编辑/草稿页/layout/review管理员审核列表/layout/applyManage教师查看自己课题下的申报列表/layout/userManage管理员用户管理页/layout/notice公告列表页。路由懒加载是必须的用() import(...)的方式按需加载页面否则打包出来的chunk会非常大首次访问白屏时间会明显变长。5.2 axios封装与token注入axios封装几乎是Vue项目的标配。我在request.js里创建了一个axios实例设置baseURL为/api请求拦截器自动从localStorage取出token放进Authorization头service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) service.interceptors.response.use( res { const data res.data if (data.code 401) { localStorage.removeItem(token) router.push(/login) return Promise.reject(new Error(登录过期)) } if (data.code ! 200) { Message.error(data.message || 请求失败) return Promise.reject(new Error(data.message)) } return data }, err { Message.error(err.message || 网络异常) return Promise.reject(err) } )这样做的直接好处是所有页面组件里不需要再写一堆重复的加载逻辑和错误提示只要调用request.get()、request.post()成功拿到data字段失败统一弹窗代码看起来非常干净。5.3 状态渲染与组件交互课题状态在页面里用el-tag展示不同颜色对应不同状态值前端定义一个映射对象const statusMap { 0: { label: 草稿, type: info }, 1: { label: 待审核, type: warning }, 2: { label: 已发布, type: success }, 3: { label: 已截止, type: info }, 4: { label: 已立项, type: primary }, 5: { label: 已驳回, type: danger } }这里要注意的是状态枚举值前后端必须保持一致我在项目里前后端各维护一份常量并在接口文档里单独列出来。如果前后端状态码对不上页面显示就会错乱。课题详情页最核心的交互是学生申报。我把它设计成一个弹窗表单表单里包含研究方向说明、个人简介、相关经历等字段。提交之前会先调用一个GET /api/apply/check?topicIdxxx的接口判断当前用户是否已经申报过如果有则按钮置灰并显示“已申报”这个交互细节非常提升使用体验。5.4 路由守卫实现角色控制前端路由守卫的主要目的是提升用户体验而不是真正的安全防线真正的安全要在后端控制。我在router.beforeEach里做了三件事判断是否访问白名单页面比如登录页未登录就跳转登录页已登录用户访问登录页时自动跳转到首页根据路由的meta.roles配置判断当前用户角色是否属于允许的角色不属于则跳转403页面。这里有一个细节值得分享不要只根据角色做按钮显隐还要做路由级拦截。比如学生手动输入/layout/review地址路由守卫要让他进不去而不是让他看到一个没有数据权限的空页面。6. 真实排错实录我在这类项目上踩过的四个坑及完整排查链路6.1 MyBatis动态SQL里Integer为0时条件不生效现象按状态筛选课题时选择“草稿”和“待审核”都能查出来选择“已发布”也能查出来唯独选择“草稿”状态状态值为0查出来的列表是空的而且不报任何错误。排查链路我一开始以为是前端传参问题打开浏览器的Network面板看请求参数status0确实已经传给了后端。接着我在Controller里加了日志打印参数接收没有问题。再往下怀疑是SQL没有按预期拼接于是打开控制台里的MyBatis日志发现SQL语句里压根没有AND status ?这一段。这时候我意识到是动态SQL的if判断出了问题。根因if teststatus ! null and status ! 这样的写法在处理Integer时status ! 会触发OGNL把当成0来处理当status0时0 ! 的计算结果为false整个条件被跳过。修复去掉对空字符串的判断只用status ! null因为MyBatis在拼接参数时本身就能处理null值。同理如果是String类型的查询条件可以保留空字符串判断但要分清楚类型的差异。这个坑几乎每个用MyBatis做过动态查询的程序员都遇到过但真正到项目里排查一次之后印象会比看十篇博客都深刻。6.2 后端返回的时间变成数组或格式不对现象课题列表接口返回的applyEndTime字段在前端显示成“2024-01-15T10:30:00.00000:00”有的机器上甚至会显示成数组页面表格里的时间列惨不忍睹。排查链路先看数据库存的时间是正常的yyyy-MM-dd HH:mm:ss再看接口返回的JSON发现字段被序列化成了一长串带T的国际格式。问题出在Jackson序列化LocalDateTime时使用了默认的ISO格式而不是我们约定的格式。修复在application.yml里配置spring: jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT8还需要在实体类的LocalDateTime字段上加上JsonFormat(pattern yyyy-MM-dd HH:mm:ss)注解双保险。如果时间字段较多也可以自定义一个JacksonConfig全局注册JavaTimeModule的序列化器。6.3 Vue打包后刷新404现象本地开发时一切正常但前端执行npm run build后部署到服务器登录页打开没问题跳转路由也正常唯独按F5刷新时出现404。排查链路这个问题是Vue Router的历史模式history模式导致的。history模式下的路由地址是前端模拟出来的服务器上并不存在真实的/layout/topic/list这个路径刷新时浏览器向服务器请求这个地址服务器找不到对应资源就返回404。这就是典型的history模式部署问题。修复有两种解决方式。一种是在后端做统一的转发处理把前端路由匹配不到的后端请求都转发到index.html但这种方式对接口请求有干扰需要排除/api路径另一种更省事的方式是如果项目没有强烈的URL美观需求直接把Vue Router改成hash模式URL里的#虽然不好看但不需要额外配置部署零维护成本。我当时为了图省事选的hash模式如果你确实想要history模式的清爽URL就去Nginx里配try_files $uri $uri/ /index.html;但必须把后端接口的location单独配置好。6.4 跨域问题本地代理与生产环境CORS怎么选现象前端本地开发时直接访问http://localhost:8081/api/login浏览器控制台出现跨域报错请求被拦截。排查链路前后端分离架构下前端运行在8080端口后端运行在8081端口浏览器跨域策略默认拦截了非同源的Ajax请求。这个问题严格来说不是后端错误而是浏览器安全策略的限制。修复本地开发最优雅的方案是配devServer代理而不是在后端开启CORS。在vue.config.js里写devServer: { proxy: { /api: { target: http://localhost:8081, changeOrigin: true } } }这样前端请求/api/login时代理服务器会转发到http://localhost:8081/api/login浏览器看到的请求是同源的不会有跨域问题。但如果前端dist是单独部署在Nginx上的则需要Nginx配置反向代理把/api转发到后端服务效果类似。如果情况特殊只能在后端开CORS那也要配置好allowedOrigin不要直接放开*否则安全性堪忧。很多同学一遇到跨域就想在后端加CrossOrigin注解其实那是最后手段最规范的方式永远是网关层或代理层解决。7. 论文结构与答辩预案代码写完不代表项目结束7.1 论文章节怎么组织课题征集与发布系统的论文结构其实非常成熟我基本是按照学院要求的模板顺序写的绪论、相关技术介绍、系统需求分析、系统设计、系统实现、系统测试、总结与展望。其中重点花心思的是“系统设计”和“系统实现”两章。系统设计里我画了功能结构图、总体架构图、数据库ER图并针对核心表逐一做文字说明尤其把课题状态机设计单独列了一节描述这样评审老师会认为你真的理解业务逻辑而不是机械地复制代码。系统实现章节则按模块划分每个模块采用“功能描述 核心代码 运行界面截图”的组合方式页面截图一定要是跑起来之后的真实效果不要用设计稿或者手绘草图充数。7.2 答辩必问的几个技术点答辩被问到的概率最高的几个问题我提前做了预案为什么用JWT而不用Session答因为项目是前后端分离架构前端部署和API服务不在同一个域名下JWT无状态、可跨域、天然适合分布式场景而Session依赖服务端存储移动端和跨域场景不友好。MyBatis和MyBatis-Plus的区别答MyBatis是基础ORM框架手写SQL更灵活MyBatis-Plus在MyBatis基础上提供了通用Mapper、分页插件、代码生成器简化了单表CRUD开发但复杂查询还是需要手写XML。如果项目里大量单表操作Plus优势明显但面试时也要说清楚它并不是银弹。如果一个课题同时有上万人申报系统怎么保证不重复申报、不超时答数据库唯一索引兜底解决重复申报时间判断在接口层实时校验分页查询通过索引优化必要时在申报表上按课题ID做分区分表。你是怎么做权限控制的答前端路由守卫控制页面可见性后端拦截器加自定义注解控制接口访问再通过在Service层校验数据归属三层结合真正核心的安全性以后端为准。7.3 后续扩展空间如果做完核心功能之后还有富余时间这个项目有不少值得扩展的方向给课题增加附件上传和在线预览功能申报结果生成Excel导出管理员端增加按学院和学科方向的统计图表引入WebSocket做申报状态变更的实时提醒或者把审批流程改成Flowable工作流引擎实现更灵活的流转。我当时选了附件上传这个方向因为课题征集往往需要提交项目计划书、指导老师审核意见等文档用FastDFS或者本地存储加文件表就能实现。这个功能在毕设演示时非常出效果评审老师会直观地觉得系统“完整度很高”。一路做下来我的整体感受是科研课题征集与发布系统看起来只是一个功能明确的业务系统但它把SSM框架、Spring Boot、Vue、权限控制、状态机、动态查询这些关键技术点都串了起来作为毕业设计或者前后端分离的练手项目都非常合适。如果你打算做或者正在做这个题目我建议你在动手写代码之前先花一天时间把业务流程图和数据表关系彻底想清楚把状态机的每一步都写下来这个前期投入会为你省下后面大量的改代码时间。等核心链路跑通之后再去折腾前端细节和锦上添花的功能整个项目的节奏就会稳得多。
返回列表