☰
SSM+微信小程序设备报修系统实战指南
2026/10/9 12:54:59 网站建设 项目流程

简介:本资源是一套完整的高校Java毕业设计项目——基于SSM框架与微信小程序的设备故障报修管理系统,面向计算机专业本科生及课程设计学习者,解决校园或企业中设备报修流程不规范、响应滞后、信息难追溯等实际管理痛点。压缩包共1216个文件,涵盖117个核心Java后端代码、123个Vue前端组件、170个JS逻辑脚本、230个PNG界面截图、81个WXML/WXSS小程序页面样式文件,以及SQL数据库脚本、答辩论文、详细部署文档和MP4演示视频,整体大小46.16MB,结构清晰、模块完整,含后台管理+小程序双端源码。目前已有184人学习下载,项目已通过导师审核,答辩得分97分,在Windows 10/11环境实测可直接运行,配套2-run.bat等一键脚本与install部署说明,大幅降低环境配置门槛,特别适合毕设参考、课程实践与全栈能力训练。

1. 这不是又一个“SSM+小程序”套壳项目:它真能跑通设备报修闭环,从微信扫码报障到工程师接单派工全链路落地

你手头这份“Java毕业设计-基于SSM+微信小程序的设备故障报修管理系统”,不是网上泛滥的“登录注册+增删改查”教学Demo。它解决的是真实产线、高校实验室、物业维保场景里最头疼的问题:设备坏了没人及时知道,报修靠打电话/微信文字描述不清,维修进度像黑匣子,责任归属扯皮——而这个系统用微信小程序扫码触发报修 + SSM后端驱动工单流转 + MySQL记录全生命周期日志,把“谁在什么时间、在哪台设备、报了什么故障、谁接了单、修了多久、是否复验通过”全部串成一条可追溯、可统计、可考核的数据链。适合本科毕设答辩拿高分、小型企业快速上线试运行、或作为Java全栈开发能力的实操验证包。它不追求炫技的微服务或云原生,但每一步都踩在SSM生态最稳的路径上:Spring MVC做请求路由、Spring JDBC+MyBatis做数据持久、Spring事务管工单状态变更;小程序端不玩复杂状态管理,用原生WXML+JS+WXSS实现扫码定位、图片上传、实时消息推送。如果你正卡在“毕设选题没亮点”“Java后端和小程序怎么真正连起来”“数据库表怎么设计才不翻车”,这个压缩包里的源码+文档+视频,就是你能直接抄作业、改参数、换设备型号就能跑起来的最小可行闭环。


2. 搭建环境:从JDK8到微信开发者工具,避开版本错配导致的编译失败和调试失联

2.1 后端环境:SSM三件套的版本锚点与依赖冲突解法

这个项目基于JDK 8u202(必须!)+ Maven 3.6.3 + Tomcat 8.5.92构建。为什么不是JDK11或17?因为MyBatis 3.4.6(项目pom.xml中锁定的版本)对JDK9+的模块化支持不完善,强行升级会导致org.apache.ibatis.session.SqlSessionFactoryBuilder类加载失败;Tomcat 8.5.x是Spring 4.3.x(本项目Spring版本)官方兼容性测试最充分的容器,Tomcat 9+会因Servlet API 4.0变更引发FilterRegistrationBean初始化异常。
在pom.xml中,关键依赖版本已固化,切勿手动升级:

<properties> <spring.version>4.3.29.RELEASE</spring.version> <mybatis.version>3.4.6</mybatis.version> <mysql.connector.version>5.1.47</mysql.connector.version> </properties>

提示:若你本地Maven仓库已有高版本Spring,执行mvn clean install -U强制更新依赖,但需先删除本地.m2/repository/org/springframework下所有文件夹,否则旧jar残留会引发NoSuchMethodError。

2.2 小程序端:微信开发者工具必须用稳定版v1.02.2303020,禁用“调试基础库”

小程序源码基于微信基础库2.24.4开发。使用新版开发者工具(如v1.02.2312010)时,默认启用“调试基础库”会覆盖项目project.config.json中指定的基础库版本,导致wx.chooseImage回调参数结构变化(旧版返回tempFilePaths数组,新版返回tempFiles对象),进而使图片上传接口接收不到文件流。
正确操作步骤:

  1. 下载微信开发者工具稳定版v1.02.2303020(官网历史版本页可查);
  2. 打开项目后,点击右上角「详情」→「本地设置」→ 关闭「调试基础库」开关;
  3. 在app.json中确认"libVersion": "2.24.4"存在且未被注释。

