news 2026/10/12 19:50:20

SpringBoot+Vue装饰工程管理系统毕设:从需求拆解到答辩避坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot+Vue装饰工程管理系统毕设:从需求拆解到答辩避坑

做装饰工程管理系统的毕设,很多同学拿到的都是类似的SpringBoot+Vue源码:后端Java、前端Vue、数据库MySQL,标题里写着“适合毕设/课设/学习”。项目本身不复杂,但如果你只是能把它跑起来,答辩时其实很吃亏。我前阵子刚好完整梳理过一个装饰工程管理系统管理平台,从需求里“工程管理”四个字出发,把整个项目的功能、表结构、核心接口、权限控制、常见坑都过了一遍。这篇就把我整理出来的思路写下来,希望能帮准备毕设或者刚开始学SpringBoot+Vue的人,真正搞懂这个项目能做什么、怎么拆、哪里容易翻车。

1. 项目定位与整体设计思路

这个系统叫装饰工程管理系统,本质上是一个面向装饰公司的业务管理平台。装修公司的核心业务链条是从客户意向、设计报价、合同签订,到施工进场、材料采购、进度跟进、竣工验收,最后结算收款。管理系统的目标就是把这条线上的人、事、钱、物集中放到一个平台里,减少Excel传表和微信催进度这些破事。所以做这个项目之前,先别急着写代码,第一件事是搞清楚“装饰工程管理”到底管什么。

1.1 为什么SpringBoot+Vue是这种项目的稳妥之选

如果你去搜索毕设选题,“SpringBoot+Vue”几乎是万能配方。原因很实在:后端SpringBoot能快速搭建一套RESTful API,它对MySQL的操作有天然生态,MyBatis或MyBatis-Plus写数据访问层很方便;前端Vue的组件化开发适合做后台管理系统,配合Element UI或者Element Plus,表单、表格、弹窗这些后台老熟人组件都是现成的。这种前后端分离的模式,正好符合当前中小型Web项目的开发习惯,也方便论文里画架构图、写技术选型分析。

另外,从答辩角度说,SpringBoot+Vue的技术栈是主流中的主流,面试官或评审老师基本都认识,不会问出什么冷门东西。出了问题也好搜答案,社区资料多,遇到跨域、Session失效、Maven依赖冲突这些问题,网上一搜一大把解决方案。所以不是它有多高大上,而是它足够“稳”。做毕设最重要的是在有限时间内稳定拿到结果,而不是炫技。

1.2 装饰工程管理到底管什么:需求拆解

这个系统的核心词是“工程管理”,那就要围绕工程项目的一整条生命周期来拆功能。我把常见的需求梳理成了五个大块:

  1. 用户与权限:系统里可能有超级管理员、项目经理、设计师、财务、材料员、老板等角色。不同角色能看到的数据和能执行的操作肯定不同。
  2. 项目管理:包括项目创建、分配项目经理、维护客户信息、确定施工地点、记录项目状态(如待开工、施工中、已停工、已验收)。
  3. 合同与资金:客户合同登记、合同金额、收款计划、实际收款记录,以及项目支出、付款申请等。
  4. 材料与库存:装修工程里的材料清单、供应商信息、材料入库出库记录、库存余量预警。
  5. 进度与验收:施工计划节点、实际进度填报、验收记录、售后或整改记录。

除此之外,很多源码里还会带上公告管理和操作日志。公告管理适合做系统首页轮播或通知栏,操作日志可以记录谁在什么时间改了什么数据,这两个模块虽然代码量不大,但对提升系统“完整性”很有帮助,写论文时也可以多凑一个功能点。

1.3 技术栈清单与版本选择

我建议在一个项目文档最前面列一章技术栈,不仅是为了论文,也是为了防止自己开发时被版本问题搞崩。以我梳理的这个装饰工程管理系统为例,比较省心的组合是:

  • 后端:Java 8(或Java 11),Spring Boot 2.7.x,MyBatis-Plus 3.5.x,Maven 3.6+,JWT做登录令牌(也可以用Spring Security,但很多人学起来觉得重,实际上对于毕设,自己写拦截器+JWT完全够用)。
  • 前端:Vue 2 + Element UI(或Vue 3 + Element Plus,看教程和源码版本,别混用),Axios发送请求,Vue Router管理路由,Vuex或Pinia管理登录状态。
  • 数据库:MySQL 5.7或8.0,Navicat操作即可。
  • 开发工具:IDEA(后端)、VS Code(前端)、Postman测试接口。

