宿舍的空调闹罢工,你一般找谁?宿管阿姨让你填张纸质报修单,一周过去毫无音讯;维修电话打过去永远占线;在年级群吼一声,回复全是"同求"。我当初定毕业设计题目的时候,在几个高校的后勤群里蹲了几天,发现"电器报修"这件事几乎是所有在校生的日常痛点,但绝大多数学校还在用十年前的老办法处理。这让我最终把题目定在了"基于微信小程序的高校电器维修服务",并且用原生小程序加云开发把整个系统完整跑通了一遍。
这篇文章适合正在纠结毕设选题的计算机相关专业学生,也适合想快速落地一个"用户端+业务端+管理端"三端项目的同学。我会把这个题目从选题动机、数据库建模、核心功能实现、工单状态机设计、消息触达、权限安全到论文答辩的完整链路讲一遍,同时把开发过程中真正卡过我的几个问题也一并写出来,希望能帮你少走冤枉路。全程没有晦涩的理论,全是可落地的代码逻辑和真实踩坑经验。
1. 选题的底层逻辑:为什么"高校电器维修"是性价比极高的毕设方向
1.1 高校场景里的真实痛点
做毕设最怕什么?最怕选一个"看起来高大上、实际无从下手"的题目。反过来说,一个合适的毕设题应该满足两个条件:第一,场景真实存在,你能讲清楚需求;第二,业务边界清晰,你知道做到哪算完。
高校电器维修恰好同时满足这两点。校园里的报修场景几乎是所有学生都经历过的:灯管坏了找谁换、空调不制冷该报哪个部门、洗衣机漏水了要填纸质表格还是打电话。传统流程的问题很明显:
- 报修渠道落后,纸质登记单容易丢,电话高峰期打不进去;
- 进度完全黑盒,学生不知道师傅有没有来、排到什么时候;
- 维修人员靠人工记录任务,排班和接单全凭感觉;
- 没有评价反馈机制,服务质量好坏无人过问;
- 管理员想统计数据(哪栋楼报修最多、哪类故障最频繁)全靠手工整理。
这个题目的好处在于,它不是一个虚构的电商demo,而是有一个真实角色链条——学生要找人修,维修工要干活,管理员要管人管数据。每个角色都有明确的任务,自然就映射成小程序里的三类用户端,业务闭环非常完整。
1.2 从毕设评分视角看这个题目的价值
站在答辩老师的角度看,一个毕设项目好不好,不外乎看几点:功能完整性、技术合理性、逻辑严谨度、界面可用性。高校电器维修服务在这些维度上都比较容易拿分。
功能完整性方面,它天然包含三个角色端:学生端完成报修、查进度、评价;维修工端完成接单、更新状态、完工;管理端完成工单监管、人员管理、统计汇总。一个系统里同时出现三种不同的权限视图,这在毕设里属于"结构很完整"的类型,比单纯做个点餐小程序要饱满得多。
技术合理性方面,微信小程序本身就是当前移动端轻量应用的典型形态。前端不用赘述,后端无论是用云开发还是自己搭服务器,都有充分的理由可以写进论文。更关键的是题目里有一个"维修工单状态流转"的业务核心,这里面涉及状态机设计、超时规则、权限校验,是很好的技术论述点。
我记得开题答辩时老师问我的第一句话就是:"你这个和校园报修公众号有什么区别?"这个问题其实很好回答——公众号是单向通知,没法做复杂的角色交互和工单流转;小程序是完整的业务系统,有账号体系、有路径管理、有数据承载。反而因为这一问,让我把选题的差异化想得更清楚了。
1.3 功能边界划定:别让毕设失控
很多同学做毕设容易陷入一个误区:需求越加越多,最后做不完。高校电器维修这个方向虽然场景清晰,但如果不划边界,同样会失控。
我给自己定的MVP范围是这样的:核心功能只有四个——提交报修、维修接单、进度跟踪、完工评价。在此基础上加一个必要的管理后台功能(数据看板、维修人员管理)。什么在线支付、耗材库存、多校区轮转、语音描述故障,这些一律砍掉,留到"展望"里写。
事实证明这个决定非常正确。毕设评审更看重"你把该做的事情做到什么程度",而不是"你铺了多大的摊子"。一个小而完整、闭环清晰、代码能跑、逻辑自洽的维修系统,远比一个界面华丽但流程残缺的产品要稳得多。
2. 技术选型与整体架构:原生小程序搭配云开发,一台电脑玩转全栈
2.1 为什么选原生小程序而不是uni-app
技术选型是每个毕设都要面对的第一道坎。我最终选了原生微信小程序 + 微信云开发,没有用uni-app,也没有自己搭Java后端。
uni-app确实很流行,一套代码多端复用,听起来效率很高。但它本质上是把Vue语法编译成各端代码,中间多了一层封装。对于毕设来说,封装带来的问题是:一旦页面出现诡异bug,你要么去查uniapp的文档,要么去查微信小程序原生机制,问题被架在两层之间,排错成本很高。而原生小程序出了问题直接在开发者工具里调试,报错信息直观,和官方文档一一对应,对第一次做完整项目的学生来说友好很多。
另外还有一个很现实的因素:毕设源码交付后,老师或者学弟学妹会拿你的代码去复现。原生小程序项目的目录结构一目了然,pages底下就是页面,utils下面是工具函数,cloudfunctions里是云函数。别人拿到手打开微信开发者工具就能跑,不需要先安装Node依赖、再配置打包环境。这种"打开即用"的体验,在展示和验收环节非常重要。
2.2 云开发解决了什么问题
说句实在话,很多本科毕设的瓶颈根本不在代码逻辑,而在部署环境。以前做小程序要自己租服务器、买域名、配HTTPS证书、部署后端接口,光环境搭建就劝退一拨人。
微信云开发把这一整套都简化了。它提供了三件套:
- 云数据库:直接存JSON文档,不用写SQL建表;
- 云存储:存放报修图片、文件,返回fileID直接在小程序里用;
- 云函数:写Node.js代码跑在后端,自动获取用户openid,天然可信。
对我这种主要精力要放在业务功能上的毕设选手来说,云开发最大的价值是"免运维"。我不用半夜还在折腾服务器环境变量,不用处理跨域问题,前端通过wx.cloud调用云函数,数据就来了。整条链路简单到可以画成一张图:小程序页面 -> 云函数 -> 云数据库,没有多余的中间环节。
2.3 项目整体目录结构
我的项目目录长这样,所有源码和文档都在一个工程里:
miniprogram/ ├── pages/ │ ├── index/ // 首页/报修入口 │ ├── order-list/ // 工单列表(学生端/维修工公共用) │ ├── order-detail/ // 工单详情 │ ├── repair-submit/ // 提交报修 │ ├── worker-todo/ // 维修工今日任务 │ ├── admin-board/ // 管理端看板 │ ├── profile/ // 个人中心 │ └── login/ // 登录注册 ├── components/ │ ├── status-timeline/ // 进度时间线组件 │ └── picker-location/ // 楼栋选择器 ├── utils/ │ └── request.js // 封装云函数调用 └── cloudfunctions/ ├── login/ // 登录获取openid与角色 ├── submitOrder/ // 提交报修 ├── acceptOrder/ // 接单 ├── updateOrderStatus/ // 更新状态 ├── checkOverdue/ // 定时检查超时 └── statsDashboard/ // 管理端统计这个结构有一个好处:页面组件基本一一对应业务功能,写论文的时候画系统结构图,直接从目录里抄就行。
3. 数据库设计:一张维修工单,串起学生、维修工、管理员三类角色
3.1 核心集合与字段
云开发是文档型数据库,不需要建表,但集合设计和字段规划依然非常重要。我的数据库里一共建了四个核心集合:users、orders、evaluations、notices。
users集合存用户基础信息和角色:
{ _id: "auto", _openid: "用户唯一openid", role: "student", // student / worker / admin studentId: "20210001", // 学号或工号 name: "张三", phone: "13800138000", dorm: "3栋2单元501", // 报修常用地址 createdAt: "2024-03-10 15:00:00" }orders集合是整张系统的核心:
{ _id: "order20240310xxxx", _openid: "报修学生openid", orderNo: "BX20240310001", deviceType: "空调", // 空调/照明/热水器/洗衣机/其他 location: "3栋2单元501", description: "空调不制冷,开机半小时仍是热风", images: ["cloud://xxx/repair/111.jpg"], status: "pending", // pending/accepted/processing/completed/evaluated/cancelled workerOpenid: "", // 接单维修工openid workerName: "李师傅", createdAt: "2024-03-10 15:00:00", acceptedAt: "", completedAt: "" }evaluations集合存学生对工单的评价:
{ _id: "auto", orderId: "order20240310xxxx", _openid: "评卷学生openid", rating: 5, // 1-5星 comment: "师傅半小时就来了,修得很仔细", createdAt: "2024-03-10 16:00:00" }notices集合留消息记录存档,方便论文里写"系统消息记录"功能。
3.2 集合之间的关联关系
文档数据库虽然没有外键,但依然要用字段做关联。我的关联逻辑是:
- 一个学生可以有多条工单,
orders._openid指向users._openid; - 一条工单对应一条评价,
evaluations.orderId指向orders._id; - 维修工通过
orders.workerOpenid知道哪些工单是自己的; - 管理员通过查询
orders集合聚合统计数据。
这里有个小技巧:查询工单列表时,与其在代码里二次查users集合拿到学生姓名和宿舍号,不如在提交报修时就把studentName、studentPhone、location冗余到orders文档里。这样列表页排序、搜索直接查orders就够了,不用做关联查询。文档型数据库里适当冗余字段是非常实用的做法,不要照搬关系型数据库的"三范式"思维。
3.3 权限视角下的数据隔离
数据库设计阶段就要考虑一个问题:学生能不能看到别人的工单?维修工能不能看到所有维修单?答案是都不能。
云开发数据库支持安全规则配置。我的做法是:集合访问权限设为"仅创建者可读写"(即只有_openid匹配的记录),同时在云函数中做二次校验。比如学生只能查orders._openid == 自己openid的记录,维修工只能查workerOpenid == 自己openid的记录,管理员拥有全表查询权限。这类规则既要落在数据库权限配置里,也要落在每个云函数的查询条件里。
4. 核心功能闭环拆解:从提交报修到完工评价,每个环节怎么落地
4.1 报修表单的设计与交互
报修是系统的入口,表单设计直接决定数据质量。我走的是"分类选择 + 楼栋定位 + 描述 + 拍照 + 联系方式"的常规组合。
设备类型用picker选择器,把空调、照明、热水器、洗衣机、其他这五类固定为选项,方便后头做统计。楼栋和宿舍号单独设字段,学生可以输入,也可以用picker记忆常用地址。故障描述给一个textarea,我特意加了一个提示文字:"请说明故障表现,例如'空调不制冷,开机半小时仍是热风',方便维修师傅带齐工具。"
图片上传这里有一个容易忽略的点:微信小程序的wx.chooseMedia拿到的是本地临时路径(tempFilePath),这个路径只在本次会话有效。必须先把图片上传到云存储拿fileID,再把fileID存进数据库。上传云存储的代码很简单:
const res = await wx.cloud.uploadFile({ cloudPath: `repair/${Date.now()}-${Math.random().toString(36).slice(2)}.jpg`, filePath: tempFilePath }); // res.fileID 存入 orders.images提交按钮点击后,调用submitOrder云函数,把表单数据写入orders集合,状态初始化为pending。这里还有一个关键点:提交完成后立刻引导用户订阅消息(后面第6章细说),这是整个用户体验链路设计的一部分。
4.2 维修工端的工作台
维修工登录后进入的是完全不同的界面,我把它叫做"工作台"。核心是两个列表:
- 待接单工单:状态为
pending的工单,展示设备类型、故障描述、楼栋、提交时间。维修工点击接单,调用acceptOrder云函数,将工单状态改为accepted,同时把workerOpenid和workerName写入工单。 - 我的工单:分"进行中"和"已完成"两个页签。进行中工单可以点击"开始维修"(状态变
processing)、"完成维修"(状态变completed),并填写维修结论和使用的耗材备注。
这里有个很有意思的业务细节:我最初设计的是"管理员派单",就是管理员在后台把工单指派给某个维修工。后来发现现实场景里维修工数量少、区域划分明确,"接单模式"反而更高效。我干脆两种模式都支持:维修工可以主动抢单,管理员也可以在后台手动改派。这个设计在论文里可以直接写成"分布式自主接单与集中调度的混合模式",听起来也像回事。
4.3 学生端的进度时间线与评价
学生提交报修后,最关心的就是"修到哪一步了"。工单详情页我用了一个自制的status-timeline组件,把状态映射成四条节点线:提交报修 -> 维修工接单 -> 维修中 -> 已完成。
时间线组件渲染逻辑非常简单,根据orders.status字段点亮对应的节点:
const statusMap = { pending: ['active', '', '', ''], accepted: ['done', 'active', '', ''], processing: ['done', 'done', 'active', ''], completed: ['done', 'done', 'done', 'active'] };状态变到completed之后,学生端的详情页会弹出一个评价入口,调用evaluateOrder云函数,写入evaluations集合,同时把工单状态改为evaluated,整个业务闭环就此完成。这里评价入口只对报修学生本人开放,维修工和管理员都看不到,逻辑上很好控制。
4.4 管理端的看板与人员管理
管理员端是整个系统的"总控室"。我实现了三项核心能力:
- 工单总览:全部工单按状态分组展示,支持按楼栋、设备类型、时间范围筛选。管理员可以查看一条工单的完整时间线,也可以手动修改状态(比如学生误报时置为取消)。
- 人员管理:管理员可以给新入职的维修工分配账号,把某个
users文档的role改成worker。学生账号和维修工账号不做复杂的审批流,一切由管理员在配置页处理。 - 统计看板:聚合显示本周报修数、待处理数、平均完工时长、各设备类型占比。这些统计全部由
statsDashboard云函数用聚合查询算出来,前端用简单的表格和数字卡片展示。
我强烈建议统计看板不要用复杂的图表库,微信小程序里拉一个ECharts或者mpvue图表库会增加不少体积和适配成本。数字卡片加简单的CSS条形图,效果完全够看,而且加载快。
5. 工单状态机的约束设计:状态迁移、超时处理与自动流转
5.1 状态定义与流转规则
工单是这个系统的灵魂,而工单的灵魂是状态机。我定义的状态和流转规则如下:
| 当前状态 | 执行角色 | 允许动作 | 下一状态 |
|---|---|---|---|
| pending(待接单) | 维修工 | 接单 | accepted |
| pending(待接单) | 学生/管理员 | 取消 | cancelled |
| accepted(已接单) | 维修工 | 开始维修 | processing |
| accepted(已接单) | 管理员 | 改派 | 重新指派到pending |
| processing(维修中) | 维修工 | 完成维修 | completed |
| completed(已完成) | 学生 | 评价 | evaluated |
| completed(已完成) | 学生/管理员 | 未评价超过N天 | evaluated(自动) |
这个表格本身就是论文里最直观的一张插图。它告诉了每一方角色:你当前能做什么、不能做什么。所有状态迁移都必须经过云函数校验,前端随意改数据是改不动的。
5.2 状态迁移的合法性校验
云函数里对状态迁移做校验是我认为整个项目最应该认真写的地方。以"接单"为例:
// acceptOrder/index.js const cloud = require('wx-server-sdk'); cloud.init(); const db = cloud.database(); exports.main = async (event) => { const wxContext = cloud.getWXContext(); const { orderId } = event; // 先查工单 const orderRes = await db.collection('orders').doc(orderId).get(); const order = orderRes.data; // 校验状态:只有pending才能接单 if (order.status !== 'pending') { return { code: 400, msg: '该工单已被接单或取消' }; } // 校验角色:必须是维修工 const userRes = await db.collection('users').where({ _openid: wxContext.OPENID }).get(); const user = userRes.data[0]; if (!user || user.role !== 'worker') { return { code: 401, msg: '没有接单权限' }; } // 更新工单 await db.collection('orders').doc(orderId).update({ data: { status: 'accepted', workerOpenid: wxContext.OPENID, workerName: user.name, acceptedAt: db.serverDate() } }); return { code: 0, msg: '接单成功' }; };注意我用了db.serverDate(),这样时间以服务器时间为准,避免用户手机时间错乱导致数据标注错误。这是开发中很基础但很多人忽略的点。
5.3 超时未接单、维修超时的自动处理
状态机如果不加时间约束,系统就会变成一个"永远无人处理的僵尸工单集合"。超时处理是运维质量的重要一环。
我做了两个定时任务:
- 每30分钟检查一次待接单工单:如果提交超过2小时仍然
pending,云函数自动把工单状态改为cancelled,同时生成一条通知记录,提醒管理员人工介入; - 每天检查一次维修中工单:如果
acceptedAt超过24小时仍未completed,自动通知维修工和管理员超时提醒。
这两个逻辑都写在checkOverdue云函数里,用微信云开发的定时触发器调度。配置在云函数的config.json中:
{ "permissions": { "openapi": [] }, "triggers": [ { "name": "checkPendingOrderTimer", "type": "timer", "config": "0 0/30 * * * * *" }, { "name": "checkProcessingOverdueTimer", "type": "timer", "config": "0 0 0 * * * *" } ] }这里要特别提醒一句:微信云开发的cron表达式是7位的,从秒开始。我第一次用的时候按网上常见的6位cron写,结果定时器怎么都不触发,排查了好久才发现是格式问题。"0 0/30 * * * * *"表示每30分钟触发一次,"0 0 0 * * * *"表示每天0点触发。这算是一个非常隐蔽的坑,后面踩坑章我会再提一次。
6. 进度触达方案:订阅消息的授权机制与推送节奏
6.1 一次性订阅消息的特性
做小程序的人都知道,微信的订阅消息是"一次授权,一次推送"。用户点击授权订阅某个模板后,你只能给他推送一条对应的消息。想让用户再次接收通知,他必须再次点击授权。
这带来的直接影响是:推送时机必须掐准。不能指望用户一次性订阅后长期收到推送,只能"用一次授权,换一次通知"。所以在业务设计里,我把订阅消息和具体业务动作绑定在一起:
- 提交报修成功后,引导用户订阅"维修进度通知",当维修工接单或完工时,就能向学生推一条消息;
- 维修工接单成功后,引导维修工订阅"新工单提醒"和"超时提醒"。
6.2 合适的订阅时机
订阅时机设计得好不好,直接关系到推送的送达率。我的做法是在用户刚完成某个动作的"顺水推舟"窗口里弹授权:
提交报修成功页,弹窗文字是"维修师傅接单或完工时将通知你",用户点"允许"后,保存订阅授权记录。这一步顺理成章,用户没有被打断的厌烦感,订阅率会高很多。
云函数里发推送的代码走的是微信开放接口:
await cloud.openapi.subscribeMessage.send({ touser: studentOpenid, templateId: '模板ID', page: 'pages/order-detail/order-detail?id=' + orderId, data: { thing1: { value: order.deviceType }, thing2: { value: '维修已完成,请查看详情' }, time3: { value: new Date().toLocaleString() } } });调试时如果发现发不出去,先检查:模板ID有没有匹配、用户是否授权过、云函数是否开通了该API权限。这三个挨个查,基本能解决九成问题。
6.3 推送节奏与用户骚扰控制
推送不是越勤越好。完工时推一条、接单时推一条,最多再加一条超时催办,学生能及时掌握状态即可。不要设计成"每一步状态变化都推送",会让用户觉得烦,也容易超出模板的推送配额限制。
这里我还做了一个体验优化:当维修工接单并开始维修时,只推送一次"已接单,请留意进度",而不是接单推一次、开始维修又推一次。把信息合并,尊重用户注意力,这个原则在毕设答辩中也会被老师认可。
7. 权限与安全:三类角色同一小程序里的数据隔离
7.1 登录与角色判定
小程序登录不需要自己做账号密码体系,核心是用微信的wx.login获取code,然后在云函数里用cloud.getWXContext()拿到用户的openid。openid是用户在当前小程序下的唯一身份标识,永远可信,不能伪造。
用户第一次登录时,我在login云函数里根据openid去users集合查记录,查不到就创建一条新用户,默认角色是student。管理员账号和维修工账号怎么来呢?我在代码里留了一个"初始管理员凭据"的逻辑:用一个固定的管理员openid做初始化判断,或者提供"管理员申请码"让第一个注册用户输入后升级为admin。
这里有个细节值得注意:角色判断不要只在前端做。前端按钮可以隐藏,但云函数必须再查一次角色。因为小程序前端代码可以被逆向、可以伪造调用,真正可靠的是云函数里getWXContext().OPENID对应的用户身份。
7.2 数据库规则与云函数校内校验
云开发数据库默认的权限设置是"仅创建者可读写",这对orders、evaluations这些敏感集合是合理的。但是全部依赖这条规则也不够,因为维修工要改的不是自己创建的工单。所以我的设计原则是:
- 前端能直接读的数据,都是不敏感的公共数据(如设备类型字典、公共公告);
- 所有涉及业务状态修改的操作,一律走云函数;
- 云函数里统一做身份校验、角色校验、状态校验三步,缺一不可。
以"更新工单状态"为例,云函数里执行流程是:先取openid -> 查用户角色 -> 查工单归属 -> 校验状态迁移是否合法 -> 执行更新。每一步失败都直接返回错误码,不会把不安全的操作漏到数据库层。
7.3 常见的越权风险与防护
这类系统最常见的越权问题有几种,我整理成表格,方便你对照检查自己的代码:
| 风险场景 | 原因 | 防护做法 |
|---|---|---|
| 学生A调接口改学生B的工单状态 | 前端只校验了登录态,没校验归属 | 云函数中查order._openid必须等于当前openid |
| 学生伪造维修工身份操作 | 角色写在前端 | 云函数中从数据库重新查角色 |
| 维修工查看所有学生隐私信息 | 列表查询条件不严 | 维修工只能查workerOpenid等于自己openid的工单 |
| 超管功能被普通用户调用 | 管理端页面隐藏但接口仍开放 | 管理云函数必须校验role==='admin' |
写云函数时把这些校验当成"默认必须做"的环节,而不是可选项。这样不仅系统安全,论文里也可以专门写一章"系统安全性与权限控制设计",又是实打实的评分点。
8. 开发过程中踩过的五个大坑:都是真问题,不是理论
8.1 手机号获取的坑:个人主体小程序拿不到手机号
最初我把报修表单里的联系方式设计成"点击按钮一键获取微信手机号",用的是button的open-type="getPhoneNumber"。结果真机一测,接口返回错误,提示当前小程序没有该接口权限。
查了半天才弄明白:微信的"手机号快速验证组件"要求小程序必须完成微信认证,且主体一般是企业、政府、媒体等非个人类型。个人主体注册的小程序无法使用这个能力。很多毕设账号都是用个人身份证注册的,所以我果断把方案改成了"学号/用户名 + 密码 + 手机号手动输入"的常规登录注册。这样虽然少了"一键获取"的炫酷感,但至少功能可用、流程完整,不会卡在资质上。
8.2 报修图片临时路径过期
第二次被坑是在图片上传环节。wx.chooseMedia返回的临时路径,第一次真机调试时,我把它直接存入了数据库。学生提交报修后,图片能正常显示;过了几小时再打开工单详情,图片全红了。
原因是临时文件路径有效期很短(过期后无法访问),只有把图片上传到云存储拿到fileID才持久可用。用fileID在image标签的src里可以直接显示,不需要额外转临时链接。这一点在开发者工具模拟器里通常不会暴露,因为模拟器的会话上下文一直存在,真机过段时间再看才明显。所以做这类毕设,真机联调一定要早做也要勤做。
8.3 云函数默认超时时间不够
云开发新创建的云函数默认超时时间是3秒(有些环境默认20秒)。我的statsDashboard云函数在数据量小的时候跑得飞快,但管理员点开统计看板时,有一次直接报Function timed out。
排查后发现,统计云函数里有好几个await串行查询,数据多了自然变慢。解决办法有两个:一是把超时时间在上传配置里改到20秒甚至60秒;二是优化云函数内部逻辑,比如用Promise.all并行查询、尽量减少重复查询。这两个办法我都用了,效果很好。如果你也做统计类功能,一定要记得改云函数超时配置。
8.4 定时触发器的cron格式
这个我在第5章提过一嘴,但值得在踩坑章再强调一遍。微信云开发的定时触发器cron格式是"秒 分 时 日 月 星期"的7位格式,跟Linux crontab的5位格式完全不一样。我第一次照着Linux习惯写了0 */30 * * * *,结果控制台创建触发器时直接报格式错误。
正确写法是0 0/30 * * * * *。多一个字段,语义差很多。而且云的定时触发器部署后,修改配置需要重新上传云函数才会生效,这个也很容易让人误以为"配置没保存上"。
8.5 tabBar页面不能带参数跳转
学生端我设置了底部tabBar,包含"首页、工单、我的"三个页面。一开始我从工单列表跳转详情页时,直接写了:
wx.navigateTo({ url: '/pages/order-detail/order-detail?id=xxx' });这个没问题。但有一次我从详情页想跳到"首页"并携带一个参数过去,用wx.switchTab带了query,结果参数直接丢失。这个在小程序里是明规则:switchTab不支持带参数。
解决方案很简单:跳tabBar页面前先把参数存到全局变量或storage,目标页面在onShow中读取。或者改用wx.reLaunch,它可以带参数跳转任意页面,包括tabBar页。
9. 论文写作与答辩展示:把毕设讲成完整项目
9.1 论文结构建议
代码写完了,论文是这个项目的最后一道大关。我建议论文结构按以下骨架展开,和大多数本科毕设论文模板吻合,写起来不费劲:
- 第一章 绪论:写背景和意义、国内外研究现状。述你要说"校园后勤数字化"这个大背景,然后收敛到"高校电器维修服务"这个具体场景。
- 第二章 需求分析:分角色写功能性需求(学生、维修工、管理员),再写非功能性需求(安全、性能、可用性)。
- 第三章 系统设计:总体架构、技术选型、数据库设计、功能模块设计、状态机设计。这一章放第5章的表格,非常加分。
- 第四章 系统实现:按功能模块贴关键代码,辅以运行截图。注意只贴核心逻辑,不要堆全部代码。
- 第五章 系统测试:写功能测试用例表和结果,再加上一些性能测试、兼容性测试(不同机型跑一遍)。
- 第六章 总结与展望。
论文的核心是在"需求分析"和"系统设计"两章,要把业务逻辑讲清楚,不要一篇论文三分之二都在贴代码。老师评审时最想看到的是"你有没有把业务问题想明白、能不能把业务需求转成技术方案"。
9.2 图表和截图素材积累
写论文时最痛苦的是临到用时才发现没截图。我建议开发过程中就随手积累素材:
- 每个功能模块完成后,立刻截图,存到一个
docs/imgs文件夹里,按模块命名; - 画一张系统用例图(E-R图和用例图用Visio或者Draw.io都行);
- 画一张系统架构图(前端、云函数、云数据库三层);
- 把工单状态流转表做成一张规范的表格或者流程图。
我踩过的教训是:前期没留截图,后期补的时候系统数据已经变了,很多界面状态(比如空数据、超时取消)很难再造出来。补截图的过程比做功能还磨人。你从开发第一天就顺手截图,后面写论文能省一半时间。
9.3 答辩高频问题与应对思路
我答辩时被问到的问题,几乎可以提前预判:
- 为什么用云开发而不用传统服务器?答:云开发免运维、原生集成小程序鉴权、支持云函数冷热部署,适合快速验证业务逻辑,且openid天然不可伪造,安全模型简单清晰。
- 报修高峰期并发怎么办?答:云函数按量扩容,数据库走文档型并发读;另外可以加简单的提交频率限制,防止刷单。
- 状态机是怎么设计的?答:展示状态迁移表格,强调每个迁移动作都要做角色+状态双重校验。
- 维修工恶意抢单怎么约束?答:前端限制可见列表 + 云函数记录操作日志 + 管理员可以改派和取消,系统留了人工干预通道。
- 这个系统真实部署过吗?答:在微信开发者工具和真机上跑通了完整流程,可以现场演示。这句话最有说服力。
答辩的核心不是背稿,而是要让老师感觉到"你是真的做过一遍的人"。你踩过的坑、做过的取舍、想过的优化方向,都比纸面上的概念更能打动评审老师。
最后:给拿到源码的同学三条实用建议
如果你准备直接以这份源码为基础做自己的毕设,或者只是参考这个项目逻辑,我有三条建议。
第一,拿到代码后先不要改功能,先在微信开发者工具里导入整个工程,配好自己的云开发环境ID,把云函数全部上传,跑通一条"提交报修 -> 接单 -> 完成 -> 评价"的完整链路。很多同学一上来就改前端页面,结果数据全乱,反而花更久时间。
第二,把地点和场景改成你自己学校的真实数据:楼栋名称、宿舍编号、常见故障类型。这些数据是写需求分析时的素材,"来源于真实需求"是最能打动答辩老师的。
第三,答辩演示时按"学生视角 -> 维修工视角 -> 管理员视角"的顺序走,每个角色只演示核心闭环,不要点开各种边角页面。演示的流畅程度,往往比系统本身更能决定印象分。
高校电器维修服务这个题目给我最大的体会是:毕设项目的成败,不取决于技术栈多新、架构多复杂,而取决于"你把这个场景里的问题想得多透"。只要业务闭环完整、代码规范、逻辑经得起追问,它就是一个扎实的毕设。希望这篇分享能帮你少走点弯路,顺利拿下自己的毕设。