☰
2026届毕设:SSM+Vue军队任务管理系统开发全攻略
2026/10/18 4:58:23 网站建设 项目流程

每到毕业设计季,任务管理系统几乎是出现频率最高的一类选题。今天要聊的是这个2026届的SSM+Vue军队任务管理系统,它既包含了管理系统最通用的套路(登录、权限、CRUD、报表),又带有特定业务场景下的差异化设计(任务层级、状态流转、过程留痕)。如果你正打算做类似的选题,或者导师指定了SSM技术栈但你还不知道怎么拆解,这篇内容应该能帮你省不少时间。

先说结论:这类系统并不复杂,但想拿高分,关键不在于代码量,而在于你是否把“为什么这样设计”想清楚了。用SSM+Vue做前后端分离,本质上是在用最经典的方式还原一个真实项目的前后端交互流程。做完这套东西,你对接口设计、数据库表关系、权限控制的理解都会比上课时要立体很多。

1. 项目背景与需求拆解

1.1 毕设选题为什么值得做

任务管理系统属于典型的管理信息系统,开发难度适中,但业务逻辑比单纯的增删改查要丰富。军队任务管理系统不是普通OA里的待办事项,它更强调任务的严肃性、时效性和分级管理。但在毕业设计这个尺度下,我们不需要接触真实的军事业务,只需要把“任务管理闭环”做完整:创建任务、逐级下发、接收确认、进度上报、验收归档。

我见过不少同学的思路是把功能铺得很大,比如做视频会议、即时通讯、地图定位,结果数据库设计混乱,答辩时被老师一个问题问倒。这个选题更合适的做法是把任务管理的主线做扎实,再加上组织架构、用户权限、统计报表这些支撑功能,已经足以撑起一篇合格的毕业论文。

适合的人群也很明确:后端课设主要用了SpringMVC和MyBatis、前端了解Vue基础语法、希望在毕设中完整走一遍前后端分离流程的同学。它不需要高深算法,也不需要分布式中间件,但对你的工程习惯要求比较高。

1.2 核心功能边界

在动手写代码前,一定要先把功能边界画清楚。我建议按角色来拆需求,因为任务系统的操作路径是跟着角色走的。

角色核心操作
管理员部门管理、用户管理、任务类型维护、系统数据统计
任务发布人创建任务、下发任务、查看进度、验收任务、退回整改
任务执行人查看待办任务、接收任务、上报进度、申请验收
普通查阅人查看任务详情、任务状态、相关通知

从需求到功能列表,可以整理为几个模块:

  • 用户登录与个人中心:身份认证、修改密码、查看个人名下任务。
  • 组织架构管理:部门与管理员的关联,用户归属部门。
  • 任务管理:任务发布、任务下发、任务接收、进度上报、任务验收、任务退回。
  • 任务日志:记录任务从创建到结束的所有关键动作。
  • 附件管理:上传文件、下载文件、删除文件。
  • 数据统计:按任务状态统计、按部门统计、按时间趋势统计。

这里的核心不是页面多好看,而是状态流转。任务必须有一条清晰的状态线:待下发 → 已下发 → 已接收 → 进行中 → 待验收 → 已完成,中间还要有“已退回”这个分支。后续代码里几乎所有核心逻辑都是在维护这条线。

2. 技术选型与架构设计

2.1 为什么用SSM+Vue而不是SpringBoot+Vue

这是个老生常谈的问题。SSM代表Spring、SpringMVC、MyBatis,是JavaWeb课程里最经典的组合。SpringBoot确实更省事,省去了大量XML配置,但很多高校的课程还是以SSM为主,或者导师指定必须用SSM。站在学习角度,SSM能让你更清楚地看到Spring容器、SpringMVC拦截器、MyBatis代理这些底层概念在实际项目中是怎么被使用的。