这里特别提醒一句,拿到源码第一步先看pom.xml里Spring Boot的版本和前端package.json里Vue的版本,如果源码是Vue 2写的,你非要用Vue 3去跑,大概率一堆报错;如果MyBatis-Plus版本太老,和新的MySQL驱动也容易出兼容问题。我见过很多同学卡在环境上,不是代码问题,是版本乱搭。

2. 核心功能模块与业务流程

这一部分我们逐个模块讲,从业务流程出发,看清前后端分别要做什么。别一上来就盯着某个Controller看,先把业务理顺,代码就是那点事。

2.1 用户权限与登录认证

装饰工程系统的用户不是只有一个管理员,常见角色我列一下:

  • 超级管理员:拥有全部权限,能管理所有项目、用户和系统设置。
  • 项目负责人(项目经理):查看自己负责的项目,填报进度,上传验收材料。
  • 设计师:维护客户设计方案和装修需求。
  • 材料员:负责材料供应商维护、材料入库出库。
  • 财务:查看合同金额、收款记录和支出记录。

登录认证的实现方式,一般源码里都是JWT。流程是:前端把用户名密码发给后端,后端校验成功后生成token返回给前端,前端把token存在localStorage里,之后每次请求在请求头带上Authorization: Bearer <token>,后端用拦截器校验token有效性并取出当前用户信息。这样就不需要传统Session了,符合前后端分离的架构。

权限控制则分为两层:第一层是接口权限,后端在拦截器里判断当前用户的角色能不能访问某个接口;第二层是页面和按钮权限,前端通过路由守卫判断用户登录状态和角色,动态渲染菜单。常见做法是在登录接口返回用户信息时带上角色标识,比如roleId或者roleKey,前端根据角色去显示不同的菜单项。

2.2 项目管理全流程(从立项到验收)

一个装饰工程项目从立项到验收,在系统里的流转大概是:

  1. 新增项目:录入项目名称、客户姓名、联系电话、房屋地址、建筑面积、装修风格、预算金额、项目负责人等信息。
  2. 上传设计文件:设计师可以把平面图、效果图等附件上传到项目下。
  3. 合同登记:财务或业务人员录入合同编号、合同金额、签约日期、付款方式,关联到项目。
  4. 施工进场:项目经理把项目状态改为“施工中”,可填写实际开工日期。
  5. 进度填报:项目经理定期填报施工阶段进度,比如水电改造、泥瓦工、木工、油漆、安装等节点,是否完成并上传照片。
  6. 竣工验收:项目经理填报完工日期,上传验收报告,状态改为“已验收”。

这套流程对应的表,至少是t_project(项目主表)、t_project_progress(进度表)、t_project_file(项目附件表)、t_contract(合同表)。在源码里,项目主表一般字段有customer_name、customer_phone、address、project_status、manager_id、budget_amount、create_time、update_time。

一个容易忽略的点是“状态流转”。很多毕设源码里的状态就是一个数字或字符串,直接在代码里if-else判断,初审代码时会觉得乱。但如果你用状态机思路去设计,比如定义0待分配、1待开工、2施工中、3已竣工、4已验收,并在后端service层写统一的更新状态方法,整个逻辑会更清晰,答辩时也更好讲。

2.3 材料、预算与成本管控

装饰公司很大一部分成本在材料上,所以材料管理模块是这个系统的核心之一。常见的功能有:

  • 材料分类维护:瓷砖、地板、油漆、电线、水管、木工板等。
  • 材料信息维护:材料名称、规格型号、单位、单价、供应商。
  • 材料入库:入库数量、入库单价、入库日期、经手人。
  • 材料出库(领用):出库数量、领用项目、领用日期、领用人。
  • 库存统计:根据入库和出库计算出当前库存余量。

数据库里一般会有t_material(材料表)、t_material_in(入库表)、t_material_out(出库表)。入库和出库分别建表的好处是方便查流水,坏处是库存会多算或漏算,因为可能有人操作时不严谨。所以很多系统里还会加一个“库存调整”功能,防止账面和实际对不上。预算与成本则单独有t_budget或t_cost表,但如果你只想做“核心功能”,材料进出库加上项目维度汇总就够了。

