ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

微信小程序+Spring Boot:传染病防控系统从0到1实战开发

微信小程序+Spring Boot:传染病防控系统从0到1实战开发 当“传染病防控”从应急处置走向常态化管理之后基层的信息采集压力一下子变大了。纸质登记效率低、数据汇总慢、跨部门流转全靠人工这些痛点在这个项目里其实都指向同一个答案用微信小程序做前端采集端再用一套后台管理系统做数据汇聚和预警。前段时间我完整做了一个“基于微信小程序的传染病防控系统”源码、文档、调试全流程走了一遍今天把这套东西拆开聊聊。这个项目包含两个端用户使用的微信小程序端以及管理员使用的Web管理端。小程序端负责健康打卡、信息登记、行程上报、防控资讯浏览管理端负责人员管理、打卡审核、数据统计和预警处理。整体适合正在做毕业设计、课程设计或者想快速搭建一套“信息采集数据展示”小系统的开发者参考。我会把整套系统从需求拆解、功能设计、核心代码实现到文档编写、调试排坑完整讲一遍。尤其是调试那一块很多问题不是代码写错而是微信小程序运行环境的特殊性导致的这块经验外面文档很少写全。1. 需求分析与整体设计思路1.1 这个系统到底要解决什么问题先别急着写代码任何一个系统在动手之前都要把问题定义清楚。传染病防控这个场景核心痛点可以归结为三个字采、报、管。“采”是指信息采集包括个人基本信息、健康状况、体温、行程轨迹、接触史等。传统方式靠填Excel表或者纸质登记效率低而且容易漏。“报”是指信息上报采集到的数据需要汇总到防控管理部门形成统计报表。“管”是指异常处理如果有人体温异常或者来自高风险地区系统要能触发预警提醒管理人员及时跟进。所以系统核心流程可以概括为用户在小程序端填报信息数据写入数据库管理端实时汇总展示异常数据触发预警通知。这个流程在技术上并不复杂但涉及的角色、状态、权限有不少细节要处理。1.2 核心模块划分与技术选型我把系统拆成了三个端小程序端、服务端、管理端。小程序端是用户直接接触的界面负责信息采集服务端提供接口和数据处理逻辑管理端给防控人员使用负责查询、审核、统计。技术选型上小程序端自然用微信官方原生框架毕竟标题就是“微信小程序”不需要额外引入uni-app之类的跨端框架原生开发在调试和真机适配上都更直接。服务端我用的是Spring Boot因为用户量级不大Spring Boot自带的Tomcat完全够用而且生态成熟网上资料多遇到问题好查。数据库选了MySQL原因很简单这系统的数据是结构化数据为主用户表、打卡记录表、行程表之间有关系用关系型数据库管理最稳。管理端用Vue 2 Element UI这套组合在后台管理系统中非常常见。Vue 2虽然不算最新但胜在稳定、资料多对毕业设计或者企业内部的小系统来说完全够用。如果你更熟悉Vue 3也可以替换核心逻辑不受影响。1.3 为什么微信小程序是合理的产品载体用户在传染病防控场景下需要的是一个“打开即用”的工具微信小程序天然满足这个需求。小程序不需要下载安装扫码或者搜索就能打开学习成本几乎为零。尤其是面对年纪偏大、不太会装App的使用者小程序的门槛明显更低。而且微信小程序提供了一些原生能力对防控场景非常有用。比如wx.getLocation可以获取用户位置配合逆地址解析就能得到详细的行程地点wx.scanCode可以扫场所码快速登记到访信息订阅消息可以主动推送防控通知给用户。这些能力如果换成H5实现起来要费不少功夫。还有一点很多人会忽略微信小程序的审核机制和更新机制。小程序发布后用户下次打开会自动更新到最新版本不需要用户手动操作。对于防控政策可能随时调整的场景来说这个特性很关键——昨天还在用“健康码行程卡”双查验今天可能就要改成“场所码登记”小程序端的功能可以做到快速迭代上线。2. 核心功能实现与关键代码细节2.1 登录态与用户身份绑定5分钟跑通小程序登录是整套系统的基础所有的用户操作都要先绑定微信身份。微信小程序登录流程说白了就是三步小程序端调wx.login拿到一个临时code把code发给后端后端拿着code去微信接口换openid和session_key后端生成自定义登录态返回给前端前端存起来后续请求带着这个登录态就行。很多新手在这里会踩一个坑直接把openid返回给前端当登录凭证。这其实是把敏感信息暴露了。openid是用户在微信体系内的唯一标识一旦泄露别人就可以伪造你的用户身份。正确做法是后端自己生成一个token比如用UUID或者JWT然后和openid关联存储。// 后端代码示意微信登录接口 PostMapping(/api/auth/login) public Result login(RequestBody LoginDTO dto) { // 1. 使用 code 换取 openid String url https://api.weixin.qq.com/sns/jscode2session?appid appId secret appSecret js_code dto.getCode() grant_typeauthorization_code; String result restTemplate.getForObject(url, String.class); JSONObject json JSON.parseObject(result); String openid json.getString(openid); // 2. 查询用户是否存在不存在则自动注册 User user userMapper.selectByOpenid(openid); if (user null) { user new User(); user.setOpenid(openid); user.setCreateTime(new Date()); userMapper.insert(user); } // 3. 生成自定义登录态 String token UUID.randomUUID().toString().replace(-, ); redisTemplate.opsForValue().set(login:token: token, openid, 7, TimeUnit.DAYS); return Result.success(token); }小程序端登录代码要注意一个问题wx.login拿到的code只能用一次而且有效期只有5分钟。如果你在页面里反复调wx.login后面的code会失效。正确做法是启动时调一次拿到token后存起来后续接口都带着token走。2.2 健康打卡表单防重复提交的那点事健康打卡是防控系统的核心高频功能用户每天至少提交一次。设计打卡功能时我重点考虑了三个问题表单校验、防重复提交、数据可追溯。表单校验是最基本的体温范围、手机号格式、必填项检查都要在前端做一层后端也要做一层。后端校验是安全底线不能依赖前端。我当时写了个简单的手写校验工具类判断体温是否在35到42度之间手机号是否符合11位数字规则。防重复提交这个在真实场景里非常考验细节。用户可能手滑点了两次提交也可能网络差导致前端重试。如果不加处理数据库里就会出现重复记录。最简单有效的方案就是打一个“唯一索引”在数据库层兜底在打卡记录表里给user_id和date加联合唯一索引。这样即使前端怎么重复请求数据库也只保留一条。ALTER TABLE health_checkin ADD UNIQUE KEY uk_user_date (user_id, checkin_date);同时前端也要做按钮置灰处理提交中状态锁定提交按钮避免用户多次点击。实测下来双保险最稳单靠前端限制还是不放心。2.3 异常预警与管理端数据看板数据采集上来之后最重要的就是异常预警。我设计了一套规则引擎逻辑体温超过37.3度自动标记为“发热”行程中选择了高风险地区标记为“高风险”接触过确诊人员标记为“密接”。这些规则不复杂用简单的判断逻辑就能实现但支撑的数据结构要设计好。打卡表里除了基础信息还要预留一个status字段用整数状态码区分0代表正常1代表发热2代表高风险3代表密接。这样管理端查询异常记录时只需要一句SELECT * FROM health_checkin WHERE status 0 AND submit_date ?就能搞定效率很高。管理端的统计看板是另一个工作量重点。我实现了几个核心图表每日打卡人数趋势图用折线图、人员健康状态分布用饼图、异常记录列表用表格。前端用ECharts实现后端提供统计接口返回的数据直接是图表可用的JSON结构。这一步的核心是SQL的聚合查询// 按日统计打卡人数 SELECT submit_date, COUNT(DISTINCT user_id) FROM health_checkin WHERE submit_date BETWEEN ? AND ? GROUP BY submit_date;2.4 后台管理端的最小可用实现管理端不用做得很花哨核心是“查询、审核、导出”。用户管理负责查看注册用户和重置账号状态打卡管理负责按日期、状态筛选打卡记录预警管理是重点管理员可以查看异常预警列表并标记处理状态数据统计负责导出报表导出Excel这块我直接用了EasyExcel配合一个简单的前端按钮就能实现导出。这里有个容易被忽视的权限问题。管理端和小程序端是同一个用户体系吗不是。管理员是内部人员不能走小程序的自动注册逻辑。我的方案是单独建一张管理员表手动预置账号登录走传统账号密码方式用拦截器校验管理员身份。小程序端的用户即使拿到了管理端地址因为没有账号也无法登录这样就实现了权限隔离。3. 项目文档的编写与组织标题里写了“源码文档”实际做项目的时候文档的重要性往往被低估。代码写完了如果文档一团糟后面接手维护的人会非常痛苦。我这次把文档拆成了五类每类都有明确的作用。3.1 需求文档与原型说明需求文档是给所有人看的要说明系统给谁用、解决什么问题、有哪些角色、每个角色能做什么。这个文档不需要写技术细节但要把功能场景写清楚。比如“用户在小程序端提交每日健康打卡管理员在管理端查看汇总数据”这种就是核心需求。原型说明建议配合截图写。我当时把小程序每个页面的截图和管理端每个页面的截图都放进文档里配上页面跳转逻辑和交互说明。这样即使不看代码也能对系统有直观认知对答辩或者项目汇报特别有用。3.2 接口文档与数据库设计文档接口文档是前后端联调的契约。我是用Apifox写的接口文档每个接口标注请求方式、URL、请求参数、返回结果、错误码。这里有个心得接口返回结构一定要统一推荐用Result.success(data)和Result.error(code, msg)这种统一包装前端处理起来非常舒服。数据库设计文档要把每张表的字段都列清楚字段名、类型、长度、是否为空、注释都要写全。最重要的是外键关系和索引设计要说明白。比如用户表、打卡表、行程表之间的关联关系如果不画ER图后面维护的人很容易搞混。3.3 部署文档与测试报告部署文档要覆盖从零到跑通的完整步骤安装JDK、安装MySQL、导入SQL脚本、修改配置文件、打包部署、小程序后台配置域名。每一步都要给出具体命令和截图。我在部署文档里踩过一个大坑小程序请求的接口必须是HTTPS域名而且要配置在微信公众平台的服务器域名白名单里。如果忘了配置前端就会报“域名不合法”。测试报告不用写得很学术但要有真实的测试记录。我当时整理了一张测试用例表包含用例编号、测试场景、操作步骤、预期结果、实际结果、是否通过。这个文档在答辩时特别加分因为能证明你是真实跑过系统而不只是写了代码。4. 完整开发与调试实战记录4.1 从搭建环境到跑通第一个接口开发环境搭建这块我建议按这个顺序来做先装JDK 8和Maven再装MySQL 5.7然后装微信开发者工具最后装IDEA。顺序不能乱因为后端项目启动依赖MySQL小程序调试依赖后端起服务。后端项目启动后第一个要测的就是登录接口。我建了一个测试用户在微信开发者工具里模拟调用wx.login拿到code后请求后端登录接口。接口返回成功且能拿到token整个系统的前后端链路就算通了。这一步走通了后面的开发就都是“填空”。要注意的是微信开发者工具默认的模拟器环境可以正常请求http://localhost:8080但真机调试不行。真机小程序必须请求HTTPS域名。如果还没有正式域名和证书可以在开发者工具里勾选“不校验合法域名”选项来临时调试。4.2 真机调试与远程调试的区别很多初学者只在开发者工具里点一点就算调试完了这个习惯我建议趁早改掉。模拟器能模拟大部分功能但有些问题只存在于真机环境手机网络下的请求速度、不同机型的状态栏高度、小程序冷启动加载速度等。微信开发者工具提供了“真机调试”和“远程调试”两个功能很多人分不清。真机调试是把开发版小程序通过二维码在手机上打开适合体验真实设备的功能表现远程调试则是在手机上打开小程序同时在电脑上打开调试工具的面板可以实时看网络请求、Console日志和DOM结构。我实操下来发现微信小程序的Screen页面栈、Wxml面板、Network面板这三个调试工具最常用。Network面板能看清每个请求的耗时和返回状态如果接口返回401说明token过期返回500优先看后端日志。这些信息在自己排查问题时非常管用。4.3 调试中的网络工具与问题定位在整个开发过程中我发现最让人头疼的就是“小程序前端报错但不知道后端发生了什么”。解决这个问题最快的方式就是看后端日志和数据库里面的实际数据而不是光看前端报错信息。后端我配置了logback日志框架把日志级别调到DEBUG这样请求参数、SQL执行、异常堆栈都能打印出来。前端配合使用console.log输出关键变量两边日志一对照问题基本就能定位。另外有一个常见问题小程序端请求后端接口超时。微信小程序的默认超时时间是60秒但实际体验来看超过10秒用户就已经不耐烦了。我封装了一个统一的请求工具类设置合理的超时时间同时对网络错误做统一处理。5. 常见问题与排查技巧实录5.1 “获取登录后的微信用户失败”如何处理这个报错我调试的时候遇到过当时被折腾了整整一下午。报错原因在小程序端拿不到用户的微信头像昵称——微信官方在2021年前后调整了获取用户信息的规则wx.getUserInfo不再直接返回用户的真实头像昵称必须通过“头像昵称填写能力”让用户主动填写获取。这个改动让很多旧代码直接失效解决方案也没那么复杂。现在推荐的做法是在小程序端做一个引导页面让用户点击“授权头像昵称”按钮然后通过button组件的open-typechooseAvatar和input的typenickname功能来获取。获取到的信息再传给后端更新用户资料不要依赖wx.getUserInfo。看到标题所附的热搜词“小程序获取登录后的微信用户失败:wx1cb4398e1413dce7”这个错误码前缀是appid的识别码说明是小程序自身的AppID报错本质原因大概率是上述授权规则的问题。排查路径我建议按照这个顺序来先确认基础库版本在2.21.2以上再检查有没有调用wx.getUserProfile成功然后看后端日志里有没有openid最后检查登录token有没有过期。5.2 打卡数据死活提交不上去怎么查打卡提交失败是高频问题。我遇到过一次线上事故某个用户连续三天提交打卡都失败最后排查发现是手机号格式校验太严格把“手机号带空格”的情况拦下来了。排查这类问题的思路我总结了一个四步法一看前端有没有把数据传给后端二看后端有没有收到请求三看SQL有没有执行成功四看数据库里到底有没有写入数据。任何一步断了都能找到具体原因。还有就是要注意微信小程序的并发请求限制。小程序同时最多发起10个请求如果页面加载时多个接口并发请求很可能后面的请求就被排队了。我优化过一次打卡页面把不相关的接口改为懒加载打卡提交的响应速度快了不少。5.3 省市区联动选择器与自定义组件的坑防控系统里有一个高频率使用的功能就是选择“当前所在地”需要做成省市区三级联动。微信小程序原生的picker组件只支持单选不支持多列联动。我当时第一时间就想到了自定义组件的方式。网上有现成的省市区组件比如mpvue-city-picker但它依赖mpvue。我最终选择用微信小程序的picker-view组件自己实现数据结构用三层嵌套对象通过两级联动判断子级数据。核心逻辑就是第一列变化时重置第二列和第三列的数据第二列变化时重置第三列的数据。这里有个体验细节要说明如果你直接把省市区数据放在小程序端的JS文件里包体积会很大。省市区数据有几千条建议放到后端接口返回前端做缓存即可。这样既能缩减包体积更新数据也不用重新发版。5.4 常见问题速查表问题现象可能原因解决方法请求报“域名不合法”未配置服务器域名白名单在微信公众平台添加request合法域名登录后获取不到用户信息微信授权规则调整使用头像昵称填写能力重新采集接口返回401token过期或未传递检查请求拦截器统一携带token打卡数据重复前端重复提交数据库加唯一索引前端按钮置灰真机调试请求失败缺少HTTPS证书或网络不通配置HTTPS证书检查手机网络管理端污染用户数据权限控制不到位管理员独立账号体系接口校验身份写到最后这个系统从需求梳理到最终调试通过前后大概花了两周时间。坦白说功能本身不算复杂真正的复杂度在于微信小程序的各类规则限制和边界情况处理。比如授权规则调整、域名白名单这些文档里不会主动告诉你都是踩过坑才长记性。最后想给正在做类似项目的朋友两个建议第一先把数据库设计想清楚再写代码我见过太多项目做了一半发现表结构要改改动成本巨大第二尽早用真机调试不要等到全部功能写完再上真机否则排查问题的范围会大到你不想面对。希望这套经验能帮你少走一些弯路。
返回列表