在我做过的项目里,用SSM写任务系统最大的感受是:配置虽然繁琐,但出了问题更容易排查,因为每个环节都是显式的。比如事务管理,在applicationContext.xml里配置事务管理器,再通过aop配置切点,一眼就能看出哪些方法需要事务;换成SpringBoot后只是注解更简洁,反而少了这个理解过程。

前端选Vue是必然的,因为Vue在数据绑定、组件化、路由控制上比原来的JSP+JQuery体验好太多。前后端分离后,后端只负责返回JSON,前端通过Axios调用接口,分工清晰。同时Vue CLI开发环境自带代理,可以完美解决接口跨域问题。

2.2 项目目录与前后端分层

后端目录结构建议按“控制层-服务层-数据访问层”三层组织,严格做到Controller不写SQL、Service不写请求参数判断、Mapper只负责数据库操作。

backend ├── src/main/java │ ├── cn/xxx/controller # 接收请求、返回JSON │ ├── cn/xxx/service # 业务逻辑层 │ ├── cn/xxx/mapper # MyBatis接口 │ ├── cn/xxx/entity # 数据库实体 │ ├── cn/xxx/vo # 视图对象,用于前后端数据交互 │ ├── cn/xxx/interceptor # 登录和权限拦截器 │ └── cn/xxx/util # 通用工具类 └── src/main/resources ├── mapper # MyBatis XML文件 ├── spring-mvc.xml ├── spring-mybatis.xml └── jdbc.properties

前端目录用Vue CLI默认脚手架,重点在src/views下按模块分页面,src/api下封装接口请求。很多同学喜欢把接口地址直接写在页面里,前期方便,后期一改后端地址就得全局替换。建议把所有请求统一放在api模块里,例如task.js、user.js、login.js,每个页面按需引入。

2.3 数据库表设计要点

数据库是这类系统的地基,表设计决定了后面开发的顺畅程度。我建议至少包含下面几张表:

表名关键字段说明
sys_userid, username, password, real_name, dept_id, role_id用户表,密码不要存明文
sys_deptid, dept_name, leader_name, parent_id部门表,支持树形结构
sys_roleid, role_name, role_key角色表
task_infoid, task_code, task_name, task_content, publisher_id, executor_id, status, create_time, finish_time任务主表
task_logid, task_id, operate_user, operate_action, operate_time, remark任务操作日志表
task_fileid, task_id, file_name, file_path, upload_time附件表

task_info里的status字段建议用字符串类型保存状态编码,例如0待下发、1已下发、2已接收、3进行中、4待验收、5已完成、6已退回。用数字或者字符串都行,但一定要在系统里统一定义常量,不要散落在业务代码里。

很多人会忽略task_log表,但答辩时这张表非常加分。它记录每一次操作动作,形成了任务流转的完整证据链。比如某个任务被退回了,谁在什么时候退的、理由是什么,都能查得清清楚楚。这个设计思路也可以顺手写进论文里的“系统设计特色”章节。

3. 核心功能落地实现

3.1 登录鉴权与权限模型

SSM项目最常见的做法是登录成功后把用户对象放进Session,再写一个拦截器判断是否登录、是否有权限。虽然现在有JWT、Spring Security这些方案,但毕设用Session+拦截器完全够用,而且更容易解释。

先定义一个权限常量:

public class RoleConstants { public static final String ADMIN = "admin"; public static final String PUBLISHER = "publisher"; public static final String EXECUTOR = "executor"; public static final String VIEWER = "viewer"; }

登录接口里验证用户名密码后,将用户的关键信息放进Session:

@RequestMapping("/login") @ResponseBody public Result login(String username, String password, HttpSession session) { String encodedPassword = Md5Util.md5(password); User user = userService.login(username, encodedPassword); if (user == null) { return Result.error("用户名或密码错误"); } session.setAttribute("loginUser", user); return Result.success(user); }

这里特别提醒一点:密码不要用明文保存,至少也要做MD5加盐。如果你论文里能写出来使用了BCrypt或者加盐MD5,比单纯写“登录功能”要高一个档次。

