ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SpringBoot建筑工程管理系统:从CRUD到业务流程闭环设计

SpringBoot建筑工程管理系统:从CRUD到业务流程闭环设计 开工之前先聊两句。很多同学拿到“基于SpringBoot的建筑工程项目管理系统”这种毕设题目第一反应是这不就是个CRUD吗表建好、页面搭好、增删改查一写就完事。但真做起来会发现建筑工程管理系统跟普通的学生管理、图书管理不太一样它有业务场景、有角色分工、有流程节点也有行业特有的术语和数据结构。你拿这套系统去答辩评委大概率不会只问“这个按钮怎么实现”而是会问“项目立项之后合同跟进度怎么关联”“材料入库和成本台账怎么对得上”。这些问题如果心里没数代码能跑也没用。这篇文章我按自己实际做这类项目的思路把这个“毕设源码文档”级别的系统拆开来讲从选题定位、技术栈选择、数据库设计到核心功能实现、跑通步骤、答辩避坑再到文档怎么写才像样。无论你是打算直接参考现有源码还是想自己从零撸一套这篇都能帮你少走弯路。1. 项目定位与技术选型为什么是SpringBoot加上建筑工程1.1 这个系统到底要解决什么问题建筑工程项目的管理链条其实很长立项审批、合同签订、施工进度、材料采购、设备进出场、质量检查、人员安全、成本核算每一环都有单据、有审批、有台账。传统做法是Excel加纸质单据项目一多就乱数据对不上、责任扯不清。管理系统要做的就是把这些线下流程搬到线上让每个角色看到自己该看的数据让每一步操作留痕可查。作为毕设没必要把整个ERP都塞进去但要覆盖一条相对完整的主线。我建议把范围圈定在这几个核心模块系统管理用户、角色、权限、项目管理立项、基本信息、合同管理登记、付款计划、发票、进度管理节点计划、实际进度、材料管理采购、入库、领用、质量管理检查、整改、报表统计合同额、成本、进度汇总。这样既贴合建筑行业又能把常规技术点全部覆盖答辩时有东西可讲。1.2 技术栈选择背后的逻辑选SpringBoot不是因为它“流行”而是它做这类管理系统确实合适。毕设场景要的是快速开发、结构清晰、部署方便SpringBoot的自动配置、内嵌Tomcat、Starter生态能让你把精力放在业务代码上而不是折腾XML配置。配合MyBatis Plus做数据访问单表CRUD几乎不用写SQL分页也直接有现成方案。前端我用的是Vue3加Element Plus后台管理界面的经典组合。Vue3的组合式API写起来比Vue2清爽Element Plus的表格、表单、弹窗组件能覆盖90%的页面需求。前后端分离的好处是结构清楚答辩时可以重点讲接口设计也可以顺手展示一下前端工程化的内容。认证这块毕设级别用JWT加拦截器就够了不必上Spring Security除非你打算把权限模型做得特别细。我见过不少同学在Spring Security上卡了两三天结果核心业务没时间写。自己用JWT生成令牌、写个拦截器校验半小时就能搞定而且原理讲得清。1.3 交付物拆解源码和文档各含什么标题里写了“毕设源码文档”这两部分的交付内容要提前想清楚。源码部分通常包含后端工程SpringBoot项目、前端工程Vue项目、数据库初始化SQL脚本、README部署说明。文档部分一般就是毕业论文核心章节包括选题背景与意义、需求分析含用例图、系统设计含架构图、功能模块图、数据库ER图、系统实现核心代码与截图、系统测试测试用例与结果。文档不是代码的附属品答辩时老师重点翻的就是它后面专门用一节写怎么写。2. 业务模块设计与数据库建模前期想得越细后期越省事2.1 建筑工程的业务链条怎么落到系统里很多同学数据库设计上来就建表结果写到一半发现字段不够、关系不对回头改表结构代码也牵连着重写。正确顺序是先捋业务对象和它们的关系。建筑工程管理系统的核心对象我列成这样一张表业务对象核心字段要点主要关联用户用户名、密码、角色、所属部门角色表、部门表项目项目编号、名称、地址、面积、预算金额、开工日期、竣工日期合同、进度、质量合同合同编号、名称、金额、签订日期、乙方单位、付款计划项目多对一进度节点节点名称、计划开始/结束、实际开始/结束、完成百分比项目、人员材料材料名称、规格、单位、单价、供应商入库单、领用单入库单入库单号、材料、数量、入库日期、经办人材料、用户领用单领用单号、材料、数量、领用人、用途材料、用户质量检查检查单号、项目、检查部位、检查结果、整改要求项目、用户通知公告标题、内容、类型、发布时间面向全体用户这些对象之间大多是“一对多”关系一个项目有多份合同、多个进度节点、多次质量检查一份合同可以有多个付款计划。在设计时把主外键关系理清楚后续写联表查询和统计报表就顺了。2.2 核心表结构设计参考拿几张核心表当例子具体设计时可以照着扩展。用户表和角色表是比较通用的CREATE TABLE sys_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 用户ID, username VARCHAR(50) NOT NULL COMMENT 用户名, password VARCHAR(100) NOT NULL COMMENT 密码BCrypt加密, real_name VARCHAR(20) COMMENT 真实姓名, phone VARCHAR(20) COMMENT 联系电话, status TINYINT DEFAULT 1 COMMENT 状态0禁用 1启用, create_time DATETIME COMMENT 创建时间 ); CREATE TABLE sys_role ( id BIGINT PRIMARY KEY AUTO_INCREMENT, role_code VARCHAR(50) NOT NULL COMMENT 角色编码ADMIN/MANAGER/STAFF, role_name VARCHAR(20) NOT NULL COMMENT 角色名称 );项目表是业务的核心字段要覆盖建筑工程的关键信息CREATE TABLE project_info ( id BIGINT PRIMARY KEY AUTO_INCREMENT, project_no VARCHAR(30) NOT NULL COMMENT 项目编号, project_name VARCHAR(100) NOT NULL COMMENT 项目名称, project_address VARCHAR(200) COMMENT 项目地址, building_area DECIMAL(12,2) COMMENT 建筑面积(平方米), budget_amount DECIMAL(15,2) COMMENT 预算金额(元), project_manager VARCHAR(20) COMMENT 项目经理, start_date DATE COMMENT 计划开工日期, end_date DATE COMMENT 计划竣工日期, actual_start_date DATE COMMENT 实际开工日期, actual_end_date DATE COMMENT 实际竣工日期, progress_status VARCHAR(20) COMMENT 项目状态筹备中/进行中/已竣工/已暂停, description TEXT COMMENT 项目描述, create_by BIGINT COMMENT 创建人, create_time DATETIME COMMENT 创建时间 );注意DECIMAL的使用。金额字段一律用DECIMAL千万别用FLOAT或DOUBLE否则累计金额会出现精度问题答辩时被问到就很尴尬。材料表会涉及规格和单位这两个字段建议分开存CREATE TABLE material_info ( id BIGINT PRIMARY KEY AUTO_INCREMENT, material_name VARCHAR(50) NOT NULL COMMENT 材料名称, material_spec VARCHAR(50) COMMENT 规格型号如HRB400/25mm, unit VARCHAR(10) COMMENT 单位吨/平方米/立方米, price DECIMAL(10,2) COMMENT 参考单价, supplier VARCHAR(50) COMMENT 主要供应商, stock_quantity DECIMAL(12,2) DEFAULT 0 COMMENT 当前库存量, warning_quantity DECIMAL(12,2) DEFAULT 0 COMMENT 库存预警值 );2.3 字段设计上的几点经验第一所有表都建议加create_time、update_time方便做审计和排错MyBatis Plus里用MetaObjectHandler可以自动填充。第二逻辑删除字段deleted建议加上避免物理删除后数据无法追溯尤其是合同、项目这类核心数据。第三状态字段用TINYINT或VARCHAR存编码不要存中文前端再通过数据字典转换显示。第四项目编号、合同编号这类业务编号不要依赖自增ID主键使用序列或日期加随机数生成更符合行业习惯。数据库字符集统一用utf8mb4排序规则用utf8mb4_general_ci不然Emoji和生僻字可能存不进去。3. 核心功能实现细节从登录鉴权到数据导出3.1 JWT登录鉴权的简单可靠实现JWT是很多管理系统登录的标配方案。流程是这样的用户提交用户名密码后端校验通过后生成一个token返回给前端前端存在本地之后每次请求在请求头里带AuthorizationBearer 后端写一个拦截器统一校验。生成JWT的代码模式大概是这样的Component public class JwtUtil { Value(${jwt.secret}) private String secret; Value(${jwt.expire}) private Long expire; // 单位秒 public String generateToken(Long userId, String username) { Date now new Date(); Date expireDate new Date(now.getTime() expire * 1000); return Jwts.builder() .setSubject(String.valueOf(userId)) .claim(username, username) .setIssuedAt(now) .setExpiration(expireDate) .signWith(SignatureAlgorithm.HS256, secret) .compact(); } }密码存储用BCrypt加密Spring Security里自带BCryptPasswordEncoder也可以单独引入jbcrypt依赖。要用明文存密码答辩直接就会被质疑安全性。校验密码时调用matches方法即可。拦截器里要注意放行登录接口、Swagger/Knife4j接口文档路径、静态资源路径其他的统一校验。这个放行配置是许多同学容易搞错的地方放多了接口裸奔放少了前端连登录都进不去。3.2 通用分页和多条件查询又是老生常谈但必须写对管理系统里最常用的接口就是分页加多条件查询。MyBatis Plus里用LambdaQueryWrapper可以链式拼条件public PageProjectInfo queryProjectPage(ProjectQueryDTO dto) { PageProjectInfo page new Page(dto.getPageNum(), dto.getPageSize()); LambdaQueryWrapperProjectInfo wrapper new LambdaQueryWrapper(); wrapper.like(StringUtils.isNotBlank(dto.getProjectName()), ProjectInfo::getProjectName, dto.getProjectName()) .eq(dto.getStatus() ! null, ProjectInfo::getProgressStatus, dto.getStatus()) .ge(dto.getStartDate() ! null, ProjectInfo::getStartDate, dto.getStartDate()) .le(dto.getEndDate() ! null, ProjectInfo::getEndDate, dto.getEndDate()) .orderByDesc(ProjectInfo::getCreateTime); return projectInfoMapper.selectPage(page, wrapper); }这里有几个要点条件判断必须加上StringUtils.isNotBlank或! null不然没传值时会拼出恒真条件拖慢查询。模糊查询用like注意like两边会自动加%不需要手动拼。排序字段建议白名单校验防止用户通过orderBy参数注入恶意排序字段或SQL。前端表格控件会绑定pageNum、pageSize、total三个字段element-plus的el-pagination组件直接对接返回结构统一设计成{ code, message, data }data里面放分页对象即可。3.3 合同金额和项目成本的统计报表怎么设计报表是建筑工程管理系统里比较出彩的部分做得好答辩时加分明显。常见的统计需求各项目合同总金额汇总、月度材料入库金额统计、项目成本与预算对比。用SQL聚合来实现这类统计很直接Select(SELECT p.id, p.project_name, IFNULL(SUM(c.contract_amount), 0) AS contract_total, IFNULL(SUM(c.paid_amount), 0) AS paid_total, p.budget_amount FROM project_info p LEFT JOIN contract_info c ON p.id c.project_id GROUP BY p.id) ListProjectCostStatsVO selectProjectCostStats();注意LEFT JOIN的用法。如果项目还没有合同INNER JOIN会把项目过滤掉统计就不全。IFNULL把金额空值变成0前端图表渲染更省心。前端展示用ECharts的柱状图或饼图对比各项目预算和合同总额图表能一眼看出哪些项目超预算了。这个组合统计在答辩演示里效果很好。3.4 Excel导出和文件上传实习单位最常用的功能施工项目动不动要上报材料报表系统里做Excel导出是刚需。我用的是EasyExcel比POI写起来省太多事public void exportMaterialStock(HttpServletResponse response, String projectId) throws IOException { ListMaterialStockVO list materialMapper.selectStockList(projectId); response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setCharacterEncoding(utf-8); String fileName URLEncoder.encode(材料库存表, UTF-8).replace(, %20); response.setHeader(Content-Disposition, attachment;filename*utf-8 fileName .xlsx); EasyExcel.write(response.getOutputStream(), MaterialStockVO.class) .sheet(材料库存) .doWrite(list); }导出文件名有中文时必须进行URL编码处理否则浏览器下载时会出现乱码或直接报错。文件上传主要用于合同附件、设计图纸、质量检查图片上传。上传目录不要放在前端静态资源里推荐按日期分目录存储生成UUID文件名防止重名和路径遍历攻击。后端返回文件访问URL前端配合element-plus的upload组件处理即可。4. 实操过程与部署跑通拿到源码后别急着改代码4.1 运行环境和初始化顺序拿到项目先别急着双击打开先把环境对齐否则各种报错会让你怀疑人生。运行环境建议如下软件版本建议说明JDK8或11SpringBoot 2.x用8没问题3.x要17以上Maven3.6建议用IDEA自带的也行MySQL5.7或8.0注意8.0的驱动配置差异Node.js14到18都行前端构建工具要求IDEIntelliJ IDEA社区版就跑得起来初始化流程是先建数据库、导入SQL脚本再启动后端最后启动前端。很多人先启动了后端结果报“数据库连接失败”又慌慌张张去查端口、查防火墙其实只是一开始就漏了导数据这一步。4.2 后端配置里的几个关键点application.yml配置看似简单但有几个点值得单独拎出来说。spring: datasource: url: jdbc:mysql://localhost:3306/construction_mgmt?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver servlet: multipart: max-file-size: 50MB max-request-size: 50MB mybatis-plus: configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0MySQL 8.0必须加serverTimezone不然会报时区异常驱动也换成com.mysql.cj.jdbc.Driver。大文件上传不调整multipart大小默认1MB图纸肯定传不上去。map-underscore-to-camel-case打开后数据库字段project_no才能自动映射到实体类的projectNo写代码能省很多事。4.3 前端联调里的跨域和代理配置前后端分离一定遇到跨域问题。最省事的办法是在SpringBoot里加全局CORS配置生产上可以换成网关或Nginx反向代理Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }如果是Vue开发环境更推荐用vite的proxy代理把/api开头请求代理到后端端口这样浏览器就不会有跨域请求了。上线再通过Nginx做一次反向代理前端和后端共用同一个入口CORS问题彻底绕开。4.4 租户和权限控制角色不要只做展示很多毕设系统的权限只做到“菜单显示与隐藏”接口层面不控制。换句话说普通用户直接调接口就能拿到管理员数据。这个点评委极爱问答不上来很扣分。我常用的方案是在拦截器里解析token里面的userId查出对应的角色编码然后在接口前置校验里判断角色权限也可以结合Spring AOP自定义注解来做RequireRole({ADMIN, PROJECT_MANAGER}) GetMapping(/project/delete/{id}) public Result deleteProject(PathVariable Long id) { projectInfoService.removeById(id); return Result.success(); }切面里判断当前用户角色是否在注解允许列表中不在就抛异常返回403。这样实现的权限控制有真实逻辑又不会像Shiro或Spring Security那么复杂。5. 常见问题排查与答辩避坑实录5.1 高频问题速查表这些是我在做类似项目时经常碰到的问题整理成表方便对照问题现象根本原因解决办法启动报“Access denied for user”数据库账号或密码配置错误核对datasource配置特别注意密码里的特殊字符接口返回404但Controller存在请求路径与RestController的RequestMapping不一致检查后端ContextPath和前端baseURL是否匹配表格数据日期比数据库少8小时MySQL连接时区与系统不一致在URL加serverTimezoneAsia/Shanghai上传excel中文文件名乱码未做URLEncoder编码见3.4节代码登录后访问其他接口401JWT放行路径配置覆盖了校验路径检查拦截器中excludePathPatterns是否正确MyBatis Plus查询字段全部为null驼峰自动映射没开启配置map-underscore-to-camel-case: true前端打包后刷新404Vue路由是history模式Nginx没配置try_filesNginx无法匹配的路径指向index.html5.2 答辩时容易被问倒的几个技术点评委会顺着代码问下去喜欢追问“为什么”。准备几个高频问题的回答思路。问你为什么不用Restful风格。你可以说项目接口有统一的REST风格GET对应查询、POST对应新增、PUT对应修改、DELETE对应删除路径用名词复数状态码统一返回200再加业务code。把response结构里的code、message、data讲清楚就行。问你权限怎么实现的。先把JWT校验流程说清再讲RequireRole注解的AOP拦截。如果做过数据权限比如项目经理只能看自己负责的项目可以进一步说在查询时把当前用户ID作为过滤条件但注意不要说得太绝对否则老师追问细节容易露怯。问你不考虑工期的甘特图吗。如果你时间有余量可以引入一个简单的时间轴图表页面展示项目节点计划。但不建议贪多基础功能做完比加不上线的鸡肋功能更值钱。5.3 现场演示的加分细节演示前把测试数据准备好尤其要有不同状态的项目和合同。不要演示时现敲查询条件一紧张打错字页面空白印象分会掉。建议按这个顺序演示首页仪表盘统计、项目全流程新增、查询、编辑、删除、合同关联项目、材料入库领用、报表导出、权限切换管理员和普通用户看同一个菜单的差异。演示时特意展示一个报错场景的兜底处理比如故意输入非法ID删除不存在的项目系统返回友好提示且不崩溃。这个细节会让评委觉得你有工程意识。6. 毕设文档怎么写才像样源码之外的另一半“交付物”6.1 需求分析不能抄模板要能对上流程论文里的需求分析章节很多同学喜欢从网上下模板复制一堆“本系统致力于提高管理效率”的空话。这样写老师一眼就能看出来。正确写法是先画出用例图然后针对每个角色写功能需求比如管理员用户管理、角色分配、系统公告、所有模块的数据维护。项目负责人项目信息维护、进度节点更新、质量检查、合同登记。仓管员材料入库、领用登记、库存预警处理。每条需求都对应一个具体页面和一个接口这样需求才跟系统对得上。数据字典也建议列出来像项目状态是“0筹备中、1进行中、2已竣工、3已暂停”写清楚枚举值后续设计章节引用起来逻辑才顺。6.2 数据库设计文档画清楚ER图和表关系数据库设计章节重点不是贴建表SQL而是讲清楚表和表之间的关系。一张项目表对应多张合同表关联字段是什么合同表对应多个付款计划通过外键关联。ER图可以用PowerDesigner或者简单的draw.io画画得干净清晰别用截图糊弄。表格设计建议每张表都写表名、字段名、数据类型、可否为空、默认值、注释说明。字段注释注意跟代码实体类对应一致别出现代码里叫projectName、文档里写项目名称到底对应哪个字段自己也说不清楚的情况。6.3 测试报告和操作说明是很多人漏掉的加分项测试章节不要只写“系统已完成测试、运行稳定”这种结论。要列测试用例包括用例编号、测试步骤、预期结果、实际结果。比如用例编号测试步骤预期结果实际结果TC001使用admin/admin123登录登录成功跳转首页通过TC002使用错误密码登录提示用户名或密码错误通过TC003新增项目并填写必填字段保存成功列表出现新记录通过TC004不填写项目名称提交提示“项目名称不能为空”通过加上几张核心页面截图标注功能点测试章节一个晚上就能搞定。操作说明要写清楚系统初始化和使用步骤尤其是管理员如何创建用户、分配角色这部分在演示环节也经常被用到。7. 后续扩展建议这套系统还能往哪些方向走如果你不想止步于毕设这套系统后续有不少可以扩展的方向。一是引入工作流引擎把合同审批、材料采购审批变成可视化流程项目经理提交、经理审批、财务复核每个环节留痕这个扩展能直接把系统从“信息台账”升级成“管理平台”。二是增加移动端适配施工现场人员不一定方便用电脑做一个H5或者小程序端只做查询和审批操作开发成本不高但行业贴合度好。三是把统计报表做得更智能比如对接ECharts画施工进度曲线、材料价格趋势图甚至可以做一个超预算预警一旦累计成本超过预算的90%就自动给项目经理发提醒。四是引入AI能力用大模型自动生成进度周报摘要或者质量整改意见初稿这个方向比较前沿如果你有余力尝试答辩效果会非常惊艳。最后再分享一个个人体会做这类项目最忌讳拿到源码就急着跑起来也不建议只盯着代码量。真正能把系统讲清楚、把每个设计决策背后的“为什么”答上来的同学哪怕功能少一两个分数也不会低。你把业务数据流理清楚了把表结构设计依据讲明白了这套SpringBoot架构下的建筑工程管理系统就不只是一份期末作业而是一份真正有行业价值的技术作品。
返回列表