这块在答辩时很容易切入的点是:如果项目材料超支了,怎么预警?一个简化做法是在项目表里存budget_amount(预算金额),在材料出库表里按项目ID聚合出sum(total_amount)(实际领用金额),后端接口返回一个对比结果,前端用进度条展示。这套逻辑代码量不大,但演示效果很好,能明显提升系统说服力。

2.4 进度、质检与文档留痕

装饰工程周期长、环节多,不可能一个节点一个节点硬编码,所以进度表的设计需要体现出多节点。常见做法是:在项目下维护一个“施工阶段模板”,比如水电、瓦工、木工、油漆、安装、保洁,然后给每个阶段设置计划开始时间和计划结束时间。实际开始时,项目经理逐项把阶段状态改为“已完成”,并填写实际完成时间、上传现场照片。

有点良心的源码会在每个阶段表上加sort_order字段用于排序,不然阶段顺序会乱;还可能会加delay_remark记录延期原因。文档留痕则是把装修施工合同、验收单、变更单这些文件以附件的形式上传承到t_project_file表,比如新增项目材料、查看下载项目文档。文件上传一般放在一个公共的Controller里,接收MultipartFile后写到服务器本地目录,再把访问路径存进数据库。

这部分如果你要学,重点是理解“一对多”的关系:一个项目对应多个进度阶段,一个项目对应多个附件。前端就会用el-timeline时间线展示项目进度,用el-upload组件上传附件,效果很直观。

3. 数据库模型与后端接口设计

数据库设计决定了一个毕设项目的上限。大部分简单源码就是每个模块一张表加一张用户表,但如果你想在论文里写“数据库设计”这一章,至少要把核心表之间的关系理清楚。

3.1 关键表结构与字段说明

以我梳理过的这套装饰工程管理系统源码为例,核心表不会少于八张。我把最常用的列出来:

表名用途关键字段
sys_user用户表id, username, password, real_name, role_id, phone, status
sys_role角色表id, role_name, role_key, remark
t_project项目表id, project_name, customer_name, customer_phone, address, manager_id, project_status, budget_amount, start_date, end_date
t_project_progress项目进度表id, project_id, stage_name, plan_start, plan_end, actual_start, actual_end, status, sort_order
t_contract合同表id, project_id, contract_no, contract_amount, sign_date, pay_type, remark
t_material材料表id, material_name, material_type, spec, unit, price, supplier
t_material_in入库记录表id, material_id, in_number, in_price, in_date, operator, remark
t_material_out出库记录表id, material_id, project_id, out_number, out_price, out_date, operator, remark
t_project_file项目附件表id, project_id, file_name, file_path, upload_time, upload_user

用户表里密码一般是MD5或BCrypt加密存储,不要存明文。角色表不一定有权限表,简单系统直接按角色字符串判断就行,但这会在后期扩展时有点局限。如果你想让项目更有深度,可以加一张sys_menu菜单权限表,做到“角色-菜单”多对多,不过对毕设来说,工作量会涨不少。

项目表和进度表是典型的一对多,项目表和合同表是一对一(一个项目可能多份合同,但毕设简化为一对一更常见)。材料入库出库和材料表是多对一,出库记录通过project_id关联到项目,这样就能统计每个项目的材料领用成本。这个关系图如果你能画好,放论文里是很加分的。

3.2 核心接口设计与返回格式

后端接口设计的规范程度,直接影响前端联调效率。我看到很多毕设源码的接口返回格式五花八门,有的直接返回对象,有的返回List,有的返回null,导致前端要写一堆判断。推荐统一用一种Result类包装返回,例如:

public class Result<T> { private Integer code; private String msg; private T data; // getter/setter... }

成功返回code=200, msg="操作成功",失败返回code=500或者自定义错误码。分页查询返回一个包含total和records的对象。举个例子,分页查询项目列表的Controller可能长这样:

@GetMapping("/project/page") public Result<Page<Project>> pageProject( @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) String projectName) { Page<Project> page = projectService.page(new Page<>(pageNum, pageSize), new LambdaQueryWrapper<Project>() .like(StringUtils.isNotBlank(projectName), Project::getProjectName, projectName) .orderByDesc(Project::getCreateTime)); return Result.success(page); }