然后写一个拦截器,在SpringMVC配置里注册,拦截所有需要登录的请求:

public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); User loginUser = (User) session.getAttribute("loginUser"); if (loginUser == null) { response.setContentType("application/json;charset=utf-8"); response.getWriter().write("{\"code\":401,\"msg\":\"未登录\"}"); return false; } // 更细的权限校验可以在这里根据request.getRequestURI()判断 return true; } }

前端Vue里也要配合做路由守卫,未登录时跳转到登录页:

router.beforeEach((to, from, next) => { if (to.path === '/login') { next(); } else if (!sessionStorage.getItem('user')) { next('/login'); } else { next(); } });

3.2 任务发布与状态流转

任务系统的核心是状态机,一个好的状态机设计会让代码少很多if-else。我是这么设计的:

  • 状态0:待下发,任务刚创建,执行人不可见。
  • 状态1:已下发,任务推送给执行人,等待接收。
  • 状态2:已接收,执行人确认任务,还未开始。
  • 状态3:进行中,执行人开始任务,可多次上报进度。
  • 状态4:待验收,执行人申请验收,发布人确认。
  • 状态5:已完成,验收通过,任务归档。
  • 状态6:已退回,发布人验收不通过,退回给执行人。

状态流转需要校验,不能在任意状态下都能改成任意状态。比如“待验收”的任务只能被发布人验收通过或退回,不能被执行人直接改成已完成。实现方式是在Service层写状态校验方法:

public boolean checkStatusTransition(Integer oldStatus, Integer newStatus) { switch (oldStatus) { case 0: return newStatus == 1; case 1: return newStatus == 2; case 2: return newStatus == 3; case 3: return newStatus == 4 || newStatus == 3; case 4: return newStatus == 5 || newStatus == 6; case 6: return newStatus == 3 || newStatus == 2; default: return false; } }

这样做的好处是,把状态判断集中在一个地方,页面上不同的按钮可以通过状态码来控制是否显示,后端Service层的逻辑也清晰很多。论文里画状态图的时候,用这张表直接转成图就行。

任务下发时还要生成一条任务日志。这里建议在Service层使用事件机制,或者简单点在操作后直接调用logService.insert,保证一次操作对应一条日志。数据库里task_log的operate_action可以记录“创建任务”“下发任务”“接收任务”“上报进度”“申请验收”“验收通过”“退回任务”等。

3.3 进度上报与附件管理

进度上报不能只做一个文本框,至少要包含文字描述和可选附件。后端用MultipartFile接收文件,保存到服务器本地目录,然后把上传后的文件路径存到数据库。

文件上传Controller示例:

@RequestMapping("/upload") @ResponseBody public Result upload(@RequestParam("taskId") Long taskId, @RequestParam("file") MultipartFile file, HttpSession session) { if (file.isEmpty()) { return Result.error("请选择文件"); } String originName = file.getOriginalFilename(); String suffix = originName.substring(originName.lastIndexOf(".")); String fileName = UUID.randomUUID().toString().replace("-", "") + suffix; String savePath = "E:/upload/" + fileName; File saveFile = new File(savePath); if (!saveFile.getParentFile().exists()) { saveFile.getParentFile().mkdirs(); } file.transferTo(saveFile); TaskFile taskFile = new TaskFile(); taskFile.setTaskId(taskId); taskFile.setFileName(originName); taskFile.setFilePath("/upload/" + fileName); taskFileService.insert(taskFile); // 同时记录日志 taskLogService.log(taskId, "上传附件:" + originName, session); return Result.success(taskFile); }

文件名必须用UUID重命名,这是我自己踩过坑之后学到的。原本我直接用原始文件名,测试时发现不同用户上传同名文件会互相覆盖,而且中文文件名在下载时还会出现乱码。加上UUID之后,数据库里只需要保存原始文件名和新的文件名映射关系,展示给用户看原始名称,下载时走文件路径即可。

下载文件时注意设置响应头,让浏览器能够识别中文文件名:

response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

3.4 首页统计与报表展示

任务系统如果没有数据统计,光靠一张任务列表撑不起系统的大盘。首页推荐放几个统计卡片:总任务数、进行中任务数、已完成任务数、待办任务数,再用Echarts画两个图解决“整体趋势”和“部门分布”。

后端可以写一个统一的统计接口,返回以下类型的数据:

  • 状态统计:按status字段分组,count出每个状态的数量。
  • 部门统计:根据发布人所属部门分组,统计各部门任务量。
  • 趋势统计:按日期分组,统计每天新增任务数量和完成任务数量。

MyBatis SQL示例:

<select id="countByStatus" resultType="map"> SELECT status, COUNT(*) AS count_value FROM task_info GROUP BY status </select> <select id="countByCreateDate" resultType="map"> SELECT DATE_FORMAT(create_time, '%Y-%m-%d') AS date_day, COUNT(*) AS count_value FROM task_info WHERE create_time >= #{startDate} GROUP BY date_day ORDER BY date_day </select>

这里要注意返回结果不要直接用Map,最好定义成StatisticVO,字段名保持规范。因为MyBatis返回的mapkey可能是type、count,前端拿到后还要再适配,直接定义VO能让接口文档更清晰。

4. 论文写作要点

4.1 论文结构建议

很多同学代码写完了才开始写论文,结果发现没思路。我的习惯是做项目的同时就搭好论文框架,每完成一个模块就写对应章节。论文可以这样安排:

  • 第一章 绪论:背景、意义、国内外现状、论文结构。
  • 第二章 相关技术介绍:SSM框架、Vue框架、MySQL、开发环境。
  • 第三章 需求分析:可行性分析、角色分析、功能需求、非功能需求。
  • 第四章 系统设计:总体架构、功能模块图、数据库设计、接口设计。
  • 第五章 系统实现:每个核心功能模块的界面截图和关键代码分析。
  • 第六章 系统测试:测试环境、测试用例、功能测试结果、兼容性测试。
  • 第七章 总结与展望:总结做了什么事,不足和后续改进。

4.2 如何写需求分析

需求分析这一章最容易被写成“系统能登录、能增删改查”这样的流水账。要用用例图和用例描述的方式写,每个角色作为一个Actor,每个核心操作作为一个用例。比如“任务下发”用例的用例描述要写清楚:前置条件、主流程、异常流程、后置条件。

这套任务系统里最有特点的需求是“任务状态流转”和“任务日志留痕”。在论文里可以用一个表格描述状态之间的关系,表格里列出当前状态、可执行操作、目标状态。这比大段文字描述直观得多,答辩老师一眼就能看出你确实做了设计。

4.3 测试章节与答辩准备

测试部分不需要把所有按钮都截图,但核心流程必须覆盖。建议写一个测试用例表,包括用例编号、测试项、操作步骤、预期结果、实际结果、是否通过。对任务系统来说,至少要覆盖:

  • 不同角色登录后能否看到各自菜单。
  • 未登录用户直接访问接口返回401。
  • 发布人创建任务并下发后,执行人是否能看到待办。
  • 执行人上报进度后,发布人是否能看到最新内容。
  • 任务被退回后,执行人能否重新编辑并再次上报。
  • 上传附件后能否正常下载。

答辩时老师特别喜欢问的几个问题,提前准备一下:

  • 为什么使用SSM而不是SpringBoot?
  • 前后端分离时如何处理跨域?
  • 任务状态为什么用状态码而不是数据库存中文?
  • 用户密码如何保证安全性?
  • 如果用户量变大,数据库和系统如何优化?

不要直接背答案,结合自己项目里的具体配置回答。比如问到跨域,就说“前端用的Vue代理,后端没有额外配置CORS”,老师会觉得你动手做过。

5. 常见问题与踩坑记录

5.1 跨域与Session不同步

前后端分离开发时,前端运行在8080端口,后端Tomcat运行在8088端口,直接调用接口会报跨域错误。我建议开发阶段优先使用Vue的proxy代理,不要在后端随手写cors允许所有来源,避免上线后接口被任意网站调用。

在vue.config.js里配置:

module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:8088', changeOrigin: true, pathRewrite: { '^/api': '' } } } } }

然后前端所有请求地址都写/api/login,代理会把请求转发到http://localhost:8088/login。注意打包部署时,如果前端文件由Nginx托管,也需要配置类似的反向代理指向后端Tomcat。

Session不同步也是常见问题。前端跨域请求如果没带Cookie,后端Session中存了登录用户但每次请求都拿不到。使用代理方式基本可以避免,但如果是直接跨域调用,必须让Axios设置withCredentials: true,后端CORS配置里允许凭证。

5.2 MyBatis动态SQL报错

任务查询列表通常需要按状态、关键字、时间范围做筛选,这时候一定要写动态SQL。最容易犯的错误是在判断条件时没有处理参数为空的情况。

<select id="selectTaskList" parameterType="map" resultType="taskInfo"> SELECT * FROM task_info <where> <if test="status != null and status != ''"> AND status = #{status} </if> <if test="keyword != null and keyword != ''"> AND (task_name LIKE CONCAT('%', #{keyword}, '%') OR task_code LIKE CONCAT('%', #{keyword}, '%')) </if> <if test="startTime != null"> AND create_time &gt;= #{startTime} </if> </where> ORDER BY create_time DESC </select>

<where>标签会自动处理首条条件前面的AND,比自己写where 1=1干净。另外注意MyBatis中大于小于号要转义,否则XML会报错。这些细节在论文关键代码分析里如果写对了,会很加分。

5.3 时间日期格式化

前端经常出现“2026-06-01T10:00:00”这种格式,显示不友好。原因很简单,后端返回的日期是ISO格式,需要统一转成yyyy-MM-dd HH:mm:ss。

解决方式之一是在实体类的日期字段上使用@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")。但SSM项目里如果用了Jackson的MappingJackson2HttpMessageConverter,还需要在SpringMVC配置里导入jackson-datatype-jsr310依赖,否则LocalDateTime类型转换会报错。

另一个方式是后端统一返回时间戳,前端自己格式化。我实际开发更喜欢后者,因为前端有dayjs或者moment库,格式化非常灵活,后端也不用处处加注解。但论文里简单起见,直接在后端格式化更省事。

5.4 部署上线

SSM项目最终打成war包放到Tomcat的webapps目录下,和JSP时代一样。但前后端分离后,前端dist目录可以放到Tomcat的webapps/ROOT里,也可以单独用Nginx托管。我推荐后端war放Tomcat,前端静态文件用Nginx托管,然后配置反向代理:

location /api/ { proxy_pass http://localhost:8088/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }

这一步经常被忽略,很多同学在图解工具上跑通了就认为万事大吉,结果部署到服务器上跨域、404、静态资源加载不出来全来了。建议尽早打包测试,至少要在本地模拟生产环境跑通一遍。

6. 个人经验与扩展建议

这个项目做完之后,我自己最大的体会是:不要把毕设当成“交差”,而是当成一次完整的工程训练。任务系统的业务并不复杂,但它强迫你把每一个环节都想清楚:为什么这张表要加这个字段、为什么这个状态允许那个操作、为什么前端的按钮要跟着角色和状态变化。这些思考过程比最终代码更有价值。

最后再分享一个小技巧:做这种管理系统,代码写累了就去画流程图和数据表关系图。我开发时先画好状态流转图,再开始写Service层,写起来非常顺。后续如果你想扩展,还有很多方向可以加分,比如加入消息通知、导入导出Excel、增加待办提醒的定时任务,甚至把前端升级成Vue3。只要主流程清晰,这些扩展都是水到渠成的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询