ARTICLE DETAIL

资讯详情

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

基于SSM与微信小程序的宿舍报修系统设计与实战解析

基于SSM与微信小程序的宿舍报修系统设计与实战解析 简介这是基于微信小程序设计的宿舍报修系统毕业源码案例后端采用SSM架构Java语言编码Mysql创建数据表面向计算机相关专业学生及小程序开发者可用于毕业设计、课程实践或项目参考。压缩包共664个文件大小约36MB类型覆盖java后端逻辑、vue页面、小程序wxml/wxss/js界面、SQL数据库脚本及mp4演示视频另有bat一键安装脚本、png/svg图标、json/css等配置样式文件整体目录清晰便于按模块查阅和代码定位。当前已有391人学习下载可作为项目实战参考。资源提供完整前后端代码和数据库初始化数据从学生报修端到管理员处理端均有对应实现覆盖报修提交、进度跟踪、后台派单、信息统计等典型功能搭配演示视频可直观了解运行效果适合需要快速上手SSM与微信小程序整合开发的学习者。 做宿舍报修系统这个选题编号是 weixin183后端走 SSMSpring SpringMVC MyBatis前端是微信小程序。乍一看和普通管理系统没什么区别但真正动手后发现这个小项目几乎把毕业设计常见的坑都踩了一遍小程序登录、接口设计、OpenId 获取、图片上传、状态流转、部署上线。今天把这套系统的完整设计思路、核心代码逻辑和排错经验整理出来给正在做同类课题、或者想用 SSM 做后端接口练手的同学一个可以直接复现的参考。这套系统能解决什么问题很简单学生不用再跑到宿管办公室填纸质报修单直接在微信小程序里拍照、描述问题、提交维修进度随时可查宿管和维修工通过后台管理页面分配工单、更新状态最后学生还能对维修结果评价。对毕设来说它包含了完整的用户体系、业务流、权限和状态流转复杂度刚好不会让人觉得水又不会做到一半失控。1. 项目整体设计思路先想清楚要做成什么形态1.1 需求端到端拆解谁在用每个角色关心什么做任何系统前先把角色和诉求列清楚。宿舍报修系统里我最后划出了三类角色学生、维修工、管理员宿管。学生侧的诉求很直观提交报修时最好 30 秒内搞定不用填一堆字段提交后能看进度知道师傅到底接没接单、修完没有。维修工侧关心的是手头还有多少单、单子在哪栋楼哪个房间、问题描述是否清晰。管理员则要处理派单、监督维修时效、抽查学生评价。所以功能模块我拆成了学生端个人信息维护、报修单提交选宿舍、选问题分类、填描述、上传图片、报修进度查询、待评价列表、历史记录。维修工端待接单列表、接单/完成操作、查看报修详情。管理后台用户管理、维修工分配、报修单审核与派单、统计报表。这个拆分本身就是给数据库和接口设计打底。很多同学一上来就写代码写到一半发现字段缺了或者接口对不上根子就在需求没有拆够细。1.2 技术选型为什么是 SSM 微信小程序后端选 SSM说实话不是因为它最新而是因为它在毕业设计语境里足够“标准”Spring 管对象和事务SpringMVC 负责接收前端请求MyBatis 操作数据库。这套组合分层清晰写起来比 Spring Boot 更能理解请求从进入控制器到数据库再返回 JSON 的完整链路。很多同学问过“接口是啥”用这个项目举例最合适。接口就相当于后端对外提供的一个 URL小程序通过 HTTP 请求这个地址带上参数后端处理完返回 JSON 数据。比如小程序提交报修单就是 POST /api/repair/add请求体里带上 dormId、description、imageUrl后端返回{code: 200, msg: 提交成功, data: null}。前端拿到这个 JSON 再做页面跳转或提示。项目中我统一定义了 Result 对象保证所有接口都返回一致结构调试起来非常省事。小程序端选择原生框架而不是 uniapp 或 Taro主要是为了降低调试成本。原生框架里调试登录、上传文件、订阅消息都直接用微信开发者工具就能搞定不需要额外编译链路。对毕设来说稳定跑通比炫技更重要。2. 数据库设计一张报修单是怎么“活”起来的2.1 核心表结构与字段设计我数据库用的 MySQL 5.7建了 6 张核心表用户表、维修工表、报修分类表、报修单表、报修进度日志表、评价表。下面这张是报修单表的核心字段也是整条业务流的主干。CREATE TABLE repair_order ( id int(11) NOT NULL AUTO_INCREMENT, order_no varchar(32) NOT NULL COMMENT 报修单号, student_id int(11) NOT NULL COMMENT 学生用户ID, worker_id int(11) DEFAULT NULL COMMENT 维修工ID, type_id int(11) NOT NULL COMMENT 报修分类ID, dorm_building varchar(20) NOT NULL COMMENT 宿舍楼, dorm_room varchar(20) NOT NULL COMMENT 宿舍门牌, description text NOT NULL COMMENT 问题描述, image_url varchar(255) DEFAULT NULL COMMENT 现场图片, status tinyint(4) NOT NULL DEFAULT 0 COMMENT 0待受理 1已派单 2维修中 3已完成 4已评价 -1已取消, create_time datetime NOT NULL, update_time datetime NOT NULL, PRIMARY KEY (id), KEY idx_student (student_id), KEY idx_worker (worker_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字段设计时有几个细节值得说。第一订单号不能用自增 ID 暴露给用户容易被人遍历抓数据我用时间戳加随机数生成order_no。第二学生姓名、手机号不要冗余在报修单里通过student_id关联用户表去查避免用户改手机号后历史单子出现旧数据。第三status用数字枚举而不是字符串省空间、查询快Java 枚举和前端展示时再映射成中文。2.2 状态机设计报修单生命周期状态流转是这类业务系统最容易写乱的地方。如果不在数据库和接口层统一约定学生端、维修工端、管理后台各维护一套状态判断最后一定出 bug。我用一个枚举类把状态定义清楚待受理(0) - 已派单(1) - 维修中(2) - 已完成(3) - 已评价(4) | | | v v v 已取消(-1) 已取消(-1) 已取消(-1)规定只有待受理和已派单状态下的单子可以取消维修中之后不能再取消。这个约束后端接口里要校验不能只靠前端按钮隐藏。写接口时我习惯把所有允许的状态转换放在一张 Map 里每次更新先判断当前状态是否允许跳到目标状态不合法直接返回错误码状态不允许变更。这个方法比到处写 if-else 清晰很多。进度日志表也是容易被忽略的设计。修改状态时同时插入一条日志记录操作人、操作时间、从什么状态变成什么状态。哪怕系统上线后不需要毕设答辩时也能展示你对业务完整性的考虑。学生端“进度查询”直接查日志表按时间倒序返回即可。3. 后端 SSM 核心实现从登录鉴权到报修接口3.1 微信登录与 token 鉴权含踩坑小程序端登录流程有三步前端调用wx.login()拿到临时 code传到后端后端拿着 code 到微信接口换 openid后端生成自定义 token 返回给前端前端存储 token 并在后续请求中带上。后端代码简化后大概是public String wxLogin(String code) { // 1. 用 code 换取 openid String url https://api.weixin.qq.com/sns/jscode2session?appid appid secret secret js_code code grant_typeauthorization_code; String result restTemplate.getForObject(url, String.class); JSONObject json JSONObject.parseObject(result); String openid json.getString(openid); // 2. 根据 openid 查用户不存在则注册 User user userMapper.findByOpenid(openid); if (user null) { user new User(); user.setOpenid(openid); // 默认角色为学生 user.setRole(1); userMapper.insert(user); } // 3. 生成 token 并存储到 redis这里用项目里简单的 token 表 String token UUID.randomUUID().toString().replace(-, ); tokenMapper.save(user.getId(), token); return token; }这个环节踩过的坑主要有三个。第一小程序的 appid 和 secret 不要写在前端代码里凡是需要 secret 的操作一律放后端不然别人反编译代码就能拿你的 secret 调接口。第二wx.login返回的 code 只能使用一次并且有效期通常只有 5 分钟后端处理完要及时调用 code2session不能把 code 存库后异步处理。第三是内容安全相关获取 openid 是登录的基础但登录后不能把所有接口都裸露即使小程序没有传统 Cookie 概念也要用自定义 token 做拦截器校验。我自定义了LoginInterceptor实现 SpringMVC 的HandlerInterceptor在preHandle里读取请求头Authorization从 token 表查用户查不到直接返回 401。配置拦截时注意排除登录接口/api/user/login否则会把登录请求也拦掉。3.2 报修业务接口与统一返回格式接口设计我遵循一个原则登录接口用小程序 code 换 token业务接口统一走 JSON文件上传单独走wx.uploadFile。这样做前后端联调时不用纠结参数格式混用的问题。以新增报修单为例控制层代码RestController RequestMapping(/api/repair) public class RepairOrderController { Autowired private RepairOrderService repairOrderService; PostMapping(/add) public Result add(RequestBody RepairCreateRequest request, RequestAttribute(userId) Integer userId) { if (request.getTypeId() null || StringUtils.isEmpty(request.getDormRoom()) || StringUtils.isEmpty(request.getDescription())) { return Result.error(必填项不能为空); } Long orderId repairOrderService.addOrder(userId, request); return Result.success(orderId); } }所有接口返回统一Result { code, msg, data }。201 表示业务成功500 表示系统异常401 表示登录失效业务参数错误用业务码 1001、1002 等。这样做的好处是前端可以统一封装request方法通过code判断成败不用为每个接口写异常处理。Service 层处理业务时要注意事务。一个完整的报修单创建涉及生成单号、插入报修单、写入进度日志三个操作必须加上Transactional否则中途报错会出现只有日志没有单子的情况。这是很多同学容易忽略的地方。3.3 MyBatis 与 SpringMVC 的配合要点SSM 项目最烦的一类问题就是 mapper 扫描不到、XML 里 SQL 写错、字段映射不对。我建议在项目结构上直接按 controller / service / mapper 分层applicationContext.xml 中配置好MapperScannerConfigurer扫描路径和 XML 资源路径保持一致。这个项目里我用注解方式实现 mapper 接口XML 放在 resources 下同名目录SQL 用动态标签写法例如where条件中根据分类和状态动态拼接方便后续扩展查询条件。SpringMVC 部分需要特意说一下子RestController与Controller的区别。如果用了Controller再配合ResponseBody返回的才是 JSON直接写RestController默认对象会走 JSON 序列化。这个项目统一用RestController控制层不再返回视图天然适合前后端分离的接口场景。数据库连接这块MySQL 8.0 和 5.7 的驱动配置不一样。我用的是 MySQL 5.7驱动类com.mysql.jdbc.Driver连接 URL 上加了characterEncodingutf8和useSSLfalse解决中文乱码和 SSL 警告。如果是 MySQL 8.0要换成com.mysql.cj.jdbc.Driver还要指定serverTimezoneAsia/Shanghai否则时间字段查询会报错。4. 微信小程序端登录、提交、进度展示落地4.1 新版用户信息获取方式不可跳过很多同学在网上搜到老版本代码用wx.getUserProfile或者button open-typegetUserInfo获取昵称头像2022 年之后这套基本拿不到真实数据了返回的要么是默认头像要么是灰色昵称“微信用户”。这个项目里我直接按 2023 年后的实现方案处理头像通过button open-typechooseAvatar让用户主动选择昵称通过input类型为nickname的输入框让用户填写保存时再调后端更新用户资料。小程序端获取登录状态的核心代码onLoad() { wx.login({ success: (res) { wx.request({ url: getApp().globalData.baseUrl /api/user/login, method: POST, data: { code: res.code }, success: (resp) { if (resp.data.code 200) { wx.setStorageSync(token, resp.data.data); } } }); } }); }这里有个常见报错很多同学会遇到小程序获取登录后的微信用户失败报错信息包含一串 wx 开头的数字。多数情况下不是登录接口本身的问题而是开发者工具中“不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书”这个选项没勾或者后端 session 接口返回延迟。排查顺序一般是先开后端日志看请求有没有进来再看 code 是否过期最后看网络请求里的完整返回信息。4.2 报修表单提交与图片上传报修表单我设计得尽量轻宿舍楼用 picker 选择、门牌号用 input、问题分类用 picker 绑定后台分类数据、描述用 textarea、图片用wx.chooseMedia选择后上传。图片处理有个容易踩的坑如果直接把图片转 base64 塞进 JSON请求体很容易超限所以图片必须单独通过wx.uploadFile上传。上传部分参考实现uploadImage(tempFilePath) { return new Promise((resolve, reject) { wx.uploadFile({ url: getApp().globalData.baseUrl /api/file/upload, filePath: tempFilePath, name: file, header: { Authorization: wx.getStorageSync(token) }, success: (res) { let data JSON.parse(res.data); if (data.code 200) { resolve(data.data); } else { reject(data.msg); } }, fail: reject }); }); }后端接收上传文件时注意两点一是限制单个文件大小比如 5MB避免有人传大图把内存打满二是把文件用 UUID 重命名后存储到指定目录不要把用户原始文件名直接当存储名否则会出现重名覆盖或中文文件名乱码问题。上传成功后保存一个相对路径到数据库访问时再拼上服务器地址。4.3 列表状态展示与下拉刷新学生提交报修后最关心的就是“现在什么状态了”。前端列表页我做成卡片式每个卡片显示单号、宿舍房间、状态标签、报修内容和时间。状态标签的颜色和文字通过一个映射函数统一处理const STATUS_MAP { 0: { text: 待受理, color: orange }, 1: { text: 已派单, color: blue }, 2: { text: 维修中, color: purple }, 3: { text: 已完成, color: green }, 4: { text: 已评价, color: gray }, -1: { text: 已取消, color: red } };这里要和后端状态枚举严格保持一致前后端各维护一份很容易出现错位。我实际开发时是在后端生成一个/api/repair/statusList接口前端启动时拉取一次状态映射而不是在前端硬编码避免改状态时两端不同步。列表页我加了enablePullDownRefresh也就是下拉刷新。学生提交完报修单后从详情页返回列表页也会在onShow生命周期里重新加载列表。微信小程序页面栈里onLoad只触发一次很多同学发现提交后回到列表页数据没更新就是因为只在onLoad里请求了数据。5. 本地部署与常见问题排查5.1 前后端分离部署步骤速查整个项目是前后端分离的后端是 Java Web 项目前端是微信小程序。本地联调我推荐这样操作后端启动在 8080 端口小程序开发者工具中把 baseUrl 指向局域网 IP 的 8080并且勾选“不校验合法域名”。这样调试速度快不需要每次改动都上传服务器。部署到生产环境时后端打包成 war 包放到 Tomcat 的 webapps 目录小程序端把运维域名配置成 HTTPS然后在微信公众平台后台把 request 合法域名加白名单。需要注意这个域名必须是备案过的并且要支持 HTTPS小程序里不能直接访问 http 地址。数据库导入也很关键。我项目里附带了一个db_sql文件导入前确认 MySQL 版本和字符集。如果导入时报“Unknown collation: utf8mb4_0900_ai_ci”说明你用的是 MySQL 5.7 但 SQL 文件是从 MySQL 8.0 导出的需要全局替换掉这个排序规则或者直接用 5.7 对应的utf8mb4_general_ci。5.2 高频报错与解决方案这个项目从开发到跑通我遇到频率最高的几个问题整理成了下面的表格基本覆盖了 SSM 后端 小程序的典型坑现象原因解决办法小程序请求一直 404后端路径不对或项目没部署先看后端控制台日志再用浏览器直接访问接口测试后端返回 401请求头没带 token 或 token 过期检查拦截器排除路径、前端 header 是否传了 Authorization登录时报“获取登录用户失败”code 已过期、secret 配置错误、域名不合法重新调 wx.login确认 appid 和 secret 与小程序一致数据库查询中文乱码数据库字符集不是 utf8mb4建库时指定DEFAULT CHARSETutf8mb4连接 URL 加 characterEncodingMyBatis 报 “Invalid bound statement”mapper 接口和 XML 没绑定XML 的 namespace 必须等于接口全限定名接口方法名要和 XML id 一致上传图片后无法访问文件保存路径和静态资源映射冲突SpringMVC 配置mvc:resources映射上传目录或用虚拟路径访问权限拦截器是新手特别容易踩的坑。如果拦截器写了excludePathPatterns(/api/user/login)但登录接口还是被拦大概率是路径模糊匹配写法有误比如写成了/api/user/*而实际请求是/api/user/login。SpringMVC 的路径匹配规则/*只匹配一层路径/**才匹配多级路径。这类小问题看后端日志比看前端报错更直接。6. 个人经验与可扩展方向整个系统做完我最大的体会是毕业设计不一定非要多高级的技术栈而是要把最基础的技术用完整、用规范。SSM 虽然已经是老框架但它能让你真正理解 Spring 注入、事务、MyBatis 映射这些原理。代码结构上我强烈建议给每个 service、mapper 都写清楚不要把所有逻辑堆在 controller 里否则后期改一个状态字段就要动三四个文件。这个项目还能继续扩展的方向有几个。第一引入 Spring Boot 版本把 XML 配置替换成注解和 yml技术栈向企业级靠拢。第二接微信订阅消息学生提交报修后管理员派单时通过 subscribeMessage 给用户推送进度通知体验会提升很多。第三加一个简单的数据可视化比如统计这周各楼栋报修数量、常用维修类型排行答辩时展示效果很加分。最后再分享一个小技巧后端接口统一打印请求耗时日志用 SpringMVC 拦截器实现。每次学生端反馈“小程序很卡”你不用猜是前端脚本慢还是后端慢看日志里每个接口的耗时就能定位。这个习惯放到任何项目里都适用。本文还有配套的精品资源点击获取
返回列表