这里用MyBatis-Plus的LambdaQueryWrapper做条件构造,比手写SQL方便很多,也是现在很流行的写法。前端Axios统一在请求拦截器里加token,在响应拦截器里判断code,如果不是200就抛出Message.error(msg)。这样一个规范下来,前后端各写一次,后面所有接口都省事。

3.3 权限控制与异常处理

后端权限控制我建议用一个自定义拦截器做,而不是引入完整的Spring Security,除非你时间特别充裕。核心逻辑是:写一个JwtInterceptor,实现HandlerInterceptor的preHandle方法,在里面检查请求头里的token,解析成功就放行,失败就返回401状态码。

@Component public class JwtInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { String jwt = token.substring(7); Claims claims = JwtUtil.parse(jwt); if (claims != null) { request.setAttribute("userId", claims.get("userId")); return true; } } response.setStatus(401); response.getWriter().write("未登录或登录已过期"); return false; } }

然后在一个配置类里注册拦截器,排除掉登录、验证码、文件预览等公开接口。这种做法的好处是代码量少,逻辑一眼就能看懂,很适合答辩时讲解。异常处理方面,建议加一个@RestControllerAdvice的全局异常处理器,把业务异常和系统异常统一转成Result格式返回,避免前端拿到一个很大的堆栈字符串。

前端也要配合做路由守卫。每次跳转路由前,检查localStorage里有没有token,没有就强制去登录页。还要在Axios响应拦截器里判断401,跳转登录页并清空本地登录信息。这两个地方少了任何一个,都会出现“重新登录后页面不跳”或“直接访问URL也能看到页面”的问题。

4. 环境搭建与关键代码实现

光说不练假把式。这一章把搭建过程和几个核心代码片段列出来,方便你拿着源码对照着看。如果你是从零开始写,这个流程也能帮你快速起一个能跑的架子。

4.1 前端工程搭建与目录结构

前端用Vue CLI创建工程:

vue create decorate-project-web

安装依赖:

npm install axios vue-router vuex element-ui sass

我常用目录结构是这样的:

src ├── api // 所有请求接口封装 │ ├── login.js │ ├── project.js │ └── material.js ├── assets // 静态资源 ├── components // 公共组件 ├── layout // 后台主框架 ├── router // 路由配置 ├── store // vuex状态管理 ├── utils // 工具函数,比如request.js └── views // 页面 ├── login ├── dashboard ├── project ├── material └── user

路由配置需要区分无权限页面和有权限页面,我把需要登录的页面放在同一个meta: { requiresAuth: true }下,然后在全局守卫里统一判断。菜单根据登录用户返回的角色来渲染,最省事的做法是在前端写死好角色对应的菜单数组,但这样不灵活。不想写动态路由的话,也可以在登录后从后端获取一个“菜单列表”接口,根据返回值控制显示哪些菜单项。

4.2 后端工程搭建与依赖配置

后端使用IDEA创建Spring Boot工程,pom.xml里添加基础依赖:

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.19.1</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>

配置application.yml:

server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/decorate_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 123456 mybatis-plus: configuration: map-underscore-to-camel-case: true global-config: db-config: table-prefix: t_

注意表前缀。如果实体类叫Project,但表名是t_project,直接加table-prefix: t_就能自动映射,不需要在每个实体类上写@TableName("t_project"),省很多事。MyBatis-Plus的代码生成器(AutoGenerator)可以一键生成实体和Mapper,很多毕设源码里已经生成了,不用自己手写。

后端目录结构一般按controller、service、service.impl、mapper、entity放:

src/main/java/com/example/decorate ├── controller // 接口层 ├── service // 业务接口 ├── service/impl // 业务实现 ├── mapper // MyBatis-Plus Mapper接口 ├── entity // 实体类 ├── config // 配置类,比如拦截器 ├── common // Result, 常量 ├── util // JwtUtil等工具 └── exception // 全局异常

4.3 登录鉴权和用户信息接口

登录接口是第一个核心接口。前端把用户名和密码POST过来,后端校验用户是否存在、密码是否正确、状态是否正常,然后生成token:

