十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

微信小程序毕业设计实战:自律学习打卡系统与云开发部署

微信小程序毕业设计实战:自律学习打卡系统与云开发部署 毕业设计自律学习小程序功能拆解、云开发部署与常见问题排查第一次做微信小程序毕业设计最怕的不是功能写不出来而是做完之后不知道怎么演示、怎么讲、怎么应对老师提问。这次我们来看一个很常见的毕业设计选题——自律学习小程序。这类项目题材贴近实际需求功能边界清晰又能覆盖用户登录、云数据库、定时提醒、数据统计这些高频技术点用来做毕设演示非常合适。我按“功能拆解 - 环境准备 - 云开发部署 - 核心功能实现 - 效果验证 - 常见问题 - 答辩建议”的顺序来写。这篇文章不是教你怎么堆功能而是给你一套能跑通、能演示、能讲清楚的完整方案。如果你现在正在选题阶段或者已经选了类似题目但代码还没头绪可以直接参考这套思路。1. 自律学习小程序核心能力速览能力项说明项目类型微信小程序原生项目 微信云开发适合角色大学生毕业设计、小程序入门实战、全栈练习核心功能学习打卡、任务清单、专注计时、学习统计、用户排行用户体系微信登录与用户信息授权数据存储云开发数据库、云存储后端方案云函数 云数据库无需自建服务器部署方式微信开发者工具上传云开发环境一键开通学习成本熟悉 JavaScript 基础即可前后端同构演示亮点打卡闭环 定时订阅消息 可视化统计商业边界个人开发可使用商用需注意用户隐私与合规要求这套技术栈最大的优势是省掉了服务器购买、接口部署和域名备案微信生态内部就能完成从开发到上线的全部流程。对毕设来说这能让你把精力集中在业务逻辑和页面实现上而不是花大量时间配置后端环境。2. 适用场景与使用边界自律学习小程序适合这几类用户准备考研、考公、英语打卡的学习者需要每日签到、任务规划和专注计时。需要做学习数据复盘的用户查看周学习时长、连续打卡天数、任务完成率。毕业设计选型阶段的学生小程序开发周期可控功能可扩展性强答辩演示方便。使用边界要先讲清楚微信登录获取用户信息的能力在持续收紧。新版小程序不再推荐直接调用getUserInfo弹窗获取头像昵称而是改用头像昵称填写能力代码实现上要做适配。涉及用户数据的功能必须在隐私协议中明确说明采集了哪些信息、如何存储、是否提供删除入口。定时提醒依赖微信订阅消息订阅消息是一次性的用户每同意一次只能收到一次通知不能像服务号模板消息那样反复触达。学习打卡数据属于用户个人数据应只允许本人查看和修改云数据库权限要按“仅创建者可读写”配置。3. 环境准备与前置条件3.1 开发环境开始之前先确认工具链工具用途说明微信开发者工具小程序编码、调试、上传建议使用稳定版微信小程序账号获取 AppID使用测试号也可但云开发需要正式账号Node.js云函数本地调试需要本机安装建议 LTS 版本基础库版本支持组件与 API建议在调试器里把调试基础库设为最新稳定版如果你已经装了 HBuilder X 并且熟悉 uni-app也可以用 uni-app 来做这套系统。但这里我按微信原生小程序来写因为毕设答辩时老师更关心你对微信生态的理解原生框架出问题好排查遇到报错网上的解决方案也最多。3.2 开通云开发用原生小程序做云开发是当前比较省事的路径。首次打开微信开发者工具导入项目后点击工具栏上的“云开发”按钮按提示开通云环境即可。云开发会提供云数据库存放用户、打卡、任务、专注记录云存储存放用户上传的图片例如打卡配图、头像云函数处理需要服务端逻辑的业务例如生成统计报表、下发订阅消息3.3 项目目录规划建议目录结构如下├── cloudfunctions/ # 云函数目录 │ ├── login/ # 登录初始化 │ ├── checkIn/ # 打卡提交 │ ├── getStatistics/ # 学习统计 │ └── sendRemind/ # 订阅消息推送 ├── miniprogram/ │ ├── pages/ │ │ ├── index/ # 首页打卡计时入口 │ │ ├── task/ # 任务清单 │ │ ├── stats/ # 学习统计 │ │ └── profile/ # 个人中心 │ ├── components/ # 自定义组件 │ ├── utils/ # 工具函数 │ ├── app.js │ ├── app.json │ └── app.wxss └── project.config.json4. 小程序页面设计与功能拆解自律学习小程序通常包含 4 个主页面每个页面承担明确的用户任务。4.1 首页打卡与专注计时首页是用户打开小程序最先看到的界面。核心元素包括今日打卡状态已完成 / 未完成连续打卡天数今日学习时长开始专注按钮打卡逻辑在云函数中完成。用户点击打卡后云函数负责检查是否已打卡、写入打卡记录、更新连续天数。连续天数的计算不能在客户端做因为客户端时间可以被修改必须依赖云函数端的时间戳。4.2 任务清单学习计划管理任务清单页面需要支持新增任务编辑任务名称与计划时间将任务标记为完成删除任务任务数据存在云数据库tasks集合中每条任务记录包含{ _id: 自动生成, _openid: 用户openid, title: 完成英语真题第一套, planTime: 2027-06-10 20:00, status: pending, createTime: 1739000000000 }4.3 统计页面可视化学习成果统计页面是答辩展示的加分项。可以用微信小程序原生ec-canvas图表组件也可以自己用 canvas 画进度环和柱状图。建议展示的数据最近 7 天学习时长今日完成任务数累计打卡天数各科目学习时长占比4.4 个人中心用户信息与隐私管理个人中心处理用户头像昵称展示、授权设置、关于页面、隐私协议入口。这里要注意头像昵称的获取方式不再推荐直接弹出授权框而是提供一个按钮让用户主动填写昵称、主动选择头像。这样既能满足小程序审核要求也方便用户控制自己的隐私。5. 云开发数据库设计数据库是整个小程序的核心。建议创建以下集合集合名字段说明usersopenid, nickName, avatarUrl, checkInDays, totalTime用户基础信息checkinsopenid, date, time, type打卡记录按日期唯一tasksopenid, title, planTime, status, createTime学习任务focus_recordsopenid, startTime, endTime, duration, subject专注记录集合名称可自定义但要注意云数据库的权限设置。users、checkins、tasks、focus_records都应设置为“仅创建者可读写”防止一个用户读到另一个用户的记录。如果要做排行榜则需要单独创建云函数由云函数端汇总数据后返回不能直接把全量数据下发到客户端。6. 核心功能实现与代码示例6.1 云开发初始化app.js中初始化云开发App({ onLaunch() { if (!wx.cloud) { console.error(请使用 2.2.3 或以上的基础库以使用云能力); } else { wx.cloud.init({ env: 你的云环境ID, traceUser: true }); } } });6.2 微信登录与用户信息处理登录在云函数中完成。云函数端可以获取用户 openid不需要客户端手动调用wx.login再换 code。// cloudfunctions/login/index.js const cloud require(wx-server-sdk); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); const db cloud.database(); exports.main async (event, context) { const { OPENID } cloud.getWXContext(); const userCollection db.collection(users); const user await userCollection.where({ _openid: OPENID }).get(); if (user.data.length 0) { return { code: 0, data: user.data[0] }; } const newUser { _openid: OPENID, nickName: 微信用户, avatarUrl: , checkInDays: 0, totalTime: 0, createTime: Date.now() }; const res await userCollection.add({ data: newUser }); return { code: 0, data: { _id: res._id, ...newUser } }; };客户端调用云函数登录wx.cloud.callFunction({ name: login, success(res) { console.log(登录成功, res.result); this.setData({ userInfo: res.result.data }); }, fail(err) { console.error(登录失败, err); } });这里要特别提醒创建用户记录时不要把_openid手动写入参数云开发在添加记录时会自动注入_openid字段。云函数内cloud.getWXContext()拿到的OPENID主要用于查询判断不是手动写入数据库的字段。6.3 学习打卡实现打卡需要处理重复提交和连续天数计算。下面是一个标准实现// cloudfunctions/checkIn/index.js const cloud require(wx-server-sdk); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); const db cloud.database(); exports.main async (event, context) { const { OPENID } cloud.getWXContext(); const today new Date(); const dateStr ${today.getFullYear()}-${today.getMonth() 1}-${today.getDate()}; const checkins db.collection(checkins); const existing await checkins.where({ _openid: OPENID, date: dateStr }).get(); if (existing.data.length 0) { return { code: -1, message: 今日已打卡 }; } try { await checkins.add({ data: { _openid: OPENID, date: dateStr, time: Date.now(), type: event.type || daily } }); const users db.collection(users); const userRes await users.where({ _openid: OPENID }).get(); if (userRes.data.length 0) { const user userRes.data[0]; let days user.checkInDays || 0; const lastCheckTime user.lastCheckTime || 0; const diffDay Math.floor((today.getTime() - lastCheckTime) / (24 * 60 * 60 * 1000)); if (diffDay 1) { days 1; } else if (diffDay 1) { days 1; } else if (diffDay 0) { days days; } await users.doc(user._id).update({ data: { checkInDays: days, lastCheckTime: today.getTime() } }); } return { code: 0, message: 打卡成功 }; } catch (err) { console.error(err); return { code: -2, message: 打卡失败 }; } };6.4 专注计时功能专注计时不依赖后端也能实现。启动时记录startTime结束时上传duration到云数据库。为了避免小程序切后台导致计时不准推荐使用时间戳差值计算而不是用setInterval一直累加。开始专注startFocus() { this.setData({ focusStartTime: Date.now(), isFocusing: true }); wx.vibrateShort({ type: medium }); }结束专注async endFocus() { const endTime Date.now(); const startTime this.data.focusStartTime; const duration Math.floor((endTime - startTime) / 1000); const db wx.cloud.database(); await db.collection(focus_records).add({ data: { startTime, endTime, duration, subject: this.data.currentSubject || 未分类 } }); wx.showToast({ title: 专注 ${Math.floor(duration / 60)} 分钟, icon: success }); this.setData({ isFocusing: false }); }6.5 学习统计实现统计功能建议通过云函数聚合数据避免在客户端遍历大量记录。下面以“近 7 天学习时长”为例// cloudfunctions/getStatistics/index.js const cloud require(wx-server-sdk); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); const db cloud.database(); const $ db.command.aggregate; exports.main async (event, context) { const { OPENID } cloud.getWXContext(); const days event.days || 7; const startTime Date.now() - days * 24 * 60 * 60 * 1000; const res await db.collection(focus_records) .aggregate() .match({ _openid: OPENID, startTime: $.gte(startTime) }) .group({ _id: $.dateToString({ date: $startTime, format: %Y-%m-%d, timezone: 08:00 }), totalDuration: $.sum($duration) }) .sort({ _id: 1 }) .end(); return { code: 0, data: res.list }; };聚合是云开发比较强的能力答辩时能讲清楚match、group、sort这条链路会明显加分。6.6 订阅消息提醒订阅消息需要用户主动触发授权。在一个按钮点击回调中调用wx.requestSubscribeMessage({ tmplIds: [你的模板ID], success(res) { if (res[你的模板ID] accept) { wx.showToast({ title: 已开启提醒 }); } else { wx.showToast({ title: 未授权提醒, icon: none }); } } });需要注意如果用户拒绝过一次需要在用户再次点击时提示如何重新开启。订阅消息每次触发只能发一条如果用户每天需要多个提醒就要多次触发授权。7. 功能测试与效果验证毕业设计演示前建议按下面的测试用例逐项跑一遍测试项测试步骤预期结果是否通过登录首次打开小程序自动创建用户记录打卡点击打卡按钮提示打卡成功连续天数增加重复打卡再次点击打卡提示今日已打卡新增任务在任务页添加任务列表出现新任务完成任务勾选任务状态变为完成专注计时开始专注 1 分钟后结束统计页新增 1 分钟记录统计图表查看最近 7 天柱状图按日期展示时长订阅消息点击开启提醒弹出授权框同意后提示成功真机预览时容易出现模拟器正常但真机报错的问题。常见的net::ERR_CONNECTION_RESET多半和本地调试环境有关首次真机预览需要在手机端打开调试模式或者在开发者工具中点击“真机调试 2.0”按钮。如果云函数调用超时优先检查云开发控制台中云函数日志查看是否有权限或参数错误。8. 常见问题与排查方法这里整理毕设过程中最常遇到的几个问题很多同学卡在这些地方问题本身不复杂但不好定位。问题现象可能原因排查方式解决方案获取登录后的微信用户失败wx1cb4398e1413dce7基础库版本过低或 AppID 配置异常检查项目 AppID 与开发者工具登录状态升级调试基础库重新导入 AppID真机预览报net::ERR_CONNECTION_RESET本地服务未开启或手机与电脑不在同一网络检查真机调试设置使用“真机调试 2.0”打开调试模式获取不到用户头像昵称小程序新规下已禁用旧接口控制台查看调用报错改用头像昵称填写能力订阅消息发送失败模板 ID 填错或用户未授权查看云函数日志核对模板 ID重新触发授权云数据库权限导致数据错乱权限设置为“所有用户可读”云开发控制台安全检查修改为“仅创建者可读写”苹果手机底部安全区遮挡按钮未适配 iPhone X 系列真机预览观察添加safe-area-inset-bottom样式兼容页面无法打开公众号文章需要配置业务域名小程序后台配置把 URL 加入业务域名白名单8.1 头像昵称填写能力新版小程序推荐使用button open-typechooseAvatar获取头像配合input typenickname让用户输入昵称。这是 2022 年之后的标准方案代码示例如下button classavatar-wrapper open-typechooseAvatar bind:chooseavataronChooseAvatar image src{{avatarUrl}} modeaspectFill/image /button input typenickname placeholder请输入昵称 value{{nickName}} bindinputonNickNameInput /对应逻辑onChooseAvatar(e) { this.setData({ avatarUrl: e.detail.avatarUrl }); }, onNickNameInput(e) { this.setData({ nickName: e.detail.value }); }拿到头像临时路径后先上传到云存储再把返回的 fileID 存入数据库。直接存本地临时路径会在小程序重启后失效这一点要注意。8.2 订阅消息配置订阅消息的模板需要到微信公众平台申请审核通过后会得到一个模板 ID。调用时模板 ID 放在前端但实际推送动作在云函数端完成。云函数推送代码const cloud require(wx-server-sdk); cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); exports.main async (event, context) { const { OPENID } cloud.getWXContext(); try { const result await cloud.openapi.subscribeMessage.send({ touser: OPENID, page: pages/index/index, data: { thing1: { value: 学习打卡提醒 }, time2: { value: 2027-06-10 20:00 } }, templateId: 你的模板ID }); return { code: 0, data: result }; } catch (err) { return { code: -1, message: err.message }; } };这里thing1、time2是模板字段的 key具体以你申请的模板为准不要照抄。9. 资源占用与性能观察小程序的性能优化不像后端服务那样看显存和 CPU而是重点看这几个指标9.1 包体积控制小程序主包限制 2MB超过后无法上传。自律学习小程序页面不多代码量不大通常不会超但如果引入图表库或者较大图片容易触发限制。建议开启小程序分包{ subPackages: [ { root: pages/stats/, pages: [ stats ] } ] }统计页面放到分包中主包只保留首页、任务、个人中心。这样主包体积能控制在 1.5MB 以内。9.2 云函数性能云函数冷启动时间是不可控的做演示前先调一次所有云函数避免现场首次调用时等待 2 到 3 秒。也可以在云函数中使用固定实例并发但这需要付费毕设场景不必配置。9.3 数据库查询优化打卡和专注记录会随时间增长。首页不需要读取全量数据只查当天记录。统计页面也需要在云函数端聚合不要一次性把几个月的数据拉到客户端再计算。以 3 个月 300 条专注记录为例全量下发到客户端大约 200KB在弱网环境下体验很差聚合后只需要返回 90 个数字。10. 云函数返回结构约定多个云函数之间建议统一返回格式方便前端统一处理{ code: 0, message: success, data: {} }错误码建议code含义0成功-1业务校验失败如重复打卡-2数据库写入失败-3参数缺失500服务端异常前端封装一个统一的调用方法function callFunction(name, data {}) { return new Promise((resolve, reject) { wx.cloud.callFunction({ name, data, success(res) { if (res.result.code 0) { resolve(res.result.data); } else { reject(new Error(res.result.message || 业务处理失败)); } }, fail(err) { reject(err); } }); }); }11. 毕业设计演示与答辩建议毕设演示是最容易翻车的环节提前做好下面几件事11.1 准备多套测试账号如果现场网络不好云函数调用可能失败。准备一个演示账号把打卡数据、任务数据、专注记录提前写好。演示时直接展示数据结果而不是现场从零开始操作。11.2 演示前预热小程序首次打开会加载云函数现场可能因为网络延迟导致白屏。提前在开发者工具里保存好页面状态打开小程序后先停留 2 秒再进行操作演示。11.3 讲清楚核心链路答辩时老师通常会问打卡连续天数是怎么计算的用户数据存在哪里如何保证用户只能看到自己的数据刚才的统计图表数据从哪来回答时明确说出连续天数在云函数端计算依据当前时间和上次打卡时间的时间戳差值。数据存在云开发的云数据库中属于非关系型数据库。每次查询带上_openid数据库权限设置为“仅创建者可读写”。统计图表数据由云函数聚合返回客户端只负责渲染。11.4 准备一套备用演示路径如果真机调试连不上直接改用开发者工具模拟器。模拟器和真机的数据互通因为数据都在云端。这个备用方案要提前演练一遍。12. 最佳实践与合规提醒到这里功能已经全部做完了但有几个工程化建议和合规事项需要提醒12.1 代码管理毕业设计代码建议使用 Git 管理至少提交三个版本初始框架、核心功能完成、答辩前稳定版。每次大改动前打 tag方便回退。12.2 隐私合规小程序涉及用户信息处理必须在app.json中声明隐私接口并在用户首次打开时弹出隐私协议提示。云存储中的用户头像、昵称数据需要提供注销入口。如果用户要求删除数据应提供一个“删除我的数据”按钮调用云函数清空该用户所有集合中的记录。12.3 数据备份云开发控制台支持数据库集合导出答辩前导出一份完整数据备份。如果现场出现云开发环境被误删的情况这份备份可以快速恢复。注意云开发环境删除后不可恢复答辩前不要随便删除或重置环境。12.4 版权与素材授权如果在小程序中加入学习资料、课程视频、真题试卷等内容必须确认这些素材有合法授权。不要上传来源不明的 PDF、图片或音频。涉及用户生成内容的还要提供举报或反馈入口并约定“用户上传内容由用户自行负责”的条款。12.5 性能优化边界自律学习小程序的用户量通常不大初期云开发免费额度足够支撑毕设演示和论文实测。如果需要做压力测试可以在开发者工具中模拟多用户并发但真实并发量要控制在一定范围内毕竟免费额度有限。上线前建议先完成功能正确性验证再根据实际用户量决定是否调整资源规格。这套方案基本覆盖了自律学习小程序的完整开发链路。从选题、环境准备、页面设计、云函数实现到答辩演示每一步都是可执行的。最容易踩的坑集中在云函数_openid获取、订阅消息模板配置、云数据库权限设置这三个地方提前注意能省掉大量排查时间。建议先按最小闭环跑通登录 - 打卡 - 查看统计再做任务管理和订阅消息提醒这样每一步都有可见的产出毕设进度也更可控。
返回列表