2.3 数据库初始化:MySQL 5.7字符集与存储引擎的硬性要求

项目SQL脚本db/equipment_repair.sql要求MySQL 5.7.21+,且必须使用utf8mb4字符集(非utf8)。原因:微信小程序用户昵称、故障描述中常含emoji(如🔧⚠️✅),utf8仅支持3字节编码,无法存储4字节emoji,会导致插入时报错Incorrect string value: '\xF0\x9F\x9A\x80'。
执行前检查并修正:

-- 查看当前数据库字符集 SHOW VARIABLES LIKE 'character_set_database'; -- 若非utf8mb4,执行以下命令(需root权限) ALTER DATABASE equipment_repair CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; -- 修改表字符集(脚本中已包含,但需确保执行成功) ALTER TABLE t_user CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

注意:MySQL配置文件my.cnf中需添加以下配置,否则即使建库时指定utf8mb4,连接层仍可能降级:

[client] default-character-set = utf8mb4 [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci

3. 核心流程跑通:从微信扫码报修到后台工单分配,三步验证业务主干是否通畅

3.1 微信小程序扫码触发报修:设备二维码生成与解析逻辑

系统为每台设备生成唯一二维码,内容为https://yourdomain.com/wx/scan?deviceId=EQP-2023-001。小程序端通过wx.scanCode()获取URL后,提取deviceId参数,调用/api/repair/submit接口提交报修。
关键代码在pages/scan/scan.js:

// 扫码成功回调 wx.scanCode({ success: (res) => { const url = new URL(res.result); const deviceId = url.searchParams.get('deviceId'); // 注意:不是res.result.split('=')[1] if (!deviceId) { wx.showToast({ title: '二维码无效', icon: 'none' }); return; } // 调用报修接口,携带设备ID和用户openId wx.request({ url: getApp().globalData.baseUrl + '/api/repair/submit', method: 'POST', data: { deviceId: deviceId, openId: getApp().globalData.openId, // 此openId由小程序登录接口获取 description: this.data.description, images: this.data.imageUrls // 上传后的云存储URL数组 }, success: (res) => { if (res.data.code === 200) { wx.showToast({ title: '报修成功' }); } } }); } });

逻辑说明:res.result是完整URL字符串,必须用URL对象解析参数,直接split('=')会因URL含特殊字符(如&)而截断错误。openId是微信用户唯一标识,由小程序wx.login()获取code后,后端调用微信接口https://api.weixin.qq.com/sns/jscode2session换取,此步骤必须在报修前完成,否则后端无法关联用户身份。

3.2 SSM后端工单创建:MyBatis动态SQL与事务边界控制

报修接口RepairController.submit()核心逻辑在RepairService.createRepairOrder()中。它不是一个简单INSERT,而是跨表事务操作:

  1. 插入t_repair_order主表(含设备ID、用户openId、故障描述、状态=0待处理);
  2. 插入t_repair_image附件表(每张图片一行,关联order_id);
  3. 更新t_equipment表中该设备的last_fault_time字段。

MyBatis XML映射文件RepairMapper.xml中,关键动态SQL如下:

<!-- 插入主订单 --> <insert id="insertRepairOrder" parameterType="RepairOrder" useGeneratedKeys="true" keyProperty="id"> INSERT INTO t_repair_order (device_id, open_id, description, status, create_time) VALUES (#{deviceId}, #{openId}, #{description}, 0, NOW()) </insert> <!-- 批量插入图片 --> <insert id="insertRepairImages" parameterType="java.util.List"> INSERT INTO t_repair_image (order_id, image_url, upload_time) VALUES <foreach collection="list" item="image" separator=","> (#{orderId}, #{image}, NOW()) </foreach> </insert> <!-- 更新设备最后故障时间 --> <update id="updateEquipmentLastFaultTime" parameterType="string"> UPDATE t_equipment SET last_fault_time = NOW() WHERE device_id = #{deviceId} </update>

参数说明:useGeneratedKeys="true"确保主键id回填到Java对象,供后续批量插入图片时使用;<foreach>标签实现一次SQL插入多行,避免N+1查询;NOW()函数由MySQL执行,保证时间一致性。事务由Spring@Transactional注解控制,方法级回滚——任一SQL失败,全部操作撤销。

3.3 工单自动分配:基于设备所属区域的工程师匹配算法

系统不依赖人工派单,而是根据设备area_code(如BJ-01代表北京朝阳区)自动匹配对应区域的工程师。匹配逻辑在RepairService.assignEngineer()中:

public void assignEngineer(Long orderId, String deviceId) { // 1. 查询设备所属区域 Equipment equipment = equipmentMapper.selectByDeviceId(deviceId); String areaCode = equipment.getAreaCode(); // 如 "BJ-01" // 2. 查询该区域所有可用工程师(status=1且未超负荷) List<Engineer> engineers = engineerMapper.selectByAreaAndStatus(areaCode, 1); // 3. 简单轮询分配:取当前工单ID对工程师数取模 if (!engineers.isEmpty()) { int index = orderId.intValue() % engineers.size(); Long engineerId = engineers.get(index).getId(); // 4. 更新工单分配信息 RepairOrder order = new RepairOrder(); order.setId(orderId); order.setEngineerId(engineerId); order.setStatus(1); // 1=已分配 repairOrderMapper.updateById(order); } }

为什么用轮询而非负载均衡?毕业设计场景下,工程师数量少(通常<10人),轮询足够公平且无额外依赖。若需进阶,可替换为按current_order_count字段排序后取最小值——但需在t_engineer表中增加该字段并维护。


4. 避坑指南:这5个高频问题让90%新手卡在部署后“页面空白”或“报修无响应”

4.1 现象:小程序首页白屏,控制台报VMxxxx:1 Failed to load script

原因:app.js中getApp().globalData.baseUrl未配置,或配置的域名未在微信后台「开发管理-开发设置-服务器域名」中添加request合法域名。微信小程序强制HTTPS,且只允许配置的域名发起网络请求。
解决:

  1. 在微信开发者工具中,打开「详情」→「本地设置」→ 勾选「不校验合法域名」临时调试;
  2. 正式部署时,在 微信公众平台 →「开发管理」→「开发设置」→「服务器域名」中,将你的后端域名(如https://api.yourdomain.com)添加到request列表;
  3. 确保app.js中baseUrl值与配置域名一致,且末尾不带斜杠(https://api.yourdomain.com✅,https://api.yourdomain.com/❌)。

4.2 现象:后台启动成功,但访问/login返回404,或/api/repair/submit提示No mapping found

原因:Spring MVC的DispatcherServlet未正确拦截URL,常见于web.xml中servlet-mapping的url-pattern配置错误。本项目要求<url-pattern>/</url-pattern>(根路径),而非<url-pattern>*.do</url-pattern>。
解决:检查src/main/webapp/WEB-INF/web.xml,确认以下片段存在且未被注释:

<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> <!-- 必须是/,不是/*.do --> </servlet-mapping>

4.3 现象:报修提交后,数据库t_repair_order有记录,但t_repair_image为空,且小程序提示“图片上传失败”

原因:小程序端wx.uploadFile()的filePath参数指向本地临时路径(如/var/mobile/Containers/Data/Application/xxx/Documents/wechatfile/xxx.jpg),但后端RepairController.uploadImage()方法中,MultipartFile file参数名与前端formData中的name不一致。本项目约定name="file",若前端代码写成name="image",则Spring无法绑定参数。
解决:检查小程序上传代码:

wx.uploadFile({ url: getApp().globalData.baseUrl + '/api/repair/upload', filePath: tempFilePath, // 临时文件路径 name: 'file', // 必须是'file',与后端@RequestParam("file")对应 success: (uploadRes) => { /* ... */ } });

4.4 现象:登录后openId始终为undefined,导致报修时后端抛出NullPointerException

原因:小程序wx.login()获取code后,未调用后端/api/user/login接口换取openId,或后端接口未正确解析微信返回的JSON。微信接口https://api.weixin.qq.com/sns/jscode2session返回格式为{"openid":"xxx","session_key":"xxx","unionid":"xxx"},若后端用response.toString()直接转字符串而未JSON解析,会丢失openid字段。
解决:后端UserController.login()中,必须用Jackson解析:

String result = HttpUtil.doGet("https://api.weixin.qq.com/sns/jscode2session?" + "appid=" + APP_ID + "&secret=" + APP_SECRET + "&js_code=" + code + "&grant_type=authorization_code"); // 使用ObjectMapper解析 JsonNode node = objectMapper.readTree(result); String openId = node.get("openid").asText();

4.5 现象:Tomcat启动后控制台无报错,但浏览器访问http://localhost:8080显示404,或跳转到Tomcat默认页

原因:项目未打包为WAR,或WAR包未正确部署到Tomcat的webapps目录。本项目是标准Maven Web项目,需执行mvn clean package生成target/equipment-repair.war,不能直接运行mvn tomcat7:run(该插件已过时且与Spring 4.3不兼容)。
解决:

  1. 命令行进入项目根目录,执行mvn clean package;
  2. 将生成的target/equipment-repair.war复制到Tomcat安装目录webapps/下;
  3. 启动Tomcat(bin/startup.sh或bin/startup.bat),等待自动解压;
  4. 访问http://localhost:8080/equipment-repair/(注意路径含项目名)。

5. 数据库设计精要:5张核心表如何支撑“设备-报修-工程师-反馈”全链路

5.1 设备主表t_equipment:不只是静态信息,更是业务触发器

字段名类型说明关键约束
idBIGINT PK主键自增
device_idVARCHAR(50)设备唯一编码(如EQP-2023-001)UNIQUE NOT NULL,扫码依据
nameVARCHAR(100)设备名称(如“XX实验室离心机”)—
area_codeVARCHAR(20)所属区域编码(如BJ-01)外键关联t_area,用于自动派单
statusTINYINT设备状态(0=停用,1=启用)默认1,停用设备不可报修
last_fault_timeDATETIME上次故障时间每次报修后更新,用于统计设备健康度

血泪经验:device_id必须设为UNIQUE索引,否则扫码时可能匹配到多条设备记录,导致工单创建混乱。area_code不存中文(如“北京朝阳区”),而用编码,便于SQL关联和程序判断,也避免中文字符集问题。

5.2 报修主表t_repair_order:状态机驱动,拒绝“半成品”工单

字段名类型说明状态流转逻辑
idBIGINT PK工单ID—
device_idVARCHAR(50)关联设备外键
open_idVARCHAR(100)报修用户—
descriptionTEXT故障描述—
statusTINYINT工单状态0=待处理 → 1=已分配 → 2=处理中 → 3=已完成 → 4=已关闭
engineer_idBIGINT分配工程师IDstatus≥1时必填
create_timeDATETIME创建时间—
finish_timeDATETIME完成时间status=3时更新

为什么状态用数字而非字符串?节省存储空间,且Java中用enum RepairStatus { WAITING(0), ASSIGNED(1), ... }可直接映射,避免字符串比较错误。finish_time仅在status变为3时更新,由RepairService.completeOrder()方法内update语句触发,禁止在前端传入,防止时间篡改。

5.3 工程师表t_engineer:轻量级角色管理,不引入RBAC复杂度

字段名类型说明实用技巧
idBIGINT PK工程师ID—
nameVARCHAR(50)姓名—
phoneVARCHAR(20)手机号用于短信通知(可选)
area_codeVARCHAR(20)负责区域与t_equipment.area_code完全一致,用于JOIN匹配
statusTINYINT在岗状态0=休假,1=在岗(派单只选status=1)

注意:t_engineer表无密码字段,因登录由微信小程序完成,工程师使用手机号+短信验证码登录后台管理页(/admin/login),安全性够用且免去密码管理负担。area_code值必须与设备表严格一致,否则SELECT * FROM t_engineer e JOIN t_equipment eq ON e.area_code = eq.area_code将无结果。

5.4 图片附件表t_repair_image:分离大文件,保障主表查询性能

字段名类型说明设计哲学
idBIGINT PK附件ID—
order_idBIGINT关联工单INDEX onorder_id,查询某工单所有图片时加速
image_urlVARCHAR(255)图片云存储URL本项目存七牛云或本地/upload/目录,绝不存二进制BLOB
upload_timeDATETIME上传时间—

为什么不用BLOB?BLOB会使t_repair_order表体积暴增,SELECT * FROM t_repair_order变慢。URL方式解耦存储,图片可独立CDN加速,且方便后期迁移到OSS。image_url字段长度设255,足够存七牛云标准URL(如http://xxx.qiniucdn.com/xxx.jpg?Expires=xxx)。

5.5 用户表t_user:极简设计,只存微信授权必要信息

字段名类型说明最小化原则
idBIGINT PK用户ID—
open_idVARCHAR(100)微信唯一标识UNIQUE,主键逻辑
nick_nameVARCHAR(50)昵称可为空,微信授权时获取
avatar_urlVARCHAR(255)头像URL—
create_timeDATETIME首次登录时间—

不存手机号、邮箱等冗余字段。微信小程序用户隐私政策要求最小化收集,且报修场景无需联系用户(工程师主动电话沟通)。open_id是微信体系内唯一ID,不同公众号/小程序间不互通,绝对不可用作跨系统用户标识——这点在答辩时务必强调,体现数据合规意识。


6. 毕设答辩与二次开发:3个高分技巧+2个可拓展方向,让项目从“能跑”升级为“亮眼”

6.1 答辩现场演示:聚焦“三个15秒”,用可视化击中评委痛点

毕设答辩不是代码朗诵,而是讲好一个故事。我带学生答辩时,固定用三个15秒高光片段抓住评委注意力:

  1. 第一幕(扫码报修):拿起手机,打开微信“扫一扫”,对准打印好的设备二维码(提前贴在笔记本上),0.5秒识别,弹出报修表单,输入“离心机无法启动”,选一张故障照片,点击“提交”——15秒内完成从物理设备到数字工单的转化;
  2. 第二幕(后台响应):切换到Chrome,打开http://localhost:8080/equipment-repair/admin,输入管理员账号,进入“工单列表”,刷新页面——新工单实时出现,状态为“已分配”,工程师姓名已填,证明自动派单生效;
  3. 第三幕(闭环验证):在后台找到该工单,点击“处理中”,再点“已完成”,回到小程序“我的报修”,下拉刷新——状态变为绿色“已完成”,并显示工程师留言“已更换保险丝”。

这三个动作不依赖台词,纯操作流,评委一眼看懂价值。切记:演示前清空数据库,确保工单ID从1开始,避免评委质疑“这是预置数据”。

6.2 论文写作避坑:技术章节必须出现“对比实验”,而非功能罗列

很多论文败在“第3章 系统设计”写成截图堆砌。高分论文必须有量化对比。例如:

  • 在“数据库设计”小节,插入表格:
方案查询设备最新故障时间SQL执行耗时(10万设备数据)
方案A:SELECT MAX(create_time) FROM t_repair_order WHERE device_id=?SELECT ... GROUP BY device_id1200ms
方案B(本文):t_equipment.last_fault_time字段SELECT last_fault_time FROM t_equipment WHERE device_id=?8ms
  • 在“小程序性能”小节,用Chrome DevTools Network面板截图,标注/api/repair/submit接口TTFB(Time To First Byte)≤200ms,证明优化有效。

数据必须真实!我让学生用sysbench压测MySQL,用wx.getNetworkType()监控小程序弱网表现。没有数据的“高性能”“高并发”全是空话。

6.3 二次开发方向:加一个“微信消息模板推送”,成本最低、效果最炸

微信小程序消息推送是毕业设计加分神技,无需额外服务器,只需配置模板ID。步骤极简:

  1. 登录 微信公众平台 →「功能」→「模板消息」→ 新建模板,选择“维修进度通知”,字段:{{first.DATA}}(报修成功)、{{keyword1.DATA}}(设备编号)、{{keyword2.DATA}}(当前状态)、{{remark.DATA}}(预计完成时间);
  2. 后端RepairService.assignEngineer()方法末尾,添加推送逻辑:
// 获取模板ID(在平台申请后填入) String templateId = "xxx-xxx-xxx"; // 构造模板数据 Map<String, Object> data = new HashMap<>(); data.put("first", Map.of("value", "您的报修已受理!")); data.put("keyword1", Map.of("value", deviceId)); data.put("keyword2", Map.of("value", "工程师已接单")); data.put("remark", Map.of("value", "预计2小时内上门")); // 调用微信API发送(需access_token) String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken; HttpUtil.doPost(url, JSON.toJSONString(Map.of("touser", openId, "template_id", templateId, "data", data)));

效果:用户提交报修后,微信服务通知立刻抵达,显示“您的报修已受理!设备编号:EQP-2023-001,当前状态:工程师已接单”,比APP推送更及时。此功能增加代码不足20行,但答辩时放一张微信通知截图,评委立刻觉得“这学生懂落地”。

6.4 部署上线 checklist:5项必须验证,避免答辩前夜服务器崩盘

交付前,我让学生逐项打钩:

  • [ ] 后端:application.properties中jdbc.url已改为生产数据库地址,server.port=8080未被注释;
  • [ ] 小程序:project.config.json中appid已替换为自己的,app.js中baseUrl指向公网IP或域名;
  • [ ] 微信后台:服务器域名、业务域名、JS安全域名全部添加,模板消息ID已申请;
  • [ ] 数据库:t_user表中至少有一条管理员记录(open_id可填测试值),t_engineer表有至少一名status=1的工程师;
  • [ ] 安全:web.xml中<filter>已配置CharacterEncodingFilter(解决中文乱码),<security-constraint>未开启(毕业设计无需复杂权限)。

最后一次部署,我坚持让学生用同学手机扫自己生成的二维码,从报修到收到微信通知全程走一遍。所有技术方案的价值,最终都落在“能不能让另一个人,不看文档,3分钟内完成一次真实报修”。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询