ARTICLE DETAIL

资讯详情

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

基于SpringBoot+Vue的工作量统计管理系统设计与实现

基于SpringBoot+Vue的工作量统计管理系统设计与实现 1. 项目概述与功能拆解1.1 这个工作量统计系统到底解决什么问题说实话我第一次接这个需求的时候对方的需求文档写得特别模糊就说搞一个统计大家干活多少的系统。但真正落地的时候你会发现工作量这三个字本身就是个坑——是统计工时统计任务数量还是统计代码行数不同团队理解完全不同。我最终做下来的方案是这样的以任务为基本单位员工对分给自己的任务提交工作量申报单填写投入工时和工作说明上级或管理员审核通过后系统按人、按部门、按时间段自动汇总。这套逻辑既能兼容写代码开发的研发团队也能兼容处理工单的运营团队因为底层抽象的是任务工时状态这套通用模型。整个系统做成了前后端完全分离的架构后端SpringBoot只提供JSON接口前端Vue负责页面渲染和数据交互MySQL存业务数据。源码里带了一份初始化SQL脚本导入数据库之后改一下配置文件里的数据库账号密码本地就能直接跑起来。这一点对于做课程设计、毕业设计或者想快速做二次开发的朋友来说非常友好。1.2 系统角色与整体业务流程系统一共有三种角色这在信息管理类系统里算是比较标准的配置普通员工查看任务列表、提交工作量申报、查看自己的工作量统计部门负责人审核下属的申报、在部门维度查看统计结果系统管理员维护用户与部门、创建任务、分配任务、查看全量统计核心流程是管理员创建任务并分配给员工员工收到任务后开始工作完成后填写工时申报单负责人审核审核不通过则退回让员工修改审核通过的数据进入统计报表。整个流程不是特别复杂但这个申报-审核-驳回-再申报的闭环是关键没有这个闭环统计出来的数据是没有任何可信度的。我觉得这套逻辑最值得借鉴的地方在于状态的流转全部在数据库里通过一个字段维护后端接口只暴露提交审核审核通过驳回这三个动作不做多余的复杂设计。对于工作量统计这种业务场景够用且稳定。2. 技术选型解析为什么是SpringBootVueMySQL这套组合2.1 SpringBoot后端快速搭建与生态成熟SpringBoot在这套系统里负责提供RESTful API接口。当初做技术选型的时候考虑过直接使用Spring MVC加XML配置的老方案也考虑过一些更轻量级的框架但最终还是落到SpringBoot上原因很简单SpringBoot内置Tomcat打进一个Jar包直接运行不需要额外配置外部容器自带自动配置大量样板代码都省掉了整合MyBatis-Plus做数据访问写SQL又灵活又方便分页。这里要特别说一个版本踩坑。网上很多教程还在用SpringBoot 2.3甚至更老的版本但新项目我建议直接用2.7.x这个版本它比较稳定。千万不要一上来就用SpringBoot 3.x——SpringBoot 3是基于Jakarta EE的很多旧版MyBatis-Plus、旧版druid连接池根本不兼容报错报到你怀疑人生。我们这个项目用的是2.7.6适配MyBatis-Plus 3.5.3这套组合经过了大量项目验证不会出幺蛾子。2.2 Vue前端渐进式框架配合Element UI前端这边选Vue的核心原因一是上手曲线平缓二是生态足够丰富。从维护和学习的角度出发当前版本用的是Vue 2.6加Element UI 2.15。我知道现在Vue 3和Element Plus已经非常成熟了但对于这个源码项目Vue 2更稳妥的原因在于网上资料多、踩坑记录全、对初学者更友好。Element UI这套组件库在这个项目里发挥了很大作用。工作量申报表单、审核列表、统计图表这些页面大部分都是基于Element的表格、表单、弹窗、日期选择器组合出来的。特别是el-table组件自带排序、多选功能配合自定义列模板做工作量明细列表非常顺手。据统计一个完整的管理系统大概80%的页面都逃不出左侧菜单顶部栏中间内容区这种布局Element UI把这些基础组件打包得明明白白。2.3 MySQL存业务数据最稳的选择数据存储选择了MySQL 8.0实际生产环境用5.7也没有任何问题。MySQL在这个场景下最大的优势就是稳定、通用、随手可用。工作量申报系统的数据量不会特别大每天几千条记录已经算很多了MySQL完全扛得住。Stored Procedure不推荐在这个项目里用业务逻辑放在Java代码里更好维护。有一点需要注意就是建表的时候必须统一字符集为utf8mb4排序规则用utf8mb4_general_ci否则存emoji或者生僻字时会出现乱码。这个在初始化SQL脚本中我已经处理好了但如果你自己从零开始建库一定要记得这个细节。3. 数据库设计详析工作量统计系统表结构全解密3.1 核心表结构与字段释义这个系统的核心表有六张用户表、角色表、部门表、任务表、工作量申报表、审核记录表。其中用户和角色是多对多关系用户和部门是多对一关系。我挑重点表展开说一下。任务表task核心字段是任务名称、任务描述、指派人ID、创建人ID、任务状态、截止时间。工作量申报表workload_report是整个系统的核心业务表字段包括申报人ID、任务ID、申报工时decimal(6,1)、工作内容说明、申报周期起始日和结束日、审批状态0待审核/1通过/2驳回、审批人ID、审批时间、驳回原因。特别说一下为什么申报工时用decimal(6,1)而不用float或者int。工作量统计最终要按工时汇总float在累加时可能会出现精度问题int又表达不了半天这种0.5工时的情况。decimal(6,1)既能保证精度也能表示半天。这个细节我是在做了第一版统计报表发现数据总和有误差之后才改过来的。3.2 索引设计与查询效率优化在信息管理系统中最容易忽视的就是索引。数据量小的时候没感觉等到数据积累了一两年几万条数据之后没有索引的SQL会比有索引的慢几十倍。工作量申报表上我加了三个关键索引(user_id, create_time)用于统计个人工作量时按时间范围查询(task_id)用于明细查询和关联任务表(approval_status)用于待办查询待审核列表在负责人端是高频访问第一个索引其实是一个联合索引这是我比较想强调的点。比如要统计张三在2024年5月的工作量总和SQL的条件是user_id 3 AND create_time BETWEEN 2024-05-01 AND 2024-05-31这个联合索引能直接命中不需要回表再做过滤查询速度快一个数量级。3.3 初始化SQL与内置演示数据项目源码里提供了init.sql脚本建库、建表、插入种子数据一条龙。这里内置了一个演示用的账号体系比如管理员账号admin/admin123、普通员工user01/123456等。它们对应的密码是经过BCrypt加密之后存进去的不是明文这一点对学习SpringSecurity和密码加密也有参考价值。再来聊聊演示数据。我在种子数据里放了一组模拟数据包括5个用户、3个部门、5个任务、20多条申报记录分布在最近三个月。这样你导入源码后打开统计报表页面立刻能看到柱状图、折线图有数据展示不用自己去造数据。这个对快速验证系统功能非常有帮助。4. 后端核心实现要点SpringBoot项目的工程化拆解4.1 项目分包结构与职责划分后端包结构按这种方式组织com.example.workload ├── common // 通用类统一返回结果、异常处理、常量定义 ├── config // 配置类跨域、拦截器注册 ├── controller // 控制层接收前端请求 ├── service // 业务层核心业务逻辑 ├── mapper // 数据访问层MyBatis-Plus的Mapper接口 ├── entity // 实体类对应数据库表 ├── dto // 数据传输对象接收前端参数 └── util // 工具类JWT工具等日常维护这么多信息管理系统我最深的体会就是分包一定要按职责划分而不是按技术类型划分。比如有些项目把所有Controller放在一起、把所有Service放在一起这种按技术层次划分的方式在小项目里没问题但一旦业务模块多了改一个需求要在好几个不相邻的包之间跳来跳去累人。4.2 前后端交互的接口风格与统一返回结构所有接口的返回结构统一封装为{ code: 200, message: success, data: { } }简洁的返回结构对前后端联调极为重要。前端axios拦截器统一处理code如果code是401就跳转到登录页如果code是200就返回data部分逻辑非常统一。异常则通过全局异常处理器捕获业务异常返回500错误提示参数校验异常返回400具体字段错误。接口设计上遵循REST风格比如工作量申报的接口是POST /api/report/submit审核接口是POST /api/report/review统计接口是GET /api/statistics/queryStatisticsDataByPersonuserIdxxx。这种接口命名方式对前端理解非常友好后端每个接口的职责也足够单一。4.3 JWT认证与登录鉴权机制的实现认证这块我选了JWT加拦截器的方案没有引入SpringSecurity是因为SpringSecurity对新手来说学习成本偏高而工作量统计系统本身的安全级别不需要那么重型的框架。JWT的思路很简单用户登录成功后后端签发一个带过期时间的token前端请求时在header里带上token后端拦截器校验token合法性。这里详细介绍JWT工具类的三个核心方法生成Token、解析Token、校验Token是否过期。Token中存放了userId和userName解析时直接拿出来用不需要再查一次数据库这也是JWT相对Session的一个优势服务端无状态方便后期横向扩展。跨域问题在前后端分离项目中一定会遇到。我在项目里写了一个CorsConfig配置类允许所有来源访问后端接口同时允许携带凭证。不过实际开发中更推荐生产环境用Nginx反向代理来解决跨域后端接口地址和前端页面地址配置成同一个域名下的不同路径既解决了跨域又隐藏了内网接口地址。4.4 工作量统计核心算法的实现细节工作量统计是这个系统最具含金量的部分。按人统计的逻辑是某个时间段内当前用户所有审批状态为通过的申报单的工时总和。这里有一种业务取舍——待审核和驳回的数据不能进入统计只有通过的数据才能算数否则统计出来的就是申报工作量而不是确认工作量。按部门和按任务维度的统计原理相同只是分组条件不同核心是下面这条SQLSELECT user_id, DATE_FORMAT(apply_date, %Y-%m) AS apply_month, SUM(work_hours) AS total_hours FROM workload_report WHERE approval_status 1 AND apply_date BETWEEN #{startDate} AND #{endDate} GROUP BY user_id, DATE_FORMAT(apply_date, %Y-%m) ORDER BY user_id, apply_month统计结果拿到之后后端在返回给前端的DataTransfer层做一次转换拼装成ECharts需要的数据格式。前端展示端做了一个个人工作量的趋势折线图和部门对比的柱状图如果只拿到后端返回的工时总和而没有按照月份分组折线图就没法画所以这个SQL是经过反复调整才定下来的方案。4.5 基于POI的任务统计导出功能工作量统计完之后另外一个非常高频的需求是导出Excel。从做过的多个管理系统来看能不能导出Excel往往是甲方验收时最关心的功能之一需求量级不亚于页面展示。这个项目用Apache POI实现了这个功能——在统计结果页面点击导出后端把查询结果写入一个xlsx文件通过HttpServletResponse输出流返回给浏览器。这个功能的实现过程有几个要点设置单元格格式时把表头背景色、加粗、列宽都设置好数据行中日期类型要设置日期格式否则会显示成Excel的时间序列号导出文件名的中文要经过URL编码处理否则下载时会产生乱码。这些技术点单独看不难但组合在一起就能做出一份大体能用、实际上手也不会丢人的导出功能。学习POI重点不在于会写多少代码而在于对Excel文件格式组件模型的熟悉程度模型清楚了写代码就是查API的过程。5. 前端核心实现要点Vue项目从搭建到页面落地5.1 Vue前端项目结构与路由设计前端部分初始化用的是Vue CLI 3构建工具入口文件是main.js路由由Vue Router管理。页面组件放在views目录下按业务模块划分子目录login登录、dashboard首页仪表盘、task任务管理、report工作量申报、review审核、statistics统计、system系统管理。路由设计上用了动态路由的思路。不同角色登录之后通过后端返回的菜单权限列表前端动态添加路由。这个方案的优点是普通员工根本不会在前端配置里看到审核相关的路由即使手动在地址栏输入路径也会被路由守卫拦截权限控制做到菜单级和路由级双重保障。对于初学者来说Vue Router的beforeEach守卫和addRoutes动态添加路由是值得单独研究学习的两个知识点。5.2 登录逻辑与Token的本地持久化登录页面提交账号密码到后端拿到token和用户信息之后存到localStorage中同时把用户名存到Vuex中用于页面右上角显示当前登录人。axios请求拦截器每次请求都从localStorage取token放到Authorization请求头中响应拦截器判断状态码。如果遇到401说明token过期或失效清除本地登录信息并跳转回登录页。这里有一个非常实用的细节就是说在axios封装中我除了处理请求头之外还做了请求的统一loading管理、错误提示的弹出统一处理。页面调用时不用每个接口都写一遍错误弹出极大减少了重复代码。这个思想对新手理解前端工程化很有帮助。5.3 核心页面拆解工作量申报与审核界面工作量申报页是前端编写的重中之重。页面核心是一张Form表单包含任务名称下拉选择、工作说明textarea输入、申报工时数字输入、申报日期范围选择。el-form自带rules校验规则比如工时不能为空且必须大于0、工作说明至少10个字等。提交成功后弹窗提示并刷新右下角展示的当前用户待审核和已通过统计信息。审核页是负责人操作的界面。默认展示所有状态为待审核的申报记录每条记录后面有通过和驳回两个操作按钮。点击通过时弹出确认框点击驳回时弹出dialog要求填写驳回原因。驳回原因在员工端要能展示出来如果没有填写就不允许提交这是业务逻辑里强调的一个硬校验。5.4 统计图表模块ECharts的具体接入流程统计图表是工作亮点的展示窗口。通过ECharts折线图展示当前用户最近12个月的工作量变化柱状图展示各部门的工作量汇总对比饼图展示不同类型任务的工作量占比。ECharts有两种引入方式一种是全局引入完整的echarts包另一种是按需引入。考虑到这个项目只用到了折线图、柱状图、饼图三种基本图表我用了按需引入打包后的体积显著减少。实际开发过程中ECharts有一点需要特别提醒图表容器初始化时如果容器还没有被渲染完成比如在v-if条件渲染的隐藏区域中初始化图表图表会获取不到正确的宽高显示为空白。处理方式是使用this.$nextTick确保DOM加载完成再初始化图表并在window的resize事件里加上图表自适应大小的逻辑。这些细节在官方文档中都有提及但真正遇到并调试过印象会深刻得多。5.5 环境配置与本地启动注意事项前端在本地跑起来非常简单前提是Node环境没问题。这个项目用的是Node.js 14以上版本npm 6以上通过npm install安装依赖npm run serve启动开发服务器。默认端口8080如果想改端口在vue.config.js里修改devServer的port字段即可。如果8080被占用可以把port改成8090同时修改axios的baseURL配置指向后端接口地址。有两个初学者极易踩的坑一是npm install非常慢建议设置一下国内npm镜像源二是依赖安装过程中报错node-sass相关问题这个项目用了sass来写样式在Node版本过高时可能出现编译问题建议先装好node-sass的编译工具或者把项目中的scss样式改为less或纯css。这段内容在实操中集成了很多经验就是因为我在多个环境中部署过这个项目才敢说在哪里容易踩坑。6. 零基础也能跑通从环境安装到系统启动全流程6.1 环境准备清单在开始运行之前你需要准备以下这些开发环境。别小看这一步我从不少初学者那里收到的反馈有一半解决不了的问题都出在环境上而不是代码上。需要安装的软件有JDK 1.8或以上版本、Maven 3.6、Node.js 14、MySQL 5.7或8.0。在这其中JDK是运行后端的基础没有它SpringBoot项目连编译都过不了Node.js是前端开发服务器的运行环境MySQL是数据存储的核心。6.2 后端启动三步骤后端启动的核心步骤概括为三步导入初始化SQL、改配置文件、启动类运行。第一步导入SQL。使用Navicat或MySQL命令行工具执行源码里的init.sql文件。执行前先确认数据库编码设为utf8mb4否则中文会乱码。第二步修改配置文件。打开src/main/resources/application.yml重点关注数据库连接的四项配置数据库地址、数据库名、用户名、密码。这里有一个细节MySQL 8.0的驱动类名是com.mysql.cj.jdbc.Driver5.7则是com.mysql.jdbc.Driver如果你的数据库版本和源码里的不一致记得对应修改。第三步启动项目。在项目根目录右键运行主类WorkloadApplication看到控制台输出Started WorkloadApplication关键信息就说明后端启动成功了。此时访问http://localhost:8081/api/ping能返回成功信息。注意后端默认端口是8081之所以不用8080是为了避免和前端开发服务器冲突。6.3 前端启动两步走前端启动更直接。在vue-element目录下打开终端先执行npm install等待依赖安装完成。这里需要特别提醒的是如果你是第一次在当前环境跑这个项目这一步可能会耗时较长主要是node_modules需要下载大量第三方依赖包速度取决于网络环境。建议先配置好国内镜像源会节省大量时间。依赖安装完成后执行npm run serve看到提示Compiled successfully并显示本地访问地址就说明前端启动成功了。浏览器访问http://localhost:8080页面会自动跳转到登录页。输入初始化账号密码即可进入系统。6.4 前后端联调的通信配置解析为什么前端页面可以访问到后端的接口关键在代理配置上。前端开发服务器默认端口是8080后端API端口是8081两者不同源。开发环境下Vue通过vue.config.js里的devServer.proxy配置把请求路径中包含/api的请求转发到后端服务器的8081端口。这样浏览器看到的请求域名和端口始终是8080不存在跨域问题。在部署生产环境时前端打包成dist目录下的一组静态文件放到Nginx的HTML目录中Nginx同理配置一层反向代理把/api路径转发给后端SpringBoot服务的8081端口。这是前后端分离项目部署的标准姿势。7. 常见问题与排查技巧实录7.1 后端启动常见报错与解决方案我总结了一份后端启动阶段的高频问题对照表这部分内容我建议先收藏等到真遇到了再对着排查效率会高很多。问题现象根本原因解决方案启动时提示Access denied for user数据库密码不正确或用户权限不足核对application.yml中文密码确认授权提示Unknown database数据库不存在或名字拼错先执行init.sql中的CREATE DATABASE语句提示Public Key Retrieval is not allowedMySQL 8.0的caching_sha2_password认证问题在JDBC连接参数中添加allowPublicKeyRetrievaltrue端口被占用8081已经被其他程序使用修改application.yml中的server.port启动后接口返回404上下文路径配置问题确认controller类的RestController注解和RequestMapping路径这里要重点提一下第二个Unknown database这个报错特别容易迷惑人。很多初学者以为SQL脚本执行成功数据库就一定建好了但如果你用命令行工具执行init.sql时只执行了建表语句而没有先切换到目标数据库表可能建到了默认数据库中Backend启动连不上指定的库名就会报这个错。检查方式是打开Navicat看左侧列表里有没有对应名字的数据库再看看表是否齐全。7.2 前端启动与运行常见问题前端的问题更多样。我发现比较常见的是Node版本不兼容、安装依赖报错、请求后端接口401无权限三种。Node版本不兼容可以参考一个规律项目里的vue/cli-service版本如果比较老使用高版本Node运行npm run serve时会提示无法找到对应版本的库支持。此时要么降低Node版本要么将vue-cli升级到新版。个人建议本着能用就好的原则直接安装Node 14的LTS版本最省心。请求接口401十有八九是token没有正确传递或token已过期。排查顺序是先打开浏览器的开发者工具查看网络请求看请求头中Authorization字段是否存在再判断内容是否包含失效token。如果请求头正常可以看后端控制台是否打印了token校验失败的错误日志。7.3 数据库层面的排查技巧数据库相关的坑三次里有两次出现在时区和中文编码上。连接报错提示时区无法识别时一种快速解决方式是在JDBC连接参数加上serverTimezoneAsia/Shanghai。中文乱码问题要分两种情况数据库里乱码说明建表字符集或连接参数不对需要检查url中characterEncodingutf8配置页面展示乱码则需要检查前端页面的meta标签编码声明。这里还有一个特别容易踩的坑。如果你用Navicat直接打开表看到的中文都是正常的但页面请求回来却是乱码这很有可能是后端在解析请求参数时使用了错误的字符集。解决方案是在后端配置文件中设置spring.http.encoding.forcetrue强制请求和响应的字符编码为UTF-8。7.4 运行阶段必查的常见通信报错前后端通信关联的报错在联调阶段最让人头疼。前端F12打开控制台最常见的报错可以分三类404请求的接口路径不存在。检查后端Controller里的路径和前端请求路径是否一致502后端服务没有启动或挂掉了。在终端中重新启动后端看是否能正常访问CORS错误后端没有允许跨域请求或代理没有配置正确。由于本项目已经配置了跨域过滤器如果仍然报CORS多半是Nginx代理配置的问题另外一个容易忽视的问题是前后端开发服务器占用的端口与代码中硬编码端口不一致。例如后端代码里配置了8081但你恰好把项目改了端口改成8082却忘了改动前端axios的baseURL这时通信就会失败。排查这类问题用CtrlShiftF全局搜索一下baseURL和server.port立刻就能找到不一致的地方。7.5 让这个系统更符合你需求的小改造思路如果你拿到源码之后发现功能上还不太贴合你的使用场景可以考虑做以下几个常见的改造方向。如果想增加部门维度的审批流也就是部门负责人审核完成后还需要分管领导二次审批那就在工作量申报表上增加一个字段比如approval_status从0到2流转改为0到3流转在审核接口中增加一个审批级别判断。如果想给工作量设置上限比如每人每周最多报50小时可以在提交申报的后端接口中增加一个校验逻辑统计当前用户本周已经通过的申报工时总和如果加上本次申报会超过50则直接返回业务异常。这种规则校验放在后端做最安全前端校验很容易被绕过。如果想把任务模块做得更细可以拆分出子任务、任务优先级、任务附件上传等功能。SpringBoot在这方面的生态支持很完善上传用MultipartFile存储用本地目录或OSS相关的集成代码在成熟项目中都有很多参考资料。8. 项目扩展思路与二次开发建议8.1 报表模块升级为可视化大屏从我个人做完多个管理系统的经验来看工作量统计系统最容易出彩的扩展方向就是报表可视化大屏。把个人、部门、项目三种维度的工作量实时数据组合到一张大屏页面上采用ECharts的图表联动、定时刷新、地图标记等视觉元素效果会非常震撼。这块的技术难点主要在ECharts配置项的熟练程度和前端布局的细节处理上数据接口部分完全复用现有统计接口即可。8.2 引入消息通知机制审核流程中最常见的痛点是什么员工提交了申报审核人迟迟不去处理员工的申报被驳回了但没人及时告诉他原因。解决这个问题可以在系统中增加一个简单的消息通知机制。实现方式是在数据库新增一张通知表审核状态变更时插入一条记录前端通过轮询或WebSocket实时刷新未读消息数量员工登录后看到未读消息红点点击进去就能看到审核结果和驳回原因。这块不复杂但对使用体验的提升非常明显。8.3 配置中心化与部署优化如果这个系统最终要部署到公网服务器上给团队使用除了源代码本身还有几件配套工作需要做。后端打成Jar包后通过systemd配置成Linux开机自启服务前端npm run build打包后部署到NginxMySQL定期通过crontab自动备份备份文件保留最近30天。这些工作项在第一次部署时需要花时间配置好但一次配置永久受益团队使用过程中不用再操心系统和数据安全问题。9. 最后分享一点个人实操体会这个项目从最开始接到需求到最终整理成一份可运行的完整源码前后花了不少时间最大的体会就是信息管理系统的开发其实没有太多高深的技术难点真正的功夫都下在业务逻辑的设计和代码细节的打磨上。比如工作量统计的口径问题看似只是一个简单的SUM函数但如果你没有想清楚只有审核通过的数据才能进入统计这个业务规则做出来的系统就会在报表环节出现严重的信任危机。再比如工时字段的数据类型选择如果你一开始图省事用了浮点类型等统计数据出现各种0.30000000000000004这种诡异结果时哭都来不及。这套源码没有用太多花哨的技术栈SpringBoot、Vue、MySQL都是最主流的组合复杂度刚好适合作为学习项目来研究也足够支撑一个中小型团队做内部管理工作量。如果你拿到源码之后遇到任何跑不起来或者配置上的问题重点关注数据库连接配置和Node环境版本这两个点我见过的绝大多数问题都出在这两处。先把环境跑通了再逐步去阅读代码逻辑理解每个模块的设计意图最后再根据自己的需求做调整扩展这个学习路径是最顺畅的。
返回列表