温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片!
1. 项目背景与意义
随着人们生活水平的不断提高,家庭装修已成为越来越多家庭关注的重点。传统的家装模式往往依赖线下门店和设计师面对面沟通,存在信息不透明、沟通效率低、方案展示不直观等问题。基于 SpringBoot + Vue3 的家装设计网站,旨在通过互联网技术打通业主、设计师与装修公司之间的信息壁垒,提供在线方案展示、预约沟通、案例浏览等一站式服务,提升家装行业的数字化服务水平。
本系统采用前后端分离架构,后端基于 SpringBoot 提供稳定可靠的 RESTful API,前端基于 Vue3 构建响应式交互界面,既保证了系统的可维护性和扩展性,也为用户带来流畅的使用体验。
2. 系统需求分析
2.1 功能需求
本系统面向三类核心用户角色,分别为普通用户(业主)、设计师和管理员,各角色的功能需求如下:
- 普通用户:注册登录、浏览装修案例、查看设计师信息、在线预约设计、收藏喜欢的案例、个人中心管理。
- 设计师:登录系统、发布和管理装修案例、维护个人资料、查看预约信息、与业主在线沟通。
- 管理员:用户管理、设计师审核、案例审核与下架、预约管理、系统数据统计。
2.2 非功能需求
- 性能:页面响应时间不超过 2 秒,支持并发访问。
- 安全:用户密码加密存储,接口权限校验,防止 SQL 注入和 XSS 攻击。
- 可维护性:代码结构清晰,模块化设计,便于后续功能扩展。
- 兼容性:支持主流浏览器,适配 PC 端和移动端。
3. 系统架构设计
3.1 技术选型
本系统采用前后端分离架构,具体技术栈如下:
| 层次 | 技术选型 | 说明 |
|---|---|---|
| 前端框架 | Vue3 + Element Plus | 组件化开发,UI 美观 |
| 前端构建 | Vite | 开发热更新,构建速度快 |
| 状态管理 | Pinia | 轻量级状态管理方案 |
| 路由管理 | Vue Router | 前端页面路由控制 |
| 后端框架 | SpringBoot | 快速构建 RESTful 服务 |
| 持久层 | MyBatis-Plus | 简化数据库操作 |
| 数据库 | MySQL 8.0 | 存储业务数据 |
| 权限认证 | JWT + Spring Security | 无状态认证,安全可靠 |
3.2 系统架构图
系统整体架构分为表现层、业务层和数据层三个层次,前端通过 HTTP 请求与后端 API 交互,后端通过 MyBatis-Plus 操作 MySQL 数据库,整体架构清晰、职责分明。
flowchart TD A[Vue3 前端] -->|HTTP/RESTful| B[SpringBoot 后端] B --> C[业务逻辑层 Service] C --> D[数据访问层 Mapper] D --> E[(MySQL 数据库)] B --> F[JWT 认证与权限控制] A --> G[Element Plus 组件库]4. 数据库设计
4.1 核心数据表
根据系统功能需求,设计以下核心数据表:
| 表名 | 说明 | 主要字段 |
|---|---|---|
| user | 用户表 | id、username、password、phone、avatar、role、create_time |
| designer | 设计师表 | id、user_id、real_name、intro、style、experience、status |
| case_info | 装修案例表 | id、designer_id、title、cover、description、area、style、price、status |
| appointment | 预约表 | id、user_id、designer_id、case_id、appoint_time、content、status |
| favorite | 收藏表 | id、user_id、case_id、create_time |
4.2 表关系说明
用户表与设计师表为一对一关系,一个用户对应一个设计师档案;设计师与案例表为一对多关系,一个设计师可发布多个案例;用户与案例通过收藏表建立多对多关系;预约表关联用户、设计师和案例三张表,记录预约信息。
5. 后端核心功能实现
5.1 项目结构
SpringBoot 后端采用分层架构,包结构如下:
com.example.decoration ├── controller // 控制层,接收前端请求 ├── service // 业务逻辑层 ├── mapper // 数据访问层 ├── entity // 实体类 ├── dto // 数据传输对象 ├── config // 配置类(安全、跨域等) ├── utils // 工具类(JWT、统一返回等) └── common // 通用类(异常处理、结果封装)5.2 统一返回结果封装
为了方便前端统一处理响应数据,定义通用返回结果类:
@Data public class Result<T> { private Integer code; private String message; private T data; public static <T> Result<T> success(T data) { Result<T> result = new Result<>(); result.setCode(200); result.setMessage("操作成功"); result.setData(data); return result; } public static <T> Result<T> error(String message) { Result<T> result = new Result<>(); result.setCode(500); result.setMessage(message); return result; } }5.3 案例查询接口实现
以装修案例列表查询为例,实现分页查询接口:
@RestController @RequestMapping("/api/case") public class CaseController { @Autowired private CaseService caseService; @GetMapping("/list") public Result<Page<CaseInfo>> getCaseList( @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) String style, @RequestParam(required = false) String area) { Page<CaseInfo> page = caseService.queryCaseList(pageNum, pageSize, style, area); return Result.success(page); } @GetMapping("/{id}") public Result<CaseInfo> getCaseDetail(@PathVariable Long id) { CaseInfo caseInfo = caseService.getById(id); return Result.success(caseInfo); } }5.4 JWT 认证实现
系统采用 JWT 实现无状态认证,登录成功后生成 Token 返回前端,前端在后续请求中携带 Token 访问受保护接口:
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Autowired private JwtUtils jwtUtils; @Override public Result<String> login(String username, String password) { User user = userMapper.selectByUsername(username); if (user == null || !password.equals(user.getPassword())) { return Result.error("用户名或密码错误"); } String token = jwtUtils.generateToken(user.getId(), user.getRole()); return Result.success(token); } }6. 前端核心功能实现
6.1 项目初始化
使用 Vite 创建 Vue3 项目,并安装 Element Plus、Pinia、Vue Router 和 Axios 等依赖:
npm create vite@latest decoration-web -- --template vue cd decoration-web npm install element-plus @element-plus/icons-vue pinia vue-router axios6.2 前端路由配置
在 router 目录下配置页面路由,实现页面跳转和权限控制:
import { createRouter, createWebHistory } from 'vue-router' const routes = [ { path: '/', name: 'Home', component: () => import('@/views/Home.vue') }, { path: '/cases', name: 'CaseList', component: () => import('@/views/CaseList.vue') }, { path: '/case/:id', name: 'CaseDetail', component: () => import('@/views/CaseDetail.vue') }, { path: '/designers', name: 'DesignerList', component: () => import('@/views/DesignerList.vue') }, { path: '/login', name: 'Login', component: () => import('@/views/Login.vue') }, { path: '/register', name: 'Register', component: () => import('@/views/Register.vue') }, { path: '/profile', name: 'Profile', component: () => import('@/views/Profile.vue'), meta: { requiresAuth: true } } ] const router = createRouter({ history: createWebHistory(), routes }) export default router6.3 Axios 请求封装
封装 Axios 实例,统一处理请求拦截和响应拦截,自动携带 Token 并处理错误状态:
import axios from 'axios' import { ElMessage } from 'element-plus' import { useUserStore } from '@/stores/user' const request = axios.create({ baseURL: '/api', timeout: 10000 }) request.interceptors.request.use(config => { const userStore = useUserStore() if (userStore.token) { config.headers.Authorization = `Bearer ${userStore.token}` } return config }) request.interceptors.response.use( response => { const res = response.data if (res.code !== 200) { ElMessage.error(res.message) return Promise.reject(new Error(res.message)) } return res }, error => { ElMessage.error('网络请求异常') return Promise.reject(error) } ) export default request6.4 案例列表页面实现
使用 Element Plus 组件实现案例列表展示,支持按风格和面积筛选:
<template> <div class="case-list"> <el-form inline> <el-form-item label="装修风格"> <el-select v-model="query.style" placeholder="全部风格"> <el-option label="现代简约" value="现代简约" /> <el-option label="北欧风" value="北欧风" /> <el-option label="新中式" value="新中式" /> <el-option label="轻奢风" value="轻奢风" /> </el-select> </el-form-item> <el-form-item> <el-button type="primary" @click="loadCases">查询</el-button> </el-form-item> </el-form> <el-row :gutter="20"> <el-col :span="8" v-for="item in caseList" :key="item.id"> <el-card class="case-card" @click="goDetail(item.id)"> <img :src="item.cover" class="case-cover" alt="案例封面" /> <h3>{{ item.title }}</h3> <p>{{ item.style }} · {{ item.area }}㎡ · ¥{{ item.price }}</p> </el-card> </el-col> </el-row> <el-pagination v-model:current-page="query.pageNum" :page-size="query.pageSize" :total="total" @current-change="loadCases" /> </div> </template> <script setup> import { ref, reactive, onMounted } from 'vue' import { useRouter } from 'vue-router' import request from '@/utils/request' const router = useRouter() const caseList = ref([]) const total = ref(0) const query = reactive({ pageNum: 1, pageSize: 9, style: '' }) const loadCases = async () => { const res = await request.get('/case/list', { params: query }) caseList.value = res.data.records total.value = res.data.total } const goDetail = (id) => { router.push(`/case/${id}`) } onMounted(loadCases) </script>7. 系统测试
7.1 测试环境
系统测试在本地开发环境进行,后端运行于 8080 端口,前端运行于 5173 端口,数据库使用 MySQL 8.0,测试数据包含 10 个设计师账号和 50 条案例数据。
7.2 功能测试
对系统核心功能进行测试,主要测试用例和结果如下:
| 测试模块 | 测试用例 | 预期结果 | 实际结果 |
|---|---|---|---|
| 用户注册 | 填写注册信息并提交 | 注册成功并跳转登录页 | 通过 |
| 用户登录 | 输入正确账号密码 | 登录成功并跳转首页 | 通过 |
| 案例查询 | 按风格筛选案例 | 返回对应风格案例列表 | 通过 |
| 案例详情 | 点击案例卡片 | 展示案例完整信息 | 通过 |
| 在线预约 | 填写预约信息提交 | 预约成功并提示 | 通过 |
| 收藏功能 | 点击收藏按钮 | 收藏成功并更新状态 | 通过 |
7.3 性能测试
使用 JMeter 对案例列表接口进行并发测试,在 100 个并发用户请求下,接口平均响应时间为 380 毫秒,吞吐量为每秒 260 个请求,系统性能满足设计要求。
8. 总结与展望
本文基于 SpringBoot + Vue3 设计并实现了一个家装设计网站系统,完成了用户管理、案例展示、设计师信息、在线预约和收藏等核心功能。系统采用前后端分离架构,后端提供稳定的 RESTful API,前端使用 Vue3 构建了良好的用户交互界面,整体实现了预期的功能目标。
在后续的迭代中,系统可以从以下几个方面进行优化和扩展:一是引入在线 3D 效果图展示,提升案例展示的沉浸感;二是增加设计师与业主的实时在线沟通功能,提高沟通效率;三是引入智能推荐算法,根据用户浏览行为推荐个性化装修案例;四是完善移动端适配,提供更好的移动端使用体验。