首页 / 资讯中心 / 文章详情

微信小程序+云开发:宿舍管理系统全栈设计与实现

微信小程序+云开发:宿舍管理系统全栈设计与实现 ★ FEATURED ARTICLE
简介这份资源是面向高校宿管人员与学生、以及学习微信小程序开发者的宿舍管理系统项目源码基于微信开发者工具构建提供宿管与学生双向登录入口覆盖签到、卫生评分、留言回复、晚归申请等日常管理场景可用于课程设计参考或小程序全栈练手。压缩包共约2000个文件整体8.4MB以769个js与393个ts脚本承载业务逻辑258个json与236个md用于配置和说明文档另有wxml、wxss页面文件及proto、yml等辅助配置目录结构完整便于按模块查阅。目前已有1958人学习下载。项目将小程序便捷性与宿舍管理需求结合预留MySQL数据库接口用于数据存储与登录密码校验读者可从中了解双角色权限划分、GPS定位签到、积分式卫生评分与留言沟通等模块的实现思路作为同类校园管理应用的参考。1. 需求先立住为什么宿舍管理这件事非得用微信小程序重做一遍每年开学季宿舍管理这件事就会集中爆雷新生分配床位靠 Excel 来回传晚归登记靠宿管阿姨手写本子报修要跑到值班室填单子检查卫生的结果贴在楼道里没人看。这些场景的共同点是——数据分散、流程断点、责任难追溯。我见过一个最典型的翻车现场某高校一栋楼同时用三份不同的住宿名单退宿时发现有两个学生被分到了同一张床最后靠人工翻纸质记录才理清。这类问题的根子不在人在于工具没有把「人—房—事」三条线串起来。微信小程序恰好卡在这个痛点上学生不用装 App扫码即用宿管和辅导员在微信里就能处理审批微信开发者工具把前端、云函数、数据库调试串成一条链一个人也能把整套系统跑通。这套方案要解决的就是宿舍场景下的住宿信息管理、报修流转、晚归登记和卫生检查四件事适合正在做毕设或课程设计、需要一套能跑通且能讲清楚设计逻辑的完整项目的读者。2. 总体架构设计小程序端、云开发与数据层的职责划分2.1 三层结构怎么切这套系统我一般按三层来切表现层是微信小程序页面负责表单、列表、状态展示逻辑层是云函数承担权限校验、状态流转和统计聚合数据层是云数据库的集合按业务对象拆成独立集合。三层之间只通过云函数调用和数据库读写交互页面不直接操作敏感集合这样权限边界清晰后期加功能也不用动老代码。为什么不把逻辑全写在小程序端血泪经验是一旦把审批状态判断放在前端学生改个请求参数就能自己把报修单标成「已处理」。云函数作为唯一写入口配合openid做身份识别才能保证「谁提交的、谁审批的、什么时候改的」这条链不断。表现层只做展示和收集逻辑层做判断数据层做持久化职责不混。2.2 数据模型与集合划分数据模型是整个系统的地基我通常拆成五个核心集合字段设计如下表。注意每个集合都带createTime和updateTime出问题时这两个字段就是黑匣子。集合名关键字段说明usersopenid, name, role, roomId, phonerole 取 student/manager/adminroomsbuildingNo, roomNo, capacity, occupied, statusstatus 取 normal/full/maintenancerepairsopenid, roomId, category, desc, images, status, handlerstatus 取 pending/processing/donelateRecordsopenid, roomId, returnTime, reason, checker晚归登记checker 记录登记人inspectionsroomId, score, items, inspector, date卫生检查items 存分项扣分users里的role是权限判断的唯一依据云函数每次执行先查这个字段再决定放不放行。rooms的occupied用计数器而不是每次 count 查询是为了避免高并发下分床冲突——这是分配床位时最容易翻车的地方。2.3 云函数入口与权限校验骨架下面这段是云函数公共入口的骨架所有业务云函数都复用它做身份和角色校验。代码里db是云数据库实例_是命令对象。// cloudfunctions/common/auth.js const cloud require(wx-server-sdk) cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const db cloud.database() // 根据 openid 查用户返回角色查不到直接拒绝 async function checkRole(openid, allowRoles) { const res await db.collection(users).where({ openid }).get() if (res.data.length 0) { throw new Error(USER_NOT_FOUND) // 未注册用户前端引导补全信息 } const user res.data[0] if (!allowRoles.includes(user.role)) { throw new Error(NO_PERMISSION) // 角色不匹配记录日志便于排查 } return user } module.exports { checkRole }这段代码的关键在两点一是openid由微信上下文自动注入前端伪造不了二是角色白名单用数组传入每个云函数声明自己允许哪些角色调用比如报修审批只允许manager和admin。参数说明上allowRoles必须显式传不允许默认放行——我见过有人图省事写成「不传就全放」结果学生能调审批接口这是典型的权限裸奔。3. 核心模块实现住宿分配、报修流转与检查登记3.1 床位分配的事务处理床位分配是整套系统里唯一需要保证原子性的操作先占床位、再写学生房间号两步必须同生共死。云开发没有传统数据库的事务语法通常的做法是用「条件更新 失败回滚」模拟。核心思路是先对rooms做带条件的自增只有occupied capacity时才成功成功后再更新学生记录。// cloudfunctions/assignRoom/index.js const { checkRole } require(../common/auth) exports.main async (event) { const { OPENID } cloud.getWXContext() await checkRole(OPENID, [manager, admin]) const { studentOpenid, roomId } event // 第一步条件自增占位成功才继续 const incRes await db.collection(rooms) .where({ _id: roomId, status: normal, occupied: _.lt(_.expr($capacity)) }) .update({ data: { occupied: _.inc(1) } }) if (incRes.stats.updated 0) { return { code: 4001, msg: 床位已满或房间不可用 } } // 第二步写学生房间号失败则回滚占位 try { await db.collection(users).doc(studentOpenid) .update({ data: { roomId, updateTime: Date.now() } }) return { code: 0, msg: 分配成功 } } catch (e) { await db.collection(rooms).doc(roomId).update({ data: { occupied: _.inc(-1) } }) return { code: 5001, msg: 分配失败已回滚 } } }这里_.lt(_.expr($capacity))是字段间比较保证占位判断和自增在同一次数据库操作里完成避免「先查后改」的竞态。回滚那一步不能省否则会出现床位被占但学生没分到的「幽灵占位」。参数上studentOpenid由前端从学生列表选中后传入roomId来自房间列表两个值都要在云函数里再校验一次存在性不能信任前端。3.2 报修工单的状态机报修模块的难点不在提交在状态流转。我一般把它设计成三态机pending → processing → done每次流转记录操作人和时间。状态机的好处是任何非法跳转比如从 pending 直接到 done都能在云函数里拦掉前端按钮只是展示真正的闸门在服务端。// 状态流转白名单当前状态 - 允许的下一状态 const FLOW { pending: [processing], processing: [done], done: [] } async function changeRepairStatus(id, nextStatus, operator) { const cur await db.collection(repairs).doc(id).get() const curStatus cur.data.status if (!FLOW[curStatus].includes(nextStatus)) { throw new Error(非法流转: ${curStatus} - ${nextStatus}) } await db.collection(repairs).doc(id).update({ data: { status: nextStatus, handler: operator, updateTime: Date.now() } }) }FLOW表就是这套逻辑的后悔药以后要加「驳回」状态只改这张表不用翻遍代码找判断。operator从checkRole返回的用户对象里取保证记录的是真实处理人。图片字段images存的是云存储 fileID 数组前端上传后拿到的 fileID 直接入库展示时用临时链接换取避免把长期链接写死。3.3 卫生检查与晚归登记的批量录入卫生检查和晚归登记的共同点是「一次录一批」如果每间房单独调一次云函数网络往返能把宿管逼疯。我通常做成批量接口前端把整层楼的检查结果攒成一个数组一次提交云函数里用Promise.all并发写入失败项单独返回。// 批量写入检查记录返回成功与失败明细 async function batchSaveInspections(list, inspector) { const tasks list.map(item db.collection(inspections).add({ data: { ...item, inspector, date: Date.now() } }).then(() ({ roomId: item.roomId, ok: true })) .catch(e ({ roomId: item.roomId, ok: false, err: e.message })) ) const results await Promise.all(tasks) return { success: results.filter(r r.ok).length, failed: results.filter(r !r.ok) } }Promise.all在这里不会因为单个失败而整体中断因为每个任务内部已经 catch 了。返回的failed数组让前端能精确提示「哪几间房没存上」宿管补录时不用重头再来。晚归登记同理只是字段换成returnTime和reasonchecker记录登记人方便事后追溯是谁登记的。4. 避坑与排查上线前最容易翻车的五个点4.1 现象学生能看到别人的报修单原因通常是查询时没带openid过滤或者把列表接口做成了「全量返回前端再筛」。解决方式是在云函数里强制拼where({ openid: OPENID })学生角色只查自己的管理角色才放开全量。这个坑我在早期项目里踩过前端筛看似省事实际是把数据全暴露了。4.2 现象床位分配偶发「超卖」原因是先get查余量再update自增两步之间有窗口期。解决就是 3.1 里的条件更新把判断和自增压进一次数据库操作。如果业务复杂到需要多集合事务通常的做法是把关键操作收敛到单个云函数里串行执行别拆成多个接口让前端编排。4.3 现象云函数本地调试正常线上报环境错误多半是cloud.init里写死了环境 ID或者DYNAMIC_CURRENT_ENV没配对。排查时先看云函数日志里的env字段确认实际连的是哪个环境。我一般要求所有云函数统一用DYNAMIC_CURRENT_ENV环境切换靠开发者工具的上传配置不在代码里硬编码。4.4 现象图片上传成功但列表里显示裂图原因是存了临时链接而不是 fileID临时链接过期就裂。解决是入库只存 fileID展示时用wx.cloud.getTempFileURL批量换取换完缓存到页面 data 里别每次渲染都换。这个细节不写进设计文档后期接手的人十有八九会重新踩一遍。4.5 现象批量录入时部分记录重复原因是网络超时后前端重试而接口没有幂等设计。解决是给每条记录带一个前端生成的clientId云函数写入前先按clientId查重已存在就跳过。幂等这件事在批量场景里是刚需单条提交反而没那么要紧。5. 验收与答辩怎么证明这套系统真的能用验收这件事我一般分三步走每一步都有可量化的判据答辩时直接拿数据说话。第一步是功能闭环验收。按角色走一遍完整链路学生提交报修 → 宿管接单转 processing → 处理完成转 done → 学生在「我的报修」里看到状态变化和时间戳。住宿分配要专门测边界把一间房占满后再分配看是否返回 4001 且occupied没有虚增分配中途模拟写学生记录失败看回滚是否把计数减回去。卫生检查和晚归登记各录一批建议不少于 20 条核对成功数与失败明细是否对得上。第二步是权限与数据隔离验收。用两个学生账号交叉测试A 能否查到 B 的报修单、能否调用审批接口、能否修改别人的房间号。预期结果全部是拒绝且云函数日志里能看到NO_PERMISSION记录。这一步答辩时最容易被追问提前把日志截图准备好比口头解释有说服力。第三步是性能与异常验收。批量录入 50 条检查记录记录接口耗时通常应在 2 秒内返回断网状态下提交报修看前端是否有明确提示而不是白屏连续快速点击提交按钮确认幂等逻辑没有产生重复单。下面这张表可以直接作为验收记录模板。验收项操作预期结果实际结果床位超卖满房后再分配返回 4001计数不变待填越权查询学生 A 查 B 的报修返回空或拒绝待填批量录入一次提交 50 条成功数 失败明细准确待填重复提交快速点两次提交只生成一条记录待填图片展示上传后隔天再看正常显示不裂图待填答辩技巧上别一上来讲技术栈先放一张「改造前 vs 改造后」的流程对比改造前新生分床靠 Excel 传三份名单改造后扫码查房、宿管端一键分配、状态实时可见。评委记住的是问题被解决的样子不是你用了哪个 API。被问到「为什么不用原生 App」时答「学生零安装成本、宿管在微信里就能审批、开发调试链路短」三点落到场景上比背技术对比表管用。从那以后我每次带这类项目验收前都强制自己用两个不同角色的账号把全链路走一遍哪怕功能昨天刚测过——因为权限和数据隔离的坑永远藏在「换个身份再看一眼」的地方。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站