基于SSM的软件项目进度管理系统毕业设计实战解析
发布时间:2026/9/25 4:44:24来源:尧图网络
做计算机毕业设计选题目是个技术活。Java 后端方向里“软件项目进度管理系统”属于那种看起来普通、但实际非常能打的题目业务逻辑完整、角色划分清晰、技术栈覆盖面广答辩时也有东西可讲。SSM 框架作为经典组合虽然近些年 Spring Boot 风头更盛但很多学校的毕设题目库、课程设计案例依然默认 SSM企业里也还有大量老系统跑在这套架构上。这篇文章我从头到尾拆一遍这个题目的完整实现思路包括需求拆解、表结构设计、核心代码逻辑、前后端联调以及我实际踩过的坑给准备拿这个题目做毕设或者正在写代码的同学一个可以直接参考的模板。既然是做毕业设计就得先想清楚一件事评分老师看的是什么不是你的代码量有多大而是你的系统能不能讲清楚一个完整的业务闭环。进度管理系统这个题目恰好具备这个优势——它不是孤立的增删改查而是把“项目—任务—进度—人员”串成一条线从立项到任务分配再到进度上报天然就是一套流程。这几百字只是个引子下面我从设计到实现逐步展开把关键代码和配置都放在对应章节。1. 项目定位与需求拆解1.1 软件项目进度管理到底在管什么很多人一开始会把这类系统做成“记事本”也就是给项目添加几条记录再写点备注就认为完成了。实际上项目进度管理的核心是动态跟踪项目拆分成任务任务分配给具体的人人按时上报进度百分比管理者根据这些数据判断项目是否会延期并在必要时调整计划。这个逻辑听起来简单做起来需要几个前置要素。一是必须有“项目”这个概念作为顶层容器二是项目下面必须挂“任务”三是任务必须关联“人”。没有人员维度的进度系统是没有意义的因为进度本质上是人干活的结果。四是进度不能只存一个最终值要记录“这次上报前是多少、上报后变成多少、谁在什么时间上报的”这样才能回溯历史状态也才能在演示时展示出“过程数据”。我见过不少同学把进度直接设计成任务表里的一个整数字段上报就 update 一下。这确实简单但答辩时老师问一句“这个项目进度从30%跳到80%中间发生了什么你能查出来吗”你大概率答不上来。所以我比较推荐额外建一张进度记录表把每次上报当作一条独立记录任务表里的当前进度可以保留但只作为冗余展示字段。1.2 角色权限三种身份各管一摊权限设计不需要做得太复杂但至少要有区分度。这个系统里最合理的角色划分是三类系统管理员、项目经理、开发人员也可以叫普通成员。管理员负责维护系统基础数据最典型的是用户管理——给新员工开账号、调整角色、重置密码。项目经理是业务核心角色可以创建项目、创建任务、把任务分配给开发人员、查看所有项目的进度、处理延期预警。开发人员做的事情很简单查看分配给我的任务、更新任务进度、填写工作内容和工时。注意这里不能给开发人员随意改任务截止日期的权限否则整个系统就没有约束力了。三个角色的功能边界想清楚之后后台的权限拦截就非常直接。用 SpringMVC 的拦截器按 URL 前缀区分就是最常见的做法/admin/** 只允许管理员访问/pm/** 只允许项目经理访问/task/** 和 /progress/** 登录后都可以访问但内部再通过查询参数校验数据归属。这种设计比引入 Shiro 或 Spring Security 更扣题也能避免权限框架带来的配置复杂度答辩时还能专门讲讲自己是怎么用拦截器实现的。1.3 功能模块地图我从实际开发顺序的角度列一下核心模块方便你规划时间用户模块注册、登录、退出、修改密码、用户管理管理员项目管理模块项目的创建、编辑、归档、状态流转、项目成员查看任务管理模块任务的创建、分配、优先级设置、截止日期设置、状态流转进度管理模块任务进度上报、进度历史记录、项目整体进度汇总、延期预警统计展示模块各个项目的进度对比图表、成员工作量统计、任务状态分布如果时间紧张前四个必须完整做第五个可以做基础版本也就是用一个列表展示项目进度百分比再用 ECharts 画一两个图表即可。很多同学把大量精力花在第六个模块上比如增加消息通知、文件上传结果前四个反而做得漏洞百出答辩的时候核心环节演示不畅非常可惜。2. 技术选型与原理SSM 为什么还能打2.1 毕业设计的现实考量近两年 Spring Boot 几乎成了新项目的默认选择但 SSM 框架在毕设语境下依然是一个合理选项原因有三个。第一是题目匹配度高。很多学校的毕设任务书里明确写了“基于 SSM 框架”或者“基于 Spring SpringMVC MyBatis”这不是你选不选的问题是题目要求。第二是 SSM 能让你把原理吃得更透。Spring Boot 把大量配置自动完成了你写一个 Controller 就能跑但很多人并不清楚请求是怎么从 Tomcat 到 DispatcherServlet再经过 HandlerMapping 到达方法的。SSM 要求你手动配置 web.xml、spring-mvc.xml、spring-dao.xml每写一个配置都有明确目的这种“痛感”反而是学习价值的来源。第三是迁移成本不高。你如果会用 SSM 的注解开发方式那么转向 Spring Boot 基本就是两三天的事因为核心业务代码完全一致。反而如果你直接用 Spring Boot 起步后面想回头补 Spring 原理反而更费劲。2.2 Spring、SpringMVC、MyBatis 各管什么对应到代码层面SSM 三个框架的职责边界非常清楚Spring 是容器管理对象。你的 Service 类、DAO 类、事务管理器都交给 Spring 容器来创建和注入。我们用注解 Service、Repository、Autowired 就是让 Spring 来帮我们拼装依赖不在代码里手动 new 对象。SpringMVC 是 Web 层框架负责接收请求和返回视图。前端发来一个 /project/list 的请求DispatcherServlet 会根据 URL 找到对应的 Controller 方法方法的参数绑定比如 RequestParam、PathVariable也都是这套框架干的。MyBatis 是持久层框架负责 Java 对象和数据库记录的映射。你写一个接口方法 List selectByStatus(int status)再在 XML 里写对应的 SQLMyBatis 就会执行 SQL 并把结果集映射成 Project 对象列表。这三个框架组合起来就是一条完整链路浏览器发送 HTTP 请求给 TomcatTomcat 把请求交给 SpringMVC 的 DispatcherServletDispatcherServlet 调用你的 Controller 方法Controller 调用 ServiceService 调用 DAO也就是 MyBatis 的 MapperMapper 执行 SQL 查询数据库结果再逐层返回最终通过 JSP 渲染成页面或通过 JSON 返回给前端。这条链路你能独立说出来任何答辩问题都难不住你。2.3 开发环境搭建与 Java 环境变量配置SSM 项目最稳妥的 Java 版本是 JDK 8。原因很简单SSM 的老项目大多基于 JDK 8 构建Tomcat 8.5/9 对 JDK 8 支持最好MyBatis 的版本兼容性也最省心。你在网上搜到的 SSM 整合教程绝大多数默认就是 JDK 8。JDK 安装本身没什么难度但环境变量配置是很多人翻车的地方。核心就是三个环境变量JAVA_HOME指向 JDK 安装目录比如 D:\Java\jdk1.8.0_291PATH在原有 PATH 后面追加 %JAVA_HOME%\binCLASSPATH很多教程让你配其实现代 Java 开发已经不需要了配了反而可能引发奇怪的问题不用管它配置完成后在命令行执行 java -version 和 javac -version能正常显示版本号就算成功。注意 javac 能识别而 java 不能大概率是 PATH 里配置错了可能是多个版本的 Java 冲突检查一下系统环境变量里有没有别的地方也设置了 JAVA_HOME 或者 PATH 里的 Java 路径。开发工具我推荐 IDEA 社区版。创建 Maven 项目时有两个坑一是 Maven 的 settings.xml 里要配置阿里云镜像仓库否则依赖下载慢到怀疑人生二是 IDEA 的 Project Structure 里要把 Project SDK 和 Project language level 都设置成 1.8否则编译级别默认对不上会出现“源发行版 17 需要目标发行版 17”之类的报错。3. 数据库设计与核心表结构3.1 从业务到表五张核心表进度管理系统的表结构可以说是一个“最小但完整”的权限与业务模型完全不涉及复杂的关系设计但又五张表缺一不可用户表 user所有角色的承载表项目表 project业务顶层容器任务表 task项目的拆解单元进度记录表 progress_record任务进度的流水账项目成员表 project_member项目组的人员关系表面上看项目表里存一个 manager_id 就够了成员关系用 project_member 表是为了支持“一个项目多个成员”的多对多关系。比如一个项目有项目经理、后端开发、前端开发、测试各一名如果只存一个负责人那开发人员登录后根本看不到这个项目的任务。3.2 核心建表 SQL 与字段说明我直接给一套标准建表语句字段命名和实际开发保持一致你拿去就能用。字符集统一用 utf8mb4不要用 utf8后者存储特殊字符会出问题。CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 用户ID, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录名, password VARCHAR(100) NOT NULL COMMENT 密码(密文存储), real_name VARCHAR(50) NOT NULL COMMENT 真实姓名, role TINYINT NOT NULL DEFAULT 2 COMMENT 角色:0管理员,1项目经理,2开发人员, email VARCHAR(100) DEFAULT NULL, phone VARCHAR(20) DEFAULT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, status TINYINT DEFAULT 1 COMMENT 1正常,0禁用 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表;关于密码字段我强烈建议用 BCrypt 加密存储而不是明文。就算毕设项目也要有基本的职业道德明文密码一旦被老师打开数据库看到印象分直接减半。Spring Security 里带 BCryptPasswordEncoder 类你单抽出来用就行。CREATE TABLE project ( id INT PRIMARY KEY AUTO_INCREMENT, project_name VARCHAR(100) NOT NULL COMMENT 项目名称, project_code VARCHAR(50) NOT NULL UNIQUE COMMENT 项目编号, manager_id INT NOT NULL COMMENT 项目经理ID, start_time DATE NOT NULL, end_time DATE NOT NULL, status TINYINT DEFAULT 0 COMMENT 0未开始,1进行中,2已完成,3已延期, description TEXT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT项目表;状态字段我之所以用 TINYINT 而不是直接存字符串是因为数字更省空间、索引更快而且前端可以通过状态码映射不同展示样式。你可能在别的系统里见过“0未开始 1进行中 2已完成”这里我加了“3已延期”是因为实际项目里经常出现过了截止日期还没完成的情况必须有一个状态来表达它否则数据统计会失真。CREATE TABLE task ( id INT PRIMARY KEY AUTO_INCREMENT, task_name VARCHAR(100) NOT NULL, project_id INT NOT NULL, assignee_id INT NOT NULL COMMENT 执行人ID, priority TINYINT DEFAULT 1 COMMENT 0低,1中,2高, deadline DATE NOT NULL COMMENT 截止日期, status TINYINT DEFAULT 0 COMMENT 0未开始,1进行中,2已完成,3已延期, progress_percent INT DEFAULT 0 COMMENT 当前进度0-100, description TEXT, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT任务表;progress_percent 这个冗余字段很多人觉得没必要因为进度记录表里已经有了。但实际查询时项目列表页需要显示所有任务的进度如果每次都要去进度记录表里聚合SQL 复杂度和性能都会变差。所以任务表保留一个当前进度值进度记录表做流水这属于典型的“以空间换时间”答辩时可以主动讲这个设计动机。CREATE TABLE progress_record ( id INT PRIMARY KEY AUTO_INCREMENT, task_id INT NOT NULL, project_id INT NOT NULL, reporter_id INT NOT NULL COMMENT 上报人ID, old_percent INT NOT NULL COMMENT 上报前进度, new_percent INT NOT NULL COMMENT 上报后进度, work_content TEXT COMMENT 本次工作说明, work_hours DECIMAL(5,2) DEFAULT 0 COMMENT 本次投入工时, report_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT进度记录表;3.3 数据库设计的几个细节第一个细节是外键。很多教材喜欢加 FOREIGN KEY但实际企业开发中很少用物理外键通常是逻辑关联只在写代码的时候保证数据一致性。毕设用物理外键其实也没错只是删除的时候会有麻烦比如管理员想删一个项目但任务表里还有引用就会报错。我的做法是不建物理外键但建索引这样可以保证查询性能又不会在删除时被约束卡住。第二个细节是时间的类型。start_time 和 end_time 用 DATE 类型而不是 DATETIME因为项目计划通常精确到天就够了用 DATETIME 反而会把事情复杂化。deadline 同理。第三个细节是数据量。毕设项目的数据量根本不会大所以不需要过度设计索引。给 user.username、project.project_code 建唯一索引给 task.project_id、task.assignee_id、progress_record.task_id 建普通索引就够了。4. 后端核心实现登录、项目与任务模块4.1 登录拦截与权限控制登录这块的核心是 Session。用户提交用户名密码后Service 层校验密码成功就把用户信息放到 Session 里。后续每个请求进来拦截器先检查 Session 里有没有 user没有就跳转到登录页。密码校验的代码用 BCrypt 实现核心逻辑是public boolean matches(String rawPassword, String encodedPassword) { return BCryptPasswordEncoder.matches(rawPassword, encodedPassword); }注册时用new BCryptPasswordEncoder().encode(password)加密再入库登录时把用户提交的明文密码和数据库里的密文进行比对。拦截器的实现是这样的。创建一个类实现 HandlerInterceptor 接口在 preHandle 方法里写校验逻辑public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); User user (User) session.getAttribute(loginUser); if (user null) { response.sendRedirect(request.getContextPath() /login); return false; } // 进一步做角色校验 return true; } }然后在 spring-mvc.xml 里注册这个拦截器指定拦截路径和放行路径mvc:interceptors mvc:interceptor mvc:mapping path/**/ mvc:exclude-mapping path/login/ mvc:exclude-mapping path/logout/ mvc:exclude-mapping path/css/**/ mvc:exclude-mapping path/js/**/ mvc:exclude-mapping path/images/**/ mvc:interceptor /mvc:interceptor /mvc:interceptors注意这里有个坑如果你用了静态资源的路径比如/static/css/xxx.css那这些请求也会被拦截器拦截。所以需要单独把静态资源路径排除掉否则页面样式加载不出来。用 SpringMVC 的mvc:resources标签可以配置静态资源映射同时配合 exclude-mapping 排除拦截。4.2 项目模块的核心代码项目模块是系统的基础创建项目时需要处理几个关键业务规则项目编号不能重复、截止日期必须在开始日期之后、必须指定一个项目经理。Controller 层只负责接收参数和返回结果业务逻辑全部在 Service 层。Controller RequestMapping(/project) public class ProjectController { Autowired private ProjectService projectService; GetMapping(/list) public String list(Model model, RequestParam(required false, defaultValue 1) int pageNum) { PageInfoProject page projectService.findByPage(pageNum, 5); model.addAttribute(page, page); return project/list; } PostMapping(/add) public String add(Project project) { projectService.createProject(project); return redirect:/project/list; } }Service 层的 createProject 方法里要做三件事校验项目编号唯一性、校验时间合法性、插入记录。校验不通过时抛自定义异常由全局异常处理器捕捉后返回提示信息。public void createProject(Project project) { if (projectService.existsByCode(project.getProjectCode())) { throw new BusinessException(项目编号已存在); } if (project.getEndTime().before(project.getStartTime())) { throw new BusinessException(结束日期不能早于开始日期); } project.setStatus(0); projectMapper.insert(project); }这里用到的 PageInfo 是 PageHelper 分页插件提供的对象。知识星球上的同学问我说毕设到底要不要用分页插件我的建议是用起来。PageHelper 的用法极简在查询前调用PageHelper.startPage(pageNum, pageSize)然后正常执行 Mapper 查询它会在底层自动拦截 SQL 并追加 LIMIT 语句返回的 List 会被包装成 PageInfo里面自带 total、pages、list 等分页属性。4.3 任务模块与状态流转任务是项目的拆解创建任务时的核心是分配执行人。前端页面选择一个项目再选择这个项目的成员作为执行人填写任务名称、优先级、截止日期提交到后端。任务的状态流转是一个经典的“状态机”问题。我推荐用最直接的方式一个 updateTaskStatus 方法接收任务 ID 和新的状态值根据当前状态判断是否允许跳转。比如“已完成”的任务不能回退到“未开始”“已延期”的任务可以修改完成状态。最简单的实现就是写一组 if-else 判断。public void changeStatus(Integer taskId, Integer targetStatus) { Task task taskMapper.selectById(taskId); if (task null) { throw new BusinessException(任务不存在); } int current task.getStatus(); // 规则未开始0 - 进行中1进行中1 - 已完成2 或 延期3延期3 - 已完成2 if (current 2) { throw new BusinessException(已完成的任务不能修改状态); } if (targetStatus current targetStatus ! 3) { throw new BusinessException(非法状态流转); } taskMapper.updateStatus(taskId, targetStatus); }任务进度上报是另一条核心链路。开发人员在自己的任务列表页点“上报进度”填写新的进度值0到100之间的整数、本次工作内容、投入工时。后端收到请求后先查出任务表的当前进度作为 old_percent再把新值写入任务表同时向 progress_record 表插入一条完整记录。这两步必须在同一个事务里完成否则可能出现任务表更新了但流水没记上的情况。事务的实现方式是 Service 方法上加Transactional注解由 Spring 容器统一管理。如果中途抛出 RuntimeException事务自动回滚。注意Transactional只对 Spring 容器管理的 bean 生效如果你在方法内部直接 new 另一个 Service 对象来调用事务会失效因为那个对象不是 Spring 代理的实例。4.4 项目整体进度的聚合计算单个任务的进度已经有了那项目的整体进度怎么算最简单的算法是所有任务进度百分比的加权平均值。有没有更精细的方案可以按任务天数加权比如一个任务周期长、工作量大它的进度对项目整体影响应该更大。我用一个相对简单又可以在答辩时解释的方案按任务数量取平均但把“已完成”的任务视为进度100“已延期”的任务如果进度未到100则按实际值。代码实现是public int getProjectProgress(int projectId) { ListTask tasks taskMapper.selectByProjectId(projectId); if (tasks.isEmpty()) { return 0; } int sum 0; for (Task t : tasks) { sum t.getProgressPercent(); } return sum / tasks.size(); }这是平均算法。如果你想让结果更贴近真实情况可以用“已完成任务数/总任务数”作为整体进度这种算法在做统计图时也更好看。公式是projectProgress 已完成任务数量 / 任务总数 × 100%。两种口径选哪一种都可以关键是答辩时能说清楚你选的是什么口径为什么选它。千万别做了图自己都不知道图里的数字是怎么算出来的。5. 前端展示与进度可视化5.1 JSP AJAX 的组合页面形态上毕设项目用 JSP Bootstrap 是主流组合。JSP 负责服务端渲染Bootstrap 负责页面样式ECharts 负责图表。如果你对前端不太熟也完全可以做出一个清晰耐看的页面重点不是炫技而是信息层级清楚。列表页的思路是Controller 查询数据后放到 Model 里JSP 用 JSTL 标签循环输出表格行。c:forEach items${page.list} varproject tr td${project.projectCode}/td td${project.projectName}/td td${project.managerName}/td td span classstatus-${project.status} c:choose c:when test${project.status 0}未开始/c:when c:when test${project.status 1}进行中/c:when c:when test${project.status 2}已完成/c:when c:when test${project.status 3}已延期/c:when /c:choose /span /td /tr /c:forEachJSP 里面直接写一堆 c:choose 很容易乱我建议在 Controller 里就把状态值转换成状态文本放到 VO 对象里页面只做展示这样 JSP 干净得多也方便后期扩展。5.2 进度图表的实现思路进度可视化是这个系统的加分项。最常用的两个图表各项目进度对比的柱状图、单个项目任务构成与状态的饼图。用 ECharts 实现步骤很简单在 JSP 页面引入 ECharts 的 JS 文件然后在页面里准备一个 div通过echarts.init(dom).setOption(option)渲染。关键点是数据来源。你可以直接在 JSP 页面里通过 JSTL 拼接一个 JSON 字符串传给前端也可以用 AJAX 请求一个返回 JSON 的接口。我推荐后者因为职责更清晰——Controller 负责把查询结果转成 JSON 返回前端 JS 负责解析和渲染。GetMapping(/project/progressData) ResponseBody public ResultListMapString, Object progressData() { ListProject projects projectService.list(); ListMapString, Object data new ArrayList(); for (Project p : projects) { MapString, Object item new HashMap(); item.put(name, p.getProjectName()); item.put(value, projectService.getProjectProgress(p.getId())); data.add(item); } return Result.success(data); }ResponseBody 配合 Jackson 依赖SpringMVC 会自动把返回对象序列化成 JSON。这里要注意如果你的 Result 里包含 null 值序列化时默认会输出 字段名:null如果不想这种冗余可以在配置里设置spring.jackson.default-property-inclusionnon_null。6. 我踩过的坑环境、配置与代码6.1 环境配置类我合作过的一届学弟光搭环境就搭了四天最后发现是JDK版本问题。SSM 项目建议直接用 JDK 8不要用 11、17因为在 JDK 8 之后Java 的一些内部 API 被模块化限制了老版本的 Tomcat 和额外依赖可能会在启动时包异常。如果老师要求必须用新版 JDK那你就得换 Tomcat 版本和部分依赖版本性价比很低。另一个高频坑是 Maven 私服配置。很多新手直接缺省配置下载依赖然后卡在 Resolving 界面一小时还不报错。解决办法是修改%MAVEN_HOME%/conf/settings.xml在 mirrors 节点加入阿里云公共仓库镜像。还有 IDEA 的编码问题。统一把 IDE 的 Global Encoding、Project Encoding 都设置为 UTF-8Maven 编译时也加project.build.sourceEncodingUTF-8/project.build.sourceEncoding否则 JSP 页面的中文会出现问号。6.2 框架整合类SSM 整合最经典的报错是Invalid bound statement (not found)。这个错误的意思是你的 Mapper 接口没有跟 XML 文件绑定。原因有三个XML 文件放错了位置比如放在了 resources 外面、MyBatis 的 mapper-locations 配置路径写错、XML 里的 namespace 跟接口全限定名不一致。排查方式就是依次检查这三个点尤其是 namespace 开头的包路径少一个点都会报这个错。另一个经典问题是Could not resolve bean definition。出现这个问题的原因是 Spring 容器扫描不到你的 Service、Controller 或 Mapper。需要在 spring-mvc.xml 里配置context:component-scan base-packagecom.xxx.controller/在 spring-dao.xml 里配置context:component-scan base-packagecom.xxx.service/然后单独配置MapperScan(com.xxx.mapper)。扫描包路径不匹配是毕业设计里最常见的框架问题。启动 Tomcat 时碰到的另一个问题是端口冲突。Eclipse 里跑完一次不关或电脑上装了什么程序占用 8080就会报Port 8080 required by Tomcat v9.0 Server is already in use。解决办法是换个端口或者打开命令行执行netstat -ano | findstr 8080找到占用进程然后结束它。6.3 业务逻辑类第一个常见的业务坑是没处理“空状态”。比如一个项目还没有任何任务页面显示整体进度时会除零报错。所以聚合计算时必须先判断任务列表是否为空为空直接返回 0。第二个坑是删除功能的连带处理。如果直接删除任务但进度记录表里还引用了这个任务ID展示历史记录时会查出空对象。我的建议是删除任务前先删进度记录或者在数据库层面用逻辑删除——加一个 is_deleted 字段查询时默认过滤掉。第三个坑是日期比较。如果你用字符串传日期给后端Model 绑定可能格式不对。建议用DateTimeFormat(pattern yyyy-MM-dd)标注日期字段前端表单提交的格式严格按 yyyy-MM-dd 来。数据库里存的是 DATE 类型Java 里用 java.util.Date 接收在传递时不会出问题。最省心的方式其实是前端用日期选择器提交格式永远是正确的。第四个很重要的坑是消息提醒。项目延期预警怎么实现最简单的方法是定时任务在 Spring 配置里开启调度每天扫描一次所有未完成任务如果截止日期已过且状态不是已完成或已延期就把状态自动改成已延期同时给项目经理发送一条通知通知实现可以直接在页面上做个消息列表不用接任意消息推送服务。这个功能实现成本很低但演示效果非常好属于“用最小成本获取最大收益”的功能点。7. 回看我自己做这个选题的体会如果你手里正好拿到这个题目我的核心建议是别急着写代码先花两三天画清楚流程图和数据流。项目整体进度怎么算、任务状态怎么流转、权限边界在哪里这三句话你在文档里写清楚代码后面就不会返工。进度管理系统的技术难点不深但业务关系比较绕数据库设计和状态设计是灵魂UI 和花哨功能反而是次要的。最后分享一个实在的小技巧答辩演示时先登录一个项目经理账号创建一个新项目创建两个任务把其中一个分配给另一个账号然后登录开发人员账号上报进度回到项目经理视角查看项目进度百分比和图表变化。这条完整的业务链路演示下来比单独展示十个页面都有说服力因为你展示的不是“会调用接口”而是“理解业务流程”。这个套路我用了不止一次效果一直很稳定。
网站建设高端定制企业官网