@Override public Result<LoginVO> login(String username, String password) { User user = userMapper.selectOne( new LambdaQueryWrapper<User>() .eq(User::getUsername, username)); if (user == null) { return Result.error("用户名不存在"); } String md5pwd = DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)); if (!md5pwd.equals(user.getPassword())) { return Result.error("密码错误"); } if (user.getStatus() != null && user.getStatus() == 0) { return Result.error("账号已被禁用"); } String token = JwtUtil.createToken(user.getId(), user.getUsername(), user.getRoleId()); LoginVO vo = new LoginVO(); vo.setToken(token); vo.setUserInfo(user); return Result.success(vo); }

前端登录页拿到token后,localStorage.setItem("token", res.data.token),然后把用户信息存进Vuex。之后每次请求在request.js请求拦截器里加Header:

service.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) { config.headers['Authorization'] = 'Bearer ' + token } return config })

拿到用户详情时,后端可以根据用户角色动态返回菜单权限。如果项目没有菜单表,最简单的做法是在前端根据roleId判断,比如roleId=1显示所有菜单,roleId=2只显示项目管理和进度填报菜单。

4.4 从Excel导入导出施工材料清单的实现

很多装饰工程项目在施工前都会做一份“材料清单”,如果用Excel维护,后续入库出库又要在系统重新录入一遍,非常麻烦。所以我建议在这个项目里增加一个“材料清单导入导出”功能。前端用Element UI的el-upload组件上传Excel文件,后端用EasyExcel读取文件数据,批量插入到材料表。

@PostMapping("/material/import") public Result<?> importMaterial(MultipartFile file) throws IOException { List<MaterialExcel> list = EasyExcel.read(file.getInputStream()) .head(MaterialExcel.class).sheet().doReadSync(); materialService.saveBatch(list.stream().map(item -> { Material m = new Material(); m.setMaterialName(item.getName()); m.setSpec(item.getSpec()); m.setUnit(item.getUnit()); m.setPrice(item.getPrice()); return m; }).collect(Collectors.toList())); return Result.success(); }

这个功能代码量不多,但在演示时效果很好。你可以提前准备一份几个excel测试数据,现场点击上传,很快得到几十条材料记录,比一条一条用手敲强太多。论文里也能写一个“批量导入设计”。

5. 常见问题与排坑实录

这部分是我最想说的。毕设源码很多同学能跑起来,但答辩或演示时一操作就翻车,基本都发生在下面几个点上。

5.1 前后端跨域与session失效问题

前后端分离后,前端跑在8081端口,后端跑在8080端口,直接请求会被浏览器跨域拦截。解决方法是后端加跨域配置:

@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); } }

这里有个坑:如果你用了JWT,跨域配置里的allowCredentials(true)和allowedOriginPatterns("*")必须一起用,不能只写allowedOrigins("*"),否则浏览器会报错。另外,每次请求前会有一次OPTIONS预检请求,后端拦截器要放行OPTIONS方法,不然前端会显示“跨域但不允许该请求”。

我自己还遇到过一种情况:登录成功后,前端发下一个请求还是报未登录。原因通常是前端请求头没带上token,或者token存的时候多了空格。可以打开浏览器DevTools看Network面板,检查请求头里Authorization是否正确。这个小细节能解决80%的“为什么一会儿登录一会儿没登录”。

5.2 日期时间字段传输时的时区问题

MySQL里的datetime字段,后端LocalDateTime类型接收后,返回给前端往往是一个很奇怪的日期,比如“2024-08-01T13:45:00”,但页面显示却没有时分秒,或者在Linux服务器上差了8小时。这个问题几乎每个毕设项目都会遇到,原因是Jackson序列化LocalDateTime默认格式不带时区。

解决方法是加一个全局时间格式配置:

