ARTICLE DETAIL

资讯详情

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

SpringBoot+Vue+MySQL在线装修管理系统:设计思路与实现拆解

SpringBoot+Vue+MySQL在线装修管理系统:设计思路与实现拆解 开门见山说一句装修公司真正需要的从来不是一个展示型官网而是一套能把客户、设计师、施工队、预算、材料、进度全部串起来的内部管理系统。这套在线装修管理系统就是这个定位——基于 SpringBoot 后端、Vue 前端、MySQL 数据库的前后端分离项目代码结构规整配置完整导入 IDE 配好环境就能跑。我花了一下午时间把它完整跑通又从业务逻辑层面过了一遍代码这篇就把项目拆开讲清楚包括它到底管理了什么、技术选型为什么是这一套、数据库怎么设计、接口权限怎么做、前端页面怎么接以及“可直接运行”这五个字背后需要你注意哪些坑。1. 这个项目解决的痛点装修行业的信息断层全在这里1.1 纸质单据和微信群撑不起一个装修项目做过装修行业软件的人应该深有体会一个普通家装项目从客户咨询到最终验收中间至少要经过量房、设计、报价、签合同、材料采购、施工交底、水电木瓦油各工种进场、节点验收、竣工保洁十几个环节。每个环节都涉及不同角色业主要看进度设计师要传图纸工长要报材料计划采购要核价格财务要管分期款。传统做法是微信群加 Excel信息散落在每个人的聊天记录和本地表格里一旦某个环节出问题想追溯责任方就得翻几个月的聊天记录。这套在线装修管理系统把核心流程搬到了线上业主在线提交装修需求管理员分配设计师设计师上传设计方案和报价单施工阶段工长按节点更新进度并上传现场照片业主可以对每个节点确认或提出整改意见。所有操作都有记录状态可查询责任边界清清楚楚。1.2 系统里的角色和权限边界项目采用典型的 RBAC 模型内置了四类角色业主查看自己的订单进度、确认设计方案、节点验收、在线评价设计师接收分配的设计任务、上传设计图纸、提交材料清单和预算施工管理员创建施工计划、更新各节点进度、上传工地照片、登记材料进场系统管理员用户管理、订单分配、全部流程监控、基础数据维护这四类角色对应到前端就是四种不同的操作界面。权限控得不严的话业主能打开施工管理页面设计师能改别人的订单那这套系统反而会制造混乱。所以我特别关注了项目里的权限设计后面会详细拆解。1.3 一个典型的业务闭环是什么样以最常见的“新房装修”为例跑一遍主流程业主注册账号填写房屋信息、面积、风格偏好、预算区间提交装修申请。管理员在后台看到新申请审核通过后分配给某个设计师。设计师上传量房图和设计方案录入主材清单和预算报价。业主在线查看方案满意则确认不满意可填写修改意见退回。方案确认后施工管理员创建施工计划按“拆改-水电-瓦工-木工-油漆-安装-保洁”节点逐步推进。每个节点开始时更新状态完工后上传照片业主确认后进入下一节点。全部节点完成后业主做竣工确认和评价。这套流程里状态的每一步流转都有据可查。系统管理的核心不是“记录信息”而是“驱动流程”。2. 技术选型拆解为什么偏偏是 SpringBoot Vue MySQL2.1 后端选 SpringBoot图的是生态成熟和上手快这个项目没有引入微服务、没有用 Spring Cloud后端就一个 SpringBoot 应用打包后是一个可直接运行的 JAR。我当时看代码第一感觉是选型很务实。SpringBoot 在这个场景下的优势有几个自动配置省掉了大量 XML 配置内嵌 Tomcat 让部署变成一条命令Spring Security 整合 JWT 做认证授权是标准方案生态里 MyBatis-Plus 这类增强工具又能把单表 CRUD 的效率拉满。对于一个需要快速交付、稳定运行的装修管理后台来说这属于“稳赚不赔”的组合。要注意的是 SpringBoot 版本。项目用的是 2.x 系列对应 JDK 8。如果你本地装的是 JDK 17 甚至 21跑 2.x 老项目大概率会遇到依赖兼容问题。实际启动时我先检查了pom.xml里的 SpringBoot 版本再决定用哪个 JDK。如果是 SpringBoot 3.x要求 JDK 17 起步。这两者的切换不算复杂但很容易在一开始就把新人卡住。2.2 前端选 Vue核心是组件化和生态前端用的是 Vue 2 Element UI。如果按现在的时间点看Vue 3 才是新项目的默认选择但很多现成源码和公司内部系统仍然跑在 Vue 2 上。这套系统选 Vue 2 并不奇怪Element UI 对应的管理后台组件丰富表格、表单、弹窗、分页这些后台高频组件都是现成的改改配置就能用不需要从零手写。Vue 的核心价值在组件化一个装修订单的进度时间线、一个材料清单表格、一个权限控制按钮都可以抽成独立组件。项目里的 src/views 下按角色分目录比如 owner、designer、admin、constructor每个页面维护自己那块业务代码不会乱成一锅粥。前端请求用 Axios全局做了拦截器请求头自动带 token响应里遇到 401 就跳登录页。状态管理用的 Vuex登录用户信息、权限列表这类全局数据放在 store 里刷新页面后通过本地缓存恢复。这套模式在后台管理系统里属于标配稳定。2.3 数据库选 MySQL业务数据量决定了没必要上重武器装修管理系统的数据量级撑死也就是几百个并发用户、几十万条订单记录MySQL 完全扛得住。项目里 SQL 用得很规矩核心表都建了索引订单表关联查询基本走主键和业务外键不会有性能瓶颈。连接层用的是 MyBatis-Plus这个选择很聪明。MyBatis-Plus 在我眼里是一个“写了等于没写”的 ORM单表查询直接用selectById、selectPage这些封装好的方法复杂的多表关联再手写 XML。项目里的用户管理、材料管理这些模块几乎全是单表 CRUD用 MyBatis-Plus 能省掉大量重复的 Mapper XML。2.4 为什么没有引入 Redis 和消息队列也有人会问都做管理系统了为什么不加 Redis 做缓存用 RabbitMQ 做消息推送。我的看法是要分场景。这个项目核心操作是状态流转和记录查询数据库压力不大Redis 缓存带来的收益有限反而引入额外组件会提高部署门槛。消息推送方面项目先用招聘轮询或简单的待办提醒就能满足不需要引入一套消息中间件。“可直接运行”的关键就是依赖越少越好你来一个 Redis用户还得先装 Redis那就不叫直接运行了。3. 数据建模思路从 8 张核心表看懂装修业务3.1 用户权限表三个基础表撑起 RBAC打开数据库脚本最先看到的是sys_user、sys_role、sys_user_role三张表。sys_user存的是用户基本信息包含用户名、密码BCrypt 加密后的密文、真实姓名、手机号、状态字段。密码绝不能用明文存储这一点项目做得没问题。sys_role表里预置了owner、designer、constructor、admin四种角色。sys_user_role是关联表一个用户可以有多个角色虽然这个项目里每个用户理论上是单一角色但多对多的结构保留了扩展性。将来如果出现“设计施工一体”这种复合角色不需要改表结构。权限控制不是简单判断角色名而是通过角色关联菜单和按钮权限。不过在这个项目里接口层主要用角色做粗粒度控制细粒度到按钮级别在前端通过v-permission指令实现后端接口同样会做二次校验。防止有人绕过前端直接调接口。3.2 业务主表装修订单表的是一切的源头核心业务表是decorate_order它几乎集中了业务全流程的所有关键字段业主 ID关联 sys_user表明这单是谁的房屋信息所在小区、楼栋、户型、面积装修需求风格偏好、预算区间、期望开工日期状态字段待分配、设计确认、施工中、待验收、已完成、已取消设计师 ID、施工管理员 ID分配给哪个设计师哪个工长负责创建时间、更新时间这张表的设计逻辑很清楚所有业务动作都围绕订单展开先有订单才能有后续的设计、施工、进度记录。状态字段用varchar存英文枚举值比如PENDING,DESIGN_CONFIRMED,UNDER_CONSTRUCTION,COMPLETED比存中文更规范也方便后端枚举类判断。3.3 子业务表设计、材料、进度分工明确design_plan表存设计方案核心字段是订单 ID、方案名称、设计说明、图纸附件 URL、预算总金额、状态待确认/已确认/已退回。图纸不是直接存进数据库而是存文件的访问路径。这个项目把上传文件保存在本机磁盘目录数据库只记录路径。如果将来要上云换成 OSS 对象存储只需要改文件上传的工具类表结构不用动。material_info表存主材清单字段包括材料名称、规格型号、单位、数量、单价、总价、品牌、采购状态。它和设计关联也可以独立维护。这个表最容易被忽略的一点是“数量和单价分开存”而不是直接存一个总价。这样万一价格调整只需要改单价数量不变总价自动重算。如果设计时偷懒只存总价后面统计和变更会很痛苦。construction_progress表是整个系统里最直观的部分。每条记录包含订单 ID、节点名称如“水电改造”、计划开始日期、计划完成日期、实际开始日期、实际完成日期、进度状态、施工说明、现场照片 URL。查询某个订单的进度时按节点序号排序返回前端渲染成时间线。这里有个细节状态不是简单的“完成/未完成”而是细分了“待开始、进行中、待业主确认、已完成”。业主确认之后才推进到下一节点这就是流程管控的意义。3.4 数据字典与状态流转设计项目里用一张sys_dict表维护数据字典比如房屋类型、风格枚举、节点名称、材料分类。数据字典的好处是页面上要加一个选项不用改代码和表结构往字典表插一条记录就行。状态流转是这类系统的核心逻辑。以装修订单为例待分配 → 设计确认 → 施工中 → 待验收 → 已完成设计确认阶段可以退回到待分配施工过程中任何节点被业主否决订单不会回退到初始状态只是当前节点状态变为“需整改”状态流最好在后端用枚举类做统一约束而不是在前端随意跳转。这个项目的 Controller 层有多个状态判断Service 层也有相应的校验。我实际测试过如果前端绕过按钮直接用 POST 请求把订单状态改成已完成后端会返回“状态流转非法”的错误安全防护是真实的。4. 后端接口与权限设计JWT 登录和 RBAC 到底怎么落地4.1 认证流程一次 POST 请求换一个 token系统登录接口是/api/auth/login请求体是用户名和密码。后端校验通过后用 JWT 生成一个 token 返回给前端。前端把 token 存在 localStorage之后每次请求在请求头里加Authorization: Bearer token。JWT 的核心是“无状态”服务器不保存会话信息用户身份就编码在 token 里。后端需要一个拦截器或过滤器在每次请求时解析 token验证签名取出用户 ID 和角色信息。Spring Security 里通过自定义OncePerRequestFilter实现把解析出的用户信息放到SecurityContextHolder里供后续使用。具体流程我也在本地断点跟过一遍JwtAuthenticationFilter先判断请求头有没有 token没有就直接放行让 Spring Security 的匿名过滤器处理有 token 则解析如果 token 有效则加载用户信息和权限列表然后构造UsernamePasswordAuthenticationToken放进上下文。这套逻辑是所有 Spring Security JWT 项目的标准范式可以用到其他任何后台系统上。4.2 接口权限方法级别注解控制角色访问在 Controller 层项目用PreAuthorize(hasAnyRole(ADMIN,DESIGNER))这类注解做接口权限控制。比如创建设计方案接口只允许设计师和管理员访问确认设计方案接口只允许业主和管理员访问更新施工进度接口只允许施工管理员和管理员访问。这里有一个很多新手容易踩的坑hasRole默认会对角色名自动加ROLE_前缀。如果数据库里角色标识是ADMIN注解里要写hasRole(ADMIN)但 Spring Security 在底层比较的是ROLE_ADMIN。如果配置权限时忘了这个前缀明明有权限也会返回 403。我翻了项目代码它在实现UserDetails时已经把角色名统一加了ROLE_前缀所以权限注解能正常工作。这个细节看似不起眼实际排查 403 时能让新手卡好几个小时。4.3 核心接口拆解设计确认和施工进度更新的逻辑以“业主确认设计方案”为例接口路径类似POST /api/design/{id}/confirm。后端逻辑分四步根据方案 ID 查方案判断方案是否存在。判断方案归属的订单是否属于当前登录业主。判断方案状态是否为“待确认”如果不是则抛业务异常。更新方案状态为“已确认”同时把关联订单状态从“设计确认”更新为“待施工”。从代码里能看出设计者把业务校验写得很克制没有把一堆 if 塞在 Controller 里而是抽了一个DesignPlanService处理核心逻辑Controller 只负责接收参数和返回统一响应。这就引出一个项目里很值得学习的点统一返回体ResultT包含 code、message、data 三个字段前端 Axios 响应拦截器里判断 code 是否为 200。这样一来后端无论返回正常数据还是业务异常整体结构都是一致的。施工进度更新的接口要考虑的东西更多。每次更新不仅是改一条进度记录还要校验当前施工节点是否轮到它。比如“瓦工”节点还没开始“油漆”节点不能直接标完成。代码里维护了一个节点顺序表用sort_order字段排序更新时检查前一个节点是否已完成。这种串行校验的写法值得记下来很多流程类系统的核心难点就在这。4.4 统一异常处理和参数校验项目里的全局异常处理使用RestControllerAdvice捕获三类异常业务异常自定义BusinessException、参数校验异常、系统级异常。返回格式统一是{code: 500, message: xxx, data: null}。前端拿到非 200 的 code 直接弹 message不需要逐个接口处理错误。参数校验用ValidatedNotBlank、NotNull这些注解DTO 字段上做声明式校验。比如创建订单时房屋面积必须大于 0手机号必须符合正则。这样做的好处是 Controller 层不会堆一堆手写的 if 判断代码一眼扫过去就知道哪些字段必填。5. Vue 前端怎么承接业务路由、状态管理和页面交互5.1 目录结构按业务角色分的 view不按组件类型分前端的src/views下不是常见的src/views/system、src/views/order这类按模块分而是按角色分。打开项目能看到owner、designer、constructor、admin四个目录。对于这个特定项目来说按角色分目录反而更清晰因为每个角色看到的页面集合差异很大不同角色之间几乎没有共用页面。公共组件放在src/components里比如订单状态标签、图片上传组件、进度时间线组件。公共 API 请求统一放在src/api下按业务模块拆文件比如order.js、design.js、progress.js。一个页面里不要直接写 axios统一走封装的request.js方便维护。5.2 路由守卫和动态侧边栏前端登录后根据用户角色动态生成可访问的菜单。这一步不是简单地在前端router.beforeEach里判断角色然后跳转而是后端登录接口返回用户信息时带上角色和菜单权限列表前端把菜单列表存到 Vuex动态渲染侧边栏。路由守卫的逻辑是判断本地有没有 token没有就跳转/login。有 token 但本地没有用户信息调/api/auth/info拉取用户详情和权限。根据权限判断当前路由是否可访问无权访问跳 403 页面。这里有个很容易忽略的问题刷新页面后 Vuex 数据会丢失所以用户信息必须同步持久化到 localStorage刷新后再从本地恢复而不是刷新后每次都重新登录。项目里在这块做了兼容刷新后先读 localStorage 恢复用户信息再发一次请求验证 token 是否有效。5.3 Vuex 状态管理里放了什么项目状态管理只放了三类全局数据用户信息、菜单权限、订单缓存。用户信息包括用户 ID、用户名、角色列表页面渲染时经常要判断当前角色决定显示哪些按钮。菜单权限决定了侧边栏的渲染结果。订单缓存主要用于业主端“我提交的订单”列表因为订单查询接口相对较重切换页面时不希望频繁重新请求。Vuex 的模块划分是标准的modules方式user.js、app.js、order.js每个模块有独立的 state、mutations、actions。典型用法是在 action 里调用 API拿到数据后 commit mutation 更新 state。这套写法虽然比直接ref定义一个响应式对象繁琐但胜在数据变更可追踪适合管理后台这种需要多人协作维护的项目。5.4 关键页面交互怎么实现的业主端最重要的页面是“装修进度详情页”。页面顶部是订单基本信息卡片中间是步骤条展示整个装修生命周期提交申请、设计确认、施工中、竣工验收。下面是大时间线每个施工节点对应一条记录包含节点名称、计划时间、实际时间、施工说明、现场照片。时间线组件通过v-for循环渲染construction_progress列表根据状态打上不同颜色的标签。设计师端最核心的页面是“上传设计方案”。表单里除了填写方案名称和设计说明还要上传图纸文件。项目里的上传组件封装了el-upload批量上传后把返回的文件 URL 拼成数组提交表单时一并传给后端。具体到el-upload的坑是它默认用 AJAX 上传需要设置action属性为后端接口同时通过headers带上 token。如果不带 token上传接口会被 401 拦截但提示很隐晦经常让人以为是文件格式问题。管理员端最亮眼的是首页的统计看板用 ECharts 展示本月新增订单数、各状态订单分布、各设计师在手订单数。这些数据来自后端的/api/dashboard/stats聚合接口一次请求返回多个统计数据前端拆开渲染。这种一个页面只要一个接口的做法能减少请求次数也方便维护。5.5 前端样式复用和自定义主题Element UI 自带一套蓝色主题项目里用 SCSS 变量覆盖了主色改成偏绿色的装修行业风格。这个改动在styles/variables.scss里改$--color-primary即可。如果你拿到源码想换品牌色这是最快的方式不用去每个组件里调样式。6. “可直接运行”背后的启动流程和踩坑实录6.1 本地跑起来需要准备什么我把“可直接运行”理解为代码下载后只要你的电脑装了 JDK、Maven、Node.js、MySQL按文档步骤操作就能跑。实际启动需要的环境是工具版本建议用途JDK1.8 或 11编译运行 SpringBoot 后端Maven3.6管理后端依赖Node.js14.x 或 16.x编译运行 Vue 前端MySQL5.7 或 8.0存储业务数据IDEIntelliJ IDEA / VS Code导入和调试代码后端项目是标准的 Maven 结构pom.xml集中在根目录直接用 IDEA 打开等待依赖下载完成就行。前端是独立的vue目录需要单独npm install。6.2 数据库初始化的正确姿势项目根目录一般会带sql文件夹里面是init.sql或decoration.sql。这个初始化脚本建库建表同时插入初始管理员账号和字典数据。我在 MySQL 8.0 里执行时遇到一个坑脚本里如果有中文注释或数据需要保证 MySQL 客户端的字符集是 utf8mb4否则中文内容会变成乱码。推荐用命令行执行mysql -u root -p sql/init.sql如果 MySQL 8.0 默认认证插件是caching_sha2_password而项目里数据库驱动是mysql-connector-java5.x 版本连接时会报Unable to load authentication plugin caching_sha2_password。解决办法有两个一是换用 8.x 的驱动二是把数据库用户改成mysql_native_password。项目里如果用的是 MySQL 5.7则不会有这个问题。6.3 后端配置修改的三个地方打开application.yml重点看三块配置server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/decoration?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: root redis: # 项目未强制依赖 Redis这里的配置一般可忽略第一是端口号默认 8080如果被占用要改。第二是数据库连接地址必须改成你本地 MySQL 的账号密码。第三是时区MySQL 8.0 驱动要求带serverTimezone否则会报时区错误。这里有个典型的启动报错The server time zone value Öйú±ê׼ʱ¼ä is unrecognized看到这个基本就是缺少 serverTimezone 参数。JWT 密钥一般在application.yml里的自定义配置段比如jwt.secret。默认值是一个随机字符串生产环境必须改掉否则 token 可以被逆向伪造。这个项目里把密钥直接写在配置文件中开发没问题上生产前一定要改成环境变量注入。6.4 前端启动步骤和跨域处理前端启动流程cd vue npm install npm run dev默认开发服务器跑在http://localhost:9528通过 Vite 或 Webpack 的代理把/api转发到后端 8080。代理在vue.config.js里配置module.exports { devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } };如果不用代理直接用 axios 调http://localhost:8080/api会因为跨域被浏览器拦截就算后端配置了CrossOrigin一开始也会踩坑。所以我建议开发环境始终走代理前端代码里用相对路径/api这样部署时只要把前端的/api请求反向代理到后端服务即可。6.5 我实际遇到的几个报错和排查思路报错一Port 8080 was already in use.后端启动失败原因是 8080 被占用。排查步骤netstat -ano | findstr 8080查看 PID如果是无用进程直接杀掉或者改application.yml里的端口号同时记得同步修改前端代理目标地址。报错二java.sql.SQLException: Access denied for user rootlocalhost数据库账号密码不对不是代码问题。检查application.yml里的 username 和 password 是否和本地 MySQL 一致。新人最容易在这里卡住因为默认密码可能不是 root。报错三npm ERR! code ELIFECYCLE前端启动失败通常不是 because 代码问题而是 Node.js 版本太高项目依赖里某个包编译不过。Vue 2 Element UI 的老项目Node 14/16 最稳。我用 Node 18 试过node-sass编译报错后来卸载重装 Node 16 就好了。如果你不想切 Node 版本可以考虑把node-sass换成sass不过这会牵扯到兼容性调整不推荐新手折腾。报错四请求接口 404如果登录页能出来但登录请求 404先确认后端是否启动成功再看前端代理是否生效。打开浏览器开发者工具看网络请求实际访问的 URL。如果请求地址是http://localhost:8080/api/auth/login说明代理没起效如果是http://localhost:9528/api/auth/login且代理配置正确那就是代理转发问题。7. 从“能跑”到“好用”这套源码的扩展空间和个人体会7.1 消息通知和工作流可以补上当前项目在“待办提醒”上只做了站内消息表没有前台主动推送。实际运营中设计师提交方案后业主并不知道必须自己点进去看。这里有两个轻量改进思路一是前端加一个定时轮询每 30 秒调一次消息接口二是引入 WebSocket后端在状态变更时主动推送。不用上消息队列单机 WebSocket 完全够用。如果订单量再大再考虑引入 Redis 发布订阅。7.2 文件存储本地化终究是过渡方案项目里的图纸和工地照片存在本机磁盘这在单机部署下没问题但多台服务器或容器化部署时文件就不同步了。建议改成 OSS/MinIO 的对象存储后端封装一个FileStorageService接口本地实现和 OSS 实现切换即可。数据库里已经存的是 URL 路径换存储方案不影响前端页面。7.3 订单状态机值得独立成一个模块当前状态流转分散在 Service 里虽然逻辑正确但状态越来越多时不好维护。更优雅的做法是用状态机模式定义每个状态允许的事件和下一个状态。比如“施工中”状态下只有所有子节点都已完成才能触发“待验收”。这样把校验规则集中到一处加新状态时不会影响原有流程。7.4 关于这套源码本身我的结论是我见过太多号称“可直接运行”的项目实际下载后要么缺配置文件要么依赖版本不兼容要么数据库脚本缺失。这套装修管理系统在完整性上做得很到位数据库脚本、后端配置、前端代理、默认账号一应俱全只要环境匹配从下载到看到登录页大约只需要半小时。对于正在做毕业设计、想快速搭一套后台管理系统、或者准备接装修行业软件外包的人来说它的参考价值都不低。项目里最有学习价值的部分不是页面多炫而是“状态流转”和“权限控制”这两个点。看懂了订单状态怎么一步步推进你就理解了大部分业务系统是怎么把现实流程搬到线上的。如果想拿这套代码作为基础二次开发建议先花一天时间把每张表的字段过一遍再从前端一个页面点击后追踪到后端接口和数据表的完整链路。把这条链路跑通这个项目你就真正吃透了。
返回列表