尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

SpringBoot+Vue+MySQL:建筑材料管理系统毕业设计全栈实战

发布时间:2026/9/26 4:36:47

资讯中心
01
ARTICLE

SpringBoot+Vue+MySQL:建筑材料管理系统毕业设计全栈实战

SpringBoot+Vue+MySQL:建筑材料管理系统毕业设计全栈实战
做毕业设计最怕的不是写不出代码而是不知道系统的边界到底在哪里。这两年我陆续收到不少读计算机或软件工程专业的同学提问十个人里有六个都在做同一个方向的题目SpringBoot加Vue写一套管理系统。而《建筑材料管理系统》就是其中出镜率非常高的一道题。很多人开始以为这就是一套简单的增删改查可真打开需求一看入库、出库、供应商、库存预警、材料分类、项目领料、统计报表每一样都要处理好。基于SpringBoot框架做后端、Vue做前端、MySQL存数据再加上数据库脚本和毕业论文文档这套方案完全可以覆盖一个计算机毕业设计的全部工作量。本文把从需求拆解、表结构设计、后端接口实现、前端页面联调到毕业论文整理和常见踩坑点完整梳理了一遍适合正在准备毕设、计划把题目做成全栈项目的同学参考也适合想掌握SpringBootVue开发闭环的入门者当作实战案例来啃。1. 题目拆解建筑材料管理系统到底在管什么1.1 先想清楚角色和流程再决定做多少页面很多同学拿到题目会急着建工程这是最容易踩的坑。建筑材料管理系统听起来很像教材里跑通的“XX管理系统”于是上来就是一个MaterialController几个页面对应四个增删改查做完就以为万事大吉。但把它放到真实场景里材料不是一个简单字典它从“进”到“存”再到“出”是有流转的供应商送来材料仓管员登记入库库存增加施工队或项目需要用料仓管员登记出库库存减少当库存低于安全线系统要提醒采购补货。整个过程还涉及价格、数量、供应商信息的追溯如果不提前拆清楚后面写代码时十有八九会把字段堆在同一张表里。我建议把角色聚焦为三类系统管理员负责用户和基础数据维护仓管员负责材料、供应商和出入库操作普通用户只做查询与领料申请。如果学校对用户管理要求不高甚至可以简化成管理员和仓管员两种角色。核心模块放在五个地方材料分类管理、供应商管理、入库管理、出库管理、库存查询与预警。项目领料这一块如果做进去需要在出库单上增加“领用单位”或“项目名称”字段如果不想扩展出库单上的“领用人 领用项目”两个字段也能解决演示问题。功能范围确定之后再画一个简单的功能结构图心里就会清楚每张页面放哪、每个接口服务谁。这一步花不了半小时但能在后面省下好几个晚上的返工时间。尤其要跟指导老师确认清楚要不要做项目维度统计、要不要做材料盘点、要不要做多级审批。这类扩展是最容易让答辩老师觉得“工作量不够”的要素也是系统从“练习项目”走向“毕业设计”的分水岭。1.2 为什么放弃JSP选择SpringBootVue这套组合前几年很多校内课程还在用SpringMVC加JSP页面和服务端混在一起写起来省事但答辩时不好讲功能复杂以后维护也痛苦。现在企业里做管理系统大多数是前后端分离的架构后端用SpringBoot提供REST接口前端用Vue框架通过Ajax调用接口渲染页面。两个工程可以独立开发、独立测试也方便分工。如果你的项目组有两三个人一个人写后端接口一个人写页面数据库脚本可以由另一个同学专门维护效率会高很多。SpringBoot在这里的核心价值是“简化配置”内嵌Tomcat不用单独部署Web容器默认支持REST接口配合MyBatis-Plus之后连最简单的单表CRUD都可以少写大量SQL。Vue的核心价值是“组件化”一个表格页面、一个弹窗表单、一个状态标签都能拆成组件复用页面代码比传统模板引擎清晰得多也更容易体现出工作量。数据库用MySQL就够了同时把SQL脚本导出发给组员和老师保证环境一致。当然这个选择也有代价前后端联调需要处理跨域、接口约定、Token等额外问题。这些我会在后面的章节里逐个写出来。总体而言SpringBootVueMySQL是目前毕业设计里性价比最高的全栈组合既踩得到技术点又不容易绕进底层坑里出不来。1.3 功能边界哪些能做哪些先不做一个常见的错误是需求发散。同学做到一半突然想加“材料二维码扫码入库”“微信小程序查看库存”“智能补货预测算法”然后项目就不受控制了。毕业设计的核心不是功能越多越好而是让每一个功能都能被讲清楚、能演示、能和数据库设计对上。我的建议是所有扩展功能先问自己三个问题数据从哪里来要新增几张表演示时是否能在两分钟内走到效果答不上来就先不做。真正可以低成本加入的扩展点有两个一是库存预警在材料表加一个safety_stock字段库存查询时用当前库存和安全库存做比较即可二是首页统计看板统计今天入库多少、出库多少、低库存材料总数。这两个功能不复杂却很能提升系统的完整度也能让答辩PPT里的“亮点功能”多一页。2. 数据库设计一张库存表撑不起一个系统2.1 核心表拆解与字段规划数据库是这套系统最容易翻车的地方。很多同学会直接在material表里放一个stock字段然后入库时update把它加一出库时减一。单机跑demo没有任何问题但论文里写不下去“库存账与单据对应关系”也说不清。所以建议把库存和业务单据分离库存表只是一个状态结果真正可信的数据是每一张入库单、出库单。基础资料有三张表材料分类表material_category材料表material供应商表supplier。材料表至少要包含分类ID、材料编号、名称、规格型号、计量单位、参考单价、安全库存、状态。材料编号建议设计成唯一编码例如JC-001这种业务编码而不是直接用主键。供应商表则放供应商编码、名称、联系人、电话、地址。业务单据用主从表结构这样一张入库单可以记录多种材料也更贴近仓库作业。入库单主表stock_in单号、供应商ID、操作人、入库日期、总金额、备注子表stock_in_item主表ID、材料ID、数量、单价、小计金额。出库同理分别为stock_out和stock_out_item出库子表字段可以省去价格但增加领用单位等信息。库存表inventory只保留material_id和quantitymaterial_id需要设为唯一索引保证每种材料只有一条库存记录。这种设计的意思是所有库存变化都能从单据回溯而不只是“内存里面一个数字加减”。很多老师第一眼就会看表结构见了主从表基本能确认你认真做了数据库设计。可以说这是整套系统的地基。2.2 关键约束与索引设计建表时不要偷懒不加外键。虽然MyBatis和代码能保证数据一致但在数据库层面加上外键约束能防止直接SQL操作造成脏数据。至少要给子表的material_id、supplier_id等字段加上外键约束或逻辑外键索引。例如ALTER TABLE stock_in_item ADD INDEX idx_material (material_id);如果使用了FK则外键自动索引。需要特别注意如果使用MySQL默认的InnoDB存储引擎删除被引用材料时会受外键约束限制这反倒是一种保护。时间字段统一使用datetime金额字段使用decimal(10,2)数量字段使用decimal(12,3)而不是int因为很多建材不是按整袋出库的沙子水泥可能按吨、按立方米计量。状态字段用tinyint比如0为停用、1为启用不要用字符串。布尔值也尽量用tinyint(1)避免不同MySQL版本对boolean的兼容性差异。建一张材料表可以参考下面的SQL核心片段CREATE TABLE material ( id bigint NOT NULL AUTO_INCREMENT, category_id bigint NOT NULL COMMENT 分类ID, code varchar(50) NOT NULL COMMENT 材料编码, name varchar(100) NOT NULL COMMENT 材料名称, spec varchar(100) DEFAULT NULL COMMENT 规格型号, unit varchar(20) DEFAULT NULL COMMENT 计量单位, reference_price decimal(10,2) DEFAULT NULL COMMENT 参考单价, safety_stock decimal(12,3) DEFAULT NULL COMMENT 安全库存, status tinyint DEFAULT 1 COMMENT 1启用0停用, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_code (code), KEY idx_category (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT材料信息表;这里设置了唯一键uk_code防止材料编码重复idx_category用于分类筛选字段注释写清楚后面直接复制到论文数据库设计章节也很方便。最后一个细节如果用了MyBatis-Plus实体类的字段名与数据库列名的驼峰映射要打开map-underscore-to-camel-case: true。SpringBoot的properties中通常是mybatis-plus.configuration.map-underscore-to-camel-casetrue。否则你会遇到create_time查出来是null这种诡异问题。2.3 初始化数据与数据库脚本准备数据库脚本不是简单把建表语句粘出来就行。一份合格的毕业设计SQL脚本应该包含创建数据库、建表、插入基础数据三个部分。基础数据至少要有管理员账号密码加密后存入两三个供应商材料分类为沙子、水泥、钢材等加上对应的材料和库存数据。这样前端页面一启动就有内容可以展示不至于登录后空空如也演示效果大打折扣。如果用手工Excel整理再导入要注意字符集问题建议统一utf8mb4。另外给脚本加上注释表明每张表的作用文件头写明“导入前请先执行source create.sql”。这样指导老师在本地几分钟就能把环境跑起来后面答辩演示会非常顺畅。3. SpringBoot后端把业务写清楚别只做CRUD3.1 工程分层与统一接口返回后端工程建议按controller、service、service.impl、mapper、entity、dto、config、common来分层。entity对应数据库表dto用来接收页面传递的参数比如分页参数、入库单DTO不要一股脑把前端参数全塞进实体类。controller只做参数接收和结果转发不写业务。service处理业务规则mapper只做数据库操作。所有接口返回值建议统一封装成一个泛型Result类前端收到后只需要判断code就可以知道业务成功还是失败。这里给出一份最精简的写法public class ResultT { private Integer code; private String msg; private T data; public static T ResultT success(T data) { ResultT r new Result(); r.setCode(200); r.setMsg(success); r.setData(data); return r; } public static T ResultT error(String msg) { ResultT r new Result(); r.setCode(500); r.setMsg(msg); return r; } // getter/setter 省略 }这样做的好处是前端axios拦截器只需要判断code不管每个接口返回结构代码整洁很多。再配合RestControllerAdvice全局异常处理业务方法里只要抛出BusinessException前端就能拿到一个统一的错误提示不用每个controller写try-catch。3.2 登录认证与密码加密管理系统不该裸奔登录功能是必须的。毕业设计做Token登录已经足够用户登录成功后后端根据用户信息生成一个Token前端保存到localStorage并放在请求头里后端用拦截器校验每个需要登录的接口。Token可以用JWT也可以用普通UUID加Redis。如果不想引入Redis用JWT最省事密钥写在配置里即可。密码存储不能明文建议用Spring Security自带的BCryptPasswordEncoder或者用Hutool的BCrypt工具类。网上很多教程用MD5加盐也凑合但答辩时老师说BCrypt更专业。把这个细节放进论文“系统安全性”那一节有加分效果。登录接口示例思路Service public class UserServiceImpl implements UserService { Override public String login(String username, String password) { User user userMapper.selectOne(new LambdaQueryWrapperUser() .eq(User::getUsername, username)); if (user null || !BCrypt.checkpw(password, user.getPassword())) { throw new BusinessException(用户名或密码错误); } // 生成JWT return Jwts.builder() .setSubject(user.getUsername()) .setExpiration(new Date(System.currentTimeMillis() 24 * 3600 * 1000)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); } }这里secretKey通常放到application.yml里用环境变量覆盖更好。答辩时问“Token过期怎么办”只要说响应拦截器统一处理401跳回登录页并把有效期设为24小时即可这个回答足够完整。3.3 入库与出库用事务保证库存一致性入库的核心逻辑是把单子写进stock_in主表同时把明细写进stock_in_item最后把数量合并到inventory表。每张单子可能对应多种材料所以入库接口通常接收一个主表DTO和子表List。Service中先插入主表拿到主键ID再循环插入子表最后更新库存。三个动作必须在一个事务里完成否则一旦中间报错就会出现“单据写入了库存没加”的数据不一致问题。出库逻辑相反但机会点更多先查当前库存如果小于出库数量直接抛异常“库存不足”如果够用则写入出库单和明细接着扣减inventory表的数量。并发环境下还要考虑两个请求同时出库同一材料的情况这里给一个常见的悲观锁写法Inventory inv inventoryMapper.selectForUpdate(materialId); if (inv null || inv.getQuantity().compareTo(demandQty) 0) { throw new BusinessException(库存不足); } inv.setQuantity(inv.getQuantity().subtract(demandQty)); inventoryMapper.updateById(inv);selectForUpdate是加了for update的SELECT语句会锁住这一行直到事务提交其他事务必须等待从而避免超卖。多个人同时操作时这个写法比“查出来判断再直接update”要安全得多。别看这个点很小写进论文“技术难点”部分非常加分。3.4 查询、分页与多条件筛选材料列表、库存列表这类页面几乎都有分页。MyBatis-Plus配合分页插件可以省掉大量手写LIMIT的活。配置一个MybatisPlusInterceptor加入PaginationInnerInterceptor然后在Service里写PageMaterial page materialMapper.selectPage(new Page(current, size), new LambdaQueryWrapperMaterial() .like(StringUtils.hasText(name), Material::getName, name) .eq(categoryId ! null, Material::getCategoryId, categoryId) .orderByDesc(Material::getId));这样前端只需要传current、size、name、categoryId后端返回总数量和列表数据即可。要注意like条件需要判断参数不为空不然会出现收到空条件时返回空列表的尴尬。对于库存预警接口其实就是lessThan查询安全库存与当前库存的差值直接在inventory和material表关联查询即可。4. Vue前端从空页面到完整交互4.1 项目初始化和目录组织前端我建议用Vue3配合Vite也可以按学校要求用Vue2加Vue CLI核心逻辑差不多。如果还不太熟悉用Vue2更稳妥资料多、踩坑少Vue3也是目前主流组件写法更简洁。创建工程命令不复杂npm create vitelatest bms-web -- --template vue cd bms-web npm install npm install axios vue-router pinia element-plussrc目录下可以分api存放axios封装和接口定义router存放路由表store存放Pinia的登录状态views放页面components放公共组件utils放本地存储和鉴权工具。前端页面数量控制在八到十个左右登录页、系统布局、材料分类、材料列表、供应商管理、入库管理、出库管理、库存查询、库存预警。如果还想加一个简单的看板页或首页统计难度也不大。4.2 路由守卫与Token处理页面是不能直接打开的登录后才能进入系统。在router.beforeEach里判断localStorage里有没有token没有就重定向到/login。axios封装时加请求拦截器service.interceptors.request.use(config { const token localStorage.getItem(token); if (token) config.headers.Authorization Bearer ${token}; return config; });响应拦截器统一处理code不为200的情况弹出错误消息并跳登录。这样每个页面的接口调用都只用关心业务数据代码干净很多答辩时展示这一层封装会让老师觉得你有工程意识。4.3 材料进销存页面的实现要点材料列表页是典型的“搜索表格分页弹窗”重点不是把功能堆出来而是要把状态管理清楚。表格数据用ref维护查询参数用一个reactive对象调用接口后重新加载。Element Plus的el-table自带多选、排序、空状态入库弹窗里选择材料时最好联动展示该材料当前的可用库存这样出库时用户就知道不能超出多少。出库表单提交前做一次前端校验比如出库数量必须大于0但真正可靠的是后端接口里的事务判断前端校验只是提升体验。入库单和出库单页面需要有点核心交互点新增时弹出表单表单里允许动态添加多行明细。用el-dialog加动态行的实现不难维护一个tableData数组每行有materialId、quantity、price。材料下拉选择后自动带出规格和单位。计算总金额放在前端展示后端再算一遍并落库。这样页面看起来很有“业务系统”的感觉。动态行明细的核心结构大概是const detailRows [ { materialId: null, materialName: , spec: , unit: , quantity: null, price: null } ]; function addRow() { detailRows.push({ materialId: null, materialName: , spec: , unit: , quantity: null, price: null }); } function removeRow(index) { detailRows.splice(index, 1); }提交时把表头字段和detailRows一起post到后端。后端接收到的是一个包含主表信息和一个明细列表的JSON对象正好对应前面设计的主从表结构。4.4 前后端联调、跨域代理与打包本地开发时前端和后端不在一个端口会有跨域问题。最省事的方案是开启Vue开发服务器代理以Vite为例在vite.config.js中写server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true, rewrite: path path.replace(/^\/api/, ) } } }后端接口如果统一是/api开头就按上面的写法所有请求从浏览器发出时都指向前端端口再由Node服务代理到后端。这样浏览器不会直接跨域省去在后端配置CORS的麻烦。但要注意后端如果加了全局跨域处理二者可以共存只是不要两边配置冲突。打包时执行npm run build生成的dist可以用Nginx托管。如果部署在服务器上Nginx里要把前端路由回退到index.htmllocation / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; }否则刷新页面会出现404这是毕设部署时最常见的坑之一。5. 数据库脚本、接口文档和毕业论文这些才是加分项5.1 先定接口契约再写代码前端和后端联调时最怕两个人各按各的想法来后端把参数叫materialName前端非要传name接口反而调不通。所以开工前花半小时在ApiPost或Swagger里把接口清单整理出来表格里写明路径、请求方式、入参出参。比如功能接口路径请求方式主要入参返回结果分页查询材料/api/material/pagePOSTpage, size, name, categoryId表格数据总数新增入库单/api/stock/in/addPOST主表明细列表成功或错误库存预警列表/api/inventory/warningGET无低于安全库存数据不要觉得花时间这些表格稍作复制就能进论文的“接口设计”章节。更重要的是接口统一之后前后端并行开发谁也不等谁。5.2 论文每一章该怎么组织很多同学把论文放到最后一天写这是最亏的一件事。写代码时的每一步决策都是论文素材边做边记录会轻松很多。建议论文章节按摘要、第一章绪论背景、意义、国内外现状、第二章技术介绍SpringBoot、Vue、MySQL、第三章需求分析用例图、用例描述、第四章系统设计架构图、功能模块、数据库设计、第五章系统实现页面截图加核心代码讲解、第六章系统测试测试用例、功能测试、并发测试结论、第七章总结与展望。数据库设计那一章重点放E-R图和表结构说明E-R图用ProcessOn画的截图就行不用复杂工具。系统实现章节不要堆全部代码挑两三个有代表性的写就行比如登录验证、入库入库事务、动态添加入库单其他地方用文字说明。测试章节可以用简单的功能测试表格记录操作步骤、预期结果、实际结果。这些准备好之后答辩时老师问什么都能有据可答。5.3 演示数据和演示脚本毕业答辩现场通常只有十来分钟最怕的是准备的演示数据不够典型。不要在系统里放几十条毫无意义的数据建议准备一组有故事的数据三个供应商六种材料其中两种库存低于安全库存一条入库单配三种材料。打开库存页面就能看到红色预警打开库存预警页面有数据可数打开入库单看得到明细和总金额。这样每个页面都有内容可以讲也方便老师现场操作测试。数据库脚本建议最后多跑几遍删掉整个库用source导入再启动后端看功能是否正常。这个流程如果能在答辩前跑通就能排除“环境问题导致演示失败”的风险。6. 常见问题与排查技巧实录6.1 高频问题的按图索骥开发过程中总有各种想不到的问题。我把自己和学生们在SpringBootVue项目中常遇到的情况整理成了一张对照表覆盖了从环境到部署的全流程现象常见原因解决办法前端访问后端接口报跨域devServer代理没配置或请求路径不对检查proxy配置确认后端接口是否统一前缀MySQL连接失败Public Key Retrieval is not allowedMySQL8连接配置缺allowPublicKeyRetrievalJDBC URL加上allowPublicKeyRetrievaltrueuseSSLfalse页面刷新404前后端路由冲突Nginx没有try_files配置location中try_files指向index.htmlJava实体日期字段返回给前端格式不对没配Jackson日期格式在application.yml中配置日期格式或加JsonFormat后端返回null字段很多没打开驼峰映射或实体字段命名不一致配置map-underscore-to-camel-casetrue打包后前端接口地址还是localhost全局axios封装中baseURL写死改为环境变量VITE_API_BASE_URL打包时替换入库单插入成功但库存没变事务没有生效或库存更新逻辑在事务外Service方法加Transactional确认方法被代理调用JWT过期后页面一直报错响应拦截器没处理401在响应拦截器里统一跳到登录页这张表做出来之后不仅是自己排查问题的索引也是论文测试章节的素材。答辩时老师问“遇到过什么问题”直接从这个表里挑两条讲效果非常好。6.2 最值得注意的三个设计教训第一个是“别为了一点简单功能引入重型依赖”。有同学为了做图表统计前端接了一大堆ECharts的懒加载和主题后端接了一个Excel导出组件结果版本互相冲突最后全部删掉重来。毕业设计里能用原生表格、CSS和简单图表解决的就不要堆库堆库反而容易变成事故现场。第二个是“别把所有代码都放在一个Controller里”。刚写的时候图省事用户管理、材料、供应商、出入库全部写在一个Controller里后期改一个功能要翻几百行。后面重新拆分花的时间比当时省下的一点要多得多。工程结构一开始就要分好这是所有优秀项目的前提。第三个是“写接口前一定要定好统一返回结构”。如果等联调时再改前端要跟着改几十处很容易心态崩。所以从第一个接口开始就坚持使用Result包装哪怕有的接口只返回一个提示文本也要包一层。这个好习惯会让后期越写越顺手。6.3 答辩前的最后一轮自测清单建议答辩前按这个清单过一遍删除数据库重建脚本能否一次性导入成功用不同浏览器系统打开页面是否功能正常正在使用的账号是否会在演示中途登录过期库存预警数据是否存在移动端缩放是否不影响核心操作后端日志是否没有红色异常刷屏。每个功能都从上到下操作一遍尤其是“新增入库单”这种带明细的功能最好演示两次确认数据正确更新到库存页面。做完这些检查剩下的重点就不是“能不能跑”而是“能不能讲清楚”。建议把E-R图、功能结构图、核心接口列表打印出来放在手边。答辩的时候先讲需求背景再讲系统怎么设计最后花两分钟演示核心流程时间刚刚好。这段项目做完之后我最大的体会是毕业设计更像是一次“把需求翻译成代码再把代码翻译回文字”的训练。刚开始你可能只想着把所有页面做出来但真正把它当成一个完整交付物对待后你会发现数据库脚本、接口文档、测试记录和工程规范这些“看不见”的工作才是决定分数上限的东西。我也见过有人花一个星期把功能写完却因为现场无法演示、论文全是流水账丢掉分数。其实只要在设计和联调阶段多留一份心把每个关键决策都记录下来答辩就会非常从容。希望这篇梳理能帮你把SpringBoot加Vue的第一套全栈系统做得更稳也欢迎在真正动手时多想一步库存账为什么这样存接口为什么这样约定事务为什么要放在这一层。想清楚这些问题代码水平一定比只会照抄项目强得多。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。