@Configuration public class JacksonConfig { @Bean public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { return builder -> { builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss"); builder.serializers(LocalDateTimeSerializer.of(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); builder.deserializers(LocalDateTimeDeserializer.of(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); }; } }

同时数据库连接url必须带serverTimezone=Asia/Shanghai。这样前后端显示的日期都是“yyyy-MM-dd HH:mm:ss”格式,既友好又不会差8小时。日期字段在Vue端也尽量别自己拼字符串,直接展示后端返回的格式化结果。因为Element UI的日期选择器默认绑定Date对象,如果你传的是字符串,可能还需要在提交时转一下格式,这块很容易出bug。

5.3 MyBatis返回Map时null值字段丢失

有些查询接口我喜欢直接返回List<Map<String, Object>>,比如用SQL聚合统计每种材料的出入库总量,这样省去建VO类的麻烦。但MyBatis-Plus默认配置下,如果某个字段为null,返回的Map里会直接没有这个key,前端res.data.sum == undefined,而不是0。这会导致前端求和或判断时报错。

解决办法有三个:一是在SQL里用IFNULL(SUM(num), 0) AS sum,把null转成0;二是在MyBatis全局配置里设置call-setters-on-nulls为true(MyBatis-Plus也有对应配置);三是在前端用|| 0兜底。我个人建议SQL里写IFNULL最简单直接,既保证数据完整,又不需要额外配置。这种方式写习惯之后,出统计接口的效率很高。

5.4 前端路由刷新404和按钮权限闪烁

如果用了history模式路由,刷新页面时会出现404。因为前端是单页应用,后端服务器无法直接找到/project/list这种路径对应的文件。解决办法有两个:后端Web服务器做try_files配置,或把Vue路由改为hash模式。但hash模式URL会带一个“#”,不太美观。如果不是部署到Nginx,只是演示和本地跑,hash模式最省心,只需要在router配置里把mode: 'history'改成mode: 'hash'。

另一个常见问题是按钮权限闪烁:刷新页面后,用户信息还没从localStorage恢复,页面就会先渲染出来,导致按钮权限一瞬间全部消失或全部出现,然后才正常。这是因为数据是异步获取的。解决方案是在路由守卫里判断当前用户信息是否为空,为空就先await调用获取用户信息的接口,再放行路由。这样虽然加载慢一点点,但不会出现闪烁。

还有一个小坑:Element UI的el-table分页组件如果设置current-page是数字0,会显示不出数据。一般分页页码从1开始,不要自己用0初始化。后端分页请求时也注意pageNum参数默认值从1开始,不要从0开始。

5.5 其他高频问题速查表

问题原因解决办法
连接MySQL失败驱动jar版本或数据库不存在检查mysql-connector-j版本,先手动在Navicat建好库
中文乱码数据库/连接url编码不对建库时用utf8mb4,url加characterEncoding=utf8
Maven依赖下载慢或失败网络和仓库源阿里云镜像配置到settings.xml
前端启动报错Module not found依赖未安装删除node_modules,重新npm install
上传文件后不能访问静态资源映射未配置配置WebMvcConfigurer.addResourceHandlers把本地目录映射到/upload/**
权限错误提示英文后端没有统一异常处理加全局异常处理器,统一Result返回中文
数据库表字段修改后实体类没同步手动改库,忘了改代码改完表后同步实体类和Mapper XML

6. 这份源码怎么用于毕设答辩与二次扩展

源码能跑只是第一步,能讲清楚、能体现出自己的思考,才是拿高分的关键。以下是针对装饰工程管理系统这个题目的答辩和扩展建议。

6.1 如何在答辩中讲清“你做了什么”

很多同学讲自己的毕设,都会从“登录注册”开始,讲着讲着就变成了“用户管理”。如果目标是装饰工程管理系统,建议重心放在项目全流程和材料成本控制上。你可以按照这个顺序讲:

  1. 先说这个系统解决什么问题:装饰公司项目分散、材料成本不受控、进度反馈靠微信。
  2. 再说系统有哪些角色:超级管理员、项目经理、材料员、财务。
  3. 然后演示一个完整流程:管理员创建项目 → 指定项目经理 → 项目经理维护进度 → 材料员做材料入库和出库 → 财务查看项目合同与材料汇总。从一条真实数据链路把系统串起来,老师跟着你的演示走,会觉得整体感很强。
  4. 最后可以讲一个难点:比如材料出库后如何统计项目材料总成本,涉及SQL聚合和前端图表展示。

不用每个功能都演示,贪多反而记不住。准备一个5分钟的演示脚本,反复练几遍,保证不卡壳。

6.2 适合扩展的点:从“能跑”到“有亮点”

拿到源码后如果想加一点自己的东西,我推荐下面几个方向:

  1. 材料库存预警:在材料表加一个min_stock字段,当库存低于该值时,在首页用图表或列表提醒。这个小功能可以结合定时任务或前端轮询实现,代码量适中。
  2. 项目成本与预算对比:给项目表加budget_amount,材料出库表加total_amount,后端写一个聚合接口,前端用ECharts画柱状图对比预算和实际成本,比纯表格演示效果好很多。
  3. 导出项目进度报告:用EasyExcel或itext把项目进度汇总导出成Excel/PDF文件。答辩时演示导出功能,非常接地气。
  4. 消息通知:当项目经理填报重大进度节点时,给管理员发送系统消息。可以用WebSocket,也可以简单地在消息表里插入记录,前端轮询获取未读数量。

不要小看这些“小功能”,它们成本低,但能让老师觉得你不只是把源码跑通了,还理解了业务并做了提升。

6.3 最后的几点个人建议

做这个项目,我最大的感受是:一个毕设系统的难点不在于技术有多深,而在于你愿不愿意把业务理顺。装饰工程管理系统如果只是CURD堆砌,那和普通的增删改查没区别;但如果你把项目状态流转、材料出入库、权限角色、进度节点之间的关系讲清楚,整个系统的价值立刻就不一样了。

我自己在梳理过程中,数不清踩了多少版本和配置的坑。印象最深的是一次前端把所有接口都调通之后,上传的图片却无法访问,折腾半天才发现是Spring Boot没有把本地磁盘的upload目录映射成静态资源路径。解决方法就是在配置类里加几行代码。这种问题如果是答辩现场遇到,真的会心态崩掉。所以强烈建议在答辩前把高频操作完整走一遍,包括重启前后端、刷新页面、上传文件、导出Excel,所有可能出状况的环节都预先演练。

最后分享一个小技巧:项目里一定要加日志。用@Slf4j在service层打一些关键操作日志,比如“用户xxx于xxx修改了项目状态”,既能帮你排查问题,又能在答辩时展示你有除了业务接口外的系统设计。代码写得好不好另说,日志和统一返回格式这两个习惯,足以让评审老师对你刮目相看。希望这篇内容能帮你把这个经典项目做出自己的亮点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/12 19:46:06

Mangos世界库编辑指南:物品任务BOSS数据修改与SQL实践

简介&#xff1a;面向Mangos服务端运维与私服配置人员&#xff0c;这套工具包用于可视化编辑物品、任务、BOSS、NPC等核心数据&#xff0c;解决手工改数据库时字段多、表关系复杂、易出错的问题&#xff0c;也适合刚接触Mangos的玩家快速掌握常用配置入口。压缩包共66个文件&am…

作者头像 李华
网站建设 2026/10/12 19:42:32

Prime算法辨析:素数判定与Prim最小生成树全解析

先说个常见的困惑&#xff1a;如果你把“Prime算法”丢给搜索引擎&#xff0c;会同时冒出两条完全不同的路线——一条是图论里求最小生成树的Prim算法&#xff08;很多人打字顺手就写成 Prime&#xff09;&#xff0c;另一条则是和“prime number&#xff08;素数&#xff09;”…

作者头像 李华
网站建设 2026/10/12 19:42:22

EasyPlayer-RTSP-Win 深度拆解:RTSP 播放器集成与低延迟调优实战

简介&#xff1a;EasyPlayer-RTSP-Win 是一套面向安防流媒体开发者的 Windows RTSP 播放器组件&#xff0c;适合需要在自有项目中集成直播、录像、抓图能力的 C/C# 工程师。它支持 H.264、H.265、MPEG4、MJPEG 视频编码与 G711A、G711U、G726、AAC 音频编码&#xff0c;兼容 RT…

作者头像 李华
网站建设 2026/10/12 19:32:20

RT-Thread上FatFs文件系统重入配置与多线程并发读写实战

1. 项目背景与核心需求拆解1.1 为什么要在实时操作系统上折腾文件系统做过嵌入式开发的人都有一个共识&#xff1a;裸机跑程序的时候&#xff0c;数据存储怎么简单怎么来&#xff0c;直接操作Flash扇区或者EEPROM读写就行。但一旦项目复杂度上来&#xff0c;尤其是引入实时操作…

作者头像 李华