ARTICLE DETAIL

资讯详情

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

校园勤工俭学小程序:云开发毕业设计中的云函数与数据库实战解析

校园勤工俭学小程序:云开发毕业设计中的云函数与数据库实战解析 简介基于云开发的校园勤工俭学微信小程序是一份已经通过的高分毕业设计源码包主要面向计算机相关专业毕业生、微信小程序开发者及需要快速搭建勤工俭学平台的院校项目。项目完整覆盖岗位发布、学生报名、工时记录等典型业务基于微信云开发实现前后端一体化无需自建服务器适合作为毕设参考或二次开发基础。资源包共1506个文件约929KB以js/ts逻辑脚本、wxml页面结构、wxss样式、json配置和wxs辅助脚本为主并附带云函数上传脚本与少量说明文档目录结构清晰便于按模块检索学习。目前已有1754人学习下载。学习价值在于能提供可直接运行的完整项目框架、云函数部署脚本及页面配置文件帮助读者梳理小程序云开发的设计思路、代码组织方式和部署验证流程具有较好的毕业设计支撑作用。1. 校园勤工俭学微信小程序云开发毕业设计的「免服务器」方案如果你正在为毕业设计选型还在纠结买服务器、备案域名、配置 HTTPS 这一堆破事这个基于云开发的校园勤工俭学微信小程序源码包会是个不错的参考。它把小程序后端全部跑在微信云开发上不需要自己运维服务器数据库、云存储、云函数都是现成的前端用原生小程序语法写后端就是一个个 Node.js 云函数。整个项目从岗位发布、学生报名、老师审核到工时记录和工资结算业务链路是完整的适合计算机相关专业的毕业设计也适合想快速搭一个校内信息发布平台练手的开发者。我拆完这个包最直接的感受是微信小程序不难云开发也不难难的是把两者串起来的工程习惯——而这份资源恰好把上传云函数、初始化环境、业务权限这些都串好了照着跑通一遍基本就摸清了云开发小程序的完整套路。2. 拆解 uploadCloudFunction.bat云函数批量上传脚本的真实用法2.1 云函数在项目里的组织方式一个 index.js 对应一个函数云开发的小程序项目里后端逻辑不是写在服务器上的而是拆成若干个云函数。每个云函数是一个独立的目录目录里至少有一个index.js作为入口文件外加一个可选的package.json声明依赖。微信开发者工具里右键某个云函数目录可以直接选择「上传并部署云端安装依赖」但如果函数多了手动一个个点就非常折磨人。这个毕业设计资源里出现的一堆index.js并不是重复文件而是不同云函数各自的入口。常见的组织方式是这样的project/ ├── miniprogram/ │ ├── pages/ │ └── app.js ├── cloudfunctions/ │ ├── login/ │ │ └── index.js │ ├── getPositions/ │ │ └── index.js │ ├── submitApplication/ │ │ └── index.js │ ├── reviewApplication/ │ │ └── index.js │ ├── recordWorkLog/ │ │ └── index.js │ ├── settleWages/ │ │ └── index.js │ └── uploadCloudFunction.bat └── project.config.json这里的cloudfunctions目录下每个子目录就是一个云函数index.js里导出exports.main async (event, context) {}事件参数event里带着小程序端传过来的数据context里可以拿到调用者的openid。云函数本质上就是运行在云端的 Node.js 服务微信帮我们封装好了wx-server-sdk用它可以操作云数据库、云存储和调用其他云函数。uploadCloudFunction.bat放在这个目录下目的很明确一条命令把cloudfunctions下所有子目录里的云函数批量部署上去。这种批处理脚本是 Windows 环境下很常见的工程化做法很多毕设项目都会打包一个省去在开发者工具里逐个右键上传的重复操作。脚本本身逻辑不复杂但里面有几个参数和前置条件不搞清楚运行起来会一头雾水。2.2 批处理脚本逐行拆解从登录到上传一个典型的uploadCloudFunction.bat内容大致是下面这样我已经把注释写在里面了echo off set ENV_IDyour-env-id set TCB_CLItcb echo 开始批量上传云函数... for /d %%i in (cloudfunctions\*) do ( echo 正在上传云函数%%~nxi call %TCB_CLI% fn deploy --envId %ENV_ID% --name %%~nxi --code %~dp0cloudfunctions\%%~nxi if errorlevel 1 ( echo 上传失败%%~nxi exit /b 1 ) ) pause这段脚本的逻辑很直白先定义两个变量ENV_ID是云开发环境 IDTCB_CLI是命令行工具tcb的调用名。然后用for /d循环遍历cloudfunctions目录下的每一个子目录%%i拿到的是完整的目录路径%%~nxi是去掉路径后的目录名也就是云函数名。接着调用tcb fn deploy命令把--code指向对应的云函数目录--name指定函数名。call关键字在批处理里很重要它确保执行完另一个批处理或命令后能回到当前脚本继续循环。errorlevel 1判断上一条命令是否失败失败就打印日志并退出避免后面一堆函数上传失败还在硬跑。最后的pause是为了让窗口停住能看到输出结果。这里的注意点是环境 ID 必须和wx.cloud.init里的保持一致否则函数是传上去了但小程序端调不到。tcb命令要求在本地已经安装并登录过腾讯云云开发命令行工具常见的方式是通过 npm 全局安装npm install -g cloudbase/cli tcb logintcb login会打开浏览器让用户扫码授权授权完成后tcb fn deploy才能拿到操作权限。如果没有登录就执行批处理几乎每条命令都会提示未授权但批处理脚本不会为每个函数弹一次登录所以必须先单独完成一次tcb login。2.3 首次运行脚本前要改的三个配置拿到这份资源后直接双击uploadCloudFunction.bat大概率会翻车因为里面有几个占位配置需要先替换成你自己的。第一个是这个环境 ID在微信开发者工具里点「云开发」控制台右上角能看到环境 ID类似your-env-id这种字符串需要把它填进 bat 文件里。第二个是开发者工具的app.js里的wx.cloud.init同样需要改成环境 ID两者不一致会导致小程序端请求云函数时报 404。第三个配置容易被忽略云函数的package.json。很多云函数需要用到上一层的依赖比如wx-server-sdk版本号要和小程序基础库匹配。常见现象是本地tcb fn deploy只上传代码依赖在云端安装时失败导致函数运行时报「module not found」。我一般会在每个云函数目录下保留独立的package.json并指定wx-server-sdk为latest然后期望云端安装依赖。如果某些云函数用了特殊依赖建议先把本地node_modules删掉再上传避免把本地的二进制模块传上去。配置修改完成后建议先单独部署一个最简单的云函数比如login在开发者工具的云开发控制台看运行日志确认环境通没通再批量跑脚本。这样即使失败也能把问题范围缩小到配置层面而不是十个函数一起报错。3. 核心功能实现岗位发布、报名审核与工资结算的云开发写法3.1 岗位发布与审核数据库权限和状态字段设计校园勤工俭学业务里岗位是核心数据。一个岗位通常包含标题、所属部门、工作内容、招聘人数、薪资标准、工作时间、状态等字段。在云数据库里我建议建一个名为positions的集合字段结构大致如下{ _id: auto-generated, title: 图书馆整理员, department: 图书馆, description: 整理书架维护阅读区秩序, salaryPerHour: 18, quota: 2, filledCount: 0, status: pending, publisherOpenId: oXXXX, createTime: 1690000000000, reviewTime: null }其中status是核心状态字段我习惯用pending待审核、approved已发布、closed已结束、rejected已驳回四个值。新发布的岗位默认是pending管理员审核通过后变成approved学生才能看到并报名。这样设计的好处是前端查询时只需要一个where条件过滤status不需要在页面里写复杂的权限判断。云开发数据库的权限控制有三种仅创建者可读写、所有用户可读仅创建者可写、所有用户不可读写。对于岗位集合正确配置是「所有用户可读仅创建者可写」。管理员审核的动作不能直接让小程序端写数据库而是要通过云函数完成。云函数拥有管理权限可以绕过客户端权限限制修改任何数据。这样就形成了一个「前端只读 云函数写」的安全模型。审核岗云的云函数reviewPosition核心逻辑如下const cloud require(wx-server-sdk) cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const db cloud.database() exports.main async (event) { const { positionId, approve } event const wxContext cloud.getWXContext() const adminOpenId await checkAdmin(wxContext.OPENID) if (!adminOpenId) { return { code: -1, msg: 无管理员权限 } } const newStatus approve ? approved : rejected await db.collection(positions).doc(positionId).update({ data: { status: newStatus, reviewTime: Date.now() } }) return { code: 0, msg: ok } }这段代码里cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV })表示使用当前环境云函数部署在哪个环境就操作哪个环境的数据不用写死环境 ID。cloud.getWXContext()可以拿到调用者OPENID服务端用这个来识别身份。checkAdmin是一个辅助函数通常查一下admins集合里有没有记录判断当前用户是不是管理员。参数上event.positionId是岗位 IDevent.approve是布尔值。前端调用时通过wx.cloud.callFunction传入这两个字段即可。注意云函数默认超时时间是 3 秒如果审核逻辑里还要发订阅消息、更新其他集合建议把超时时间设置到 20 秒具体在云函数目录的config.json里配置timeout: 20。3.2 学生报名与状态流转云函数事务与原子操作学生看到已审核通过的岗位后可以发起报名。报名数据放在applications集合字段包括jobId、studentOpenId、status、applyTime、resultTime。这里最关键的约束是一个学生不能重复报名同一个岗位。这个问题不能用「先查再插」的方式解决因为两个并发请求可能同时通过查询然后同时写入导致两条重复记录。云开发数据库支持事务可以用db.runTransaction来保证原子性。另一种更轻量的做法是利用数据库的where条件更新在插入报名记录前先尝试把岗位的某个自增字段加一如果影响行数为 0说明条件不满足。不过最稳妥的还是事务因为报名状态流转还可能涉及撤销、录用、完成等多个动作。下面是submitApplication云函数的简化版逻辑是在一个事务里同时检查重复报名、减少岗位剩余名额、创建报名记录const cloud require(wx-server-sdk) cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const db cloud.database() exports.main async (event) { const { jobId } event const { OPENID } cloud.getWXContext() try { const result await db.runTransaction(async transaction { const jobDoc await transaction.collection(positions).doc(jobId).get() const job jobDoc.data if (job.status ! approved) { throw new Error(岗位未发布或已关闭) } if (job.filledCount job.quota) { throw new Error(岗位名额已满) } const existing await transaction.collection(applications) .where({ jobId, studentOpenId: OPENID }) .count() if (existing.total 0) { throw new Error(你已经报过这个岗位了) } await transaction.collection(applications).add({ data: { jobId, studentOpenId: OPENID, status: applied, applyTime: Date.now() } }) await transaction.collection(positions).doc(jobId).update({ data: { filledCount: job.filledCount 1 } }) return { code: 0, msg: 报名成功 } }) return result } catch (err) { return { code: -1, msg: err.message } } }事务里的逻辑顺序很关键先获取岗位文档检查状态和名额再查是否重复报名最后写入报名记录并更新名额。任何一个步骤抛错整个事务回滚数据库不会留下半截数据。transaction.collection().doc().get()在事务里是支持的但必须使用事务对象transaction而不是db否则会报错说不支持在事务外操作。状态流转方面applications.status的取值我建议是applied已报名、accepted已录用、rejected已拒绝、ended已结算。管理员在审核学生时调用reviewApplication云函数传入applicationId和newStatus。如果是录用还要顺便把岗位的filledCount加一。这里要注意在 3.1 的岗位发布里filledCount默认是报名人数也可以设计成录用人数。如果报名即占名额就用 3.2 的写法如果要等管理员审核通过才算占名额那么filledCount应该在reviewApplication里更新而不是submitApplication里更新。这两种模型各有场景毕设答辩时讲清楚你是哪一种就可以了。3.3 工时登记与工资结算定时触发器的配置与代码勤工俭学岗位通常按小时计费学生干了活需要登记工时月底再由管理员结算工资。工时记录放在work_logs集合字段包含applicationId、studentOpenId、jobId、hours、date、confirmStatus。这里的坑是学生自己登记的工时不能直接视为有效否则会出现乱填工时的情况。常见做法是学生提交工时后由岗位负责人或管理员确认confirmStatus从pending改为confirmed。工资结算是个批处理任务很适合用云开发定时触发器来做。定时触发器是云函数的一种配置在云函数目录下的config.json里声明触发规则{ triggers: [ { name: monthly-settle, type: timer, config: 0 0 0 1 * * * } ] }这个规则表示每月 1 号零点执行。Cron 表达式有 7 位分别是秒、分、时、日、月、星期、年这里0 0 0 1 * * *对应的就是「每月 1 日 00:00:00」。如果对 Cron 语法不熟我推荐先在云开发控制台里用自动生成的规则试跑一次确认时间对了再部署。结算云函数settleWages的核心逻辑是拉取所有状态为accepted的报名记录汇总对应work_logs里已确认的工时乘以时薪写入wages集合并更新报名状态const cloud require(wx-server-sdk) cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const db cloud.database() const _ db.command exports.main async () { const now new Date() const month now.getMonth() 1 const appRes await db.collection(applications) .where({ status: accepted }) .get() for (const app of appRes.data) { const logRes await db.collection(work_logs) .where({ applicationId: app._id, confirmStatus: confirmed }) .get() const totalHours logRes.data.reduce((sum, log) sum log.hours, 0) const positionRes await db.collection(positions).doc(app.jobId).get() const salary totalHours * positionRes.data.salaryPerHour await db.collection(wages).add({ data: { applicationId: app._id, studentOpenId: app.studentOpenId, month, totalHours, salary, status: unpaid, createTime: Date.now() } }) await db.collection(applications).doc(app._id).update({ data: { status: ended } }) } return { code: 0, msg: 结算完成 } }这段代码做了三件事查所有已录用的报名累加已确认工时计算工资并写入wages。注意db.command是云开发数据库的更新操作符这里没有用到_其实可以去掉但在更复杂的查询里它会非常有用。get()默认一次最多返回 100 条数据如果报名记录超过 100 条需要分页或使用limit、skip。毕设数据量一般不会太大但如果答辩演示时塞了几百条模拟数据记得处理get()的上限否则结算结果会遗漏。定时触发器在本地调试时不会自动触发只能通过开发者工具的「云函数本地调试」手动调用。我习惯把结算函数写成既能被定时器触发也能被event.test参数控制执行一次方便演示时手动跑。4. 避坑指南云开发小程序毕设最常见的五个翻车现场4.1 本地调试正常上传云函数后报 -501000现象在微信开发者工具里用本地调试跑云函数一切都正常一旦上传到云端从真实小程序端调用就开始报错错误码-501000提示FunctionName not found或者Function not found。原因最常见的是云函数部署到了错误的云开发环境。开发者工具里可能有多个环境小程序端wx.cloud.init指定的环境 ID 和云函数实际部署的环境不是同一个。另一个原因是uploadCloudFunction.bat脚本里的--envId写错导致函数传到别的环境去了。解决进入云开发控制台先确认当前选中的环境再查看「云函数」列表里有没有对应的函数名。接着看小程序app.js里的wx.cloud.init({ env: your-env-id })把环境 ID 改成云函数所在的那个。如果函数名不一致检查批处理脚本里的--name是否取自目录名不要在云函数目录名里加空格或中文。4.2 数据库权限设成「所有用户可读」导致越权现象学生打开小程序不仅能看到所有岗位还能直接看到其他学生的报名记录、工时记录甚至工资信息。答辩评委随便点点就发现了。原因云开发数据库集合的默认权限是「仅创建者可读写」但如果照着网上教程为了省事把权限改成了「所有用户可读」那么所有用户都能读整个集合。工资和报名记录这类敏感数据必须设置为「仅创建者可读写」之外更严格的规则。解决在云开发控制台把applications、work_logs、wages三个集合的权限都设为「仅创建者可读写」或者更彻底地设为「所有用户不可读写」只允许云函数访问。前端页面需要这些数据时一律通过云函数拉取。云函数端可以用getWXContext()拿到调用者OPENID在查询时强制过滤studentOpenId等于当前用户确保用户只能看自己的数据。4.3 uploadCloudFunction.bat 提示登录失败TCB CLI 的版本问题现象双击uploadCloudFunction.bat窗口快速闪过一堆文字然后提示登录失败或者命令不存在云函数一个都没传上去。原因批处理里调用的是tcb命令但本机没有安装cloudbase/cli或者安装的是旧版本的tcb腾讯云之前的命令行工具命令参数不兼容导致部署报错。解决先卸载旧版本重新安装最新版本npm uninstall -g cloudbase/cli npm install -g cloudbase/cli tcb logintcb login会弹出一个二维码用微信扫码授权。授权状态有有效期过期后需要重新登录。另外如果电脑上安装了多个 Node.js 版本tcb命令可能不在PATH里批处理脚本里调用时要写全路径或者先进入cloudfunctions目录再执行call npx tcb fn deploy ...用npx临时调用当前项目的依赖。我一般会在 bat 脚本开头加一行where tcb如果找不到就直接提示安装日志会更友好。4.4 wx.cloud.init 环境 ID 写错所有请求静默失败现象小程序能正常打开页面也能渲染静态内容但每个需要云数据库数据的页面都空白控制台报错显示invalid env或者请求超时。有时甚至不报错只是返回undefined。原因wx.cloud.init里的env参数和环境 ID 对不上。环境 ID 是一个字符串不能带前缀不能带空格很多人从云开发控制台复制时多复制了一个换行符或者把环境名称和环境 ID 搞混。解决在微信开发者工具点「云开发」按钮进入控制台在右上角「设置-环境设置」里复制环境 ID粘贴到app.js。不要手打因为环境 ID 常见的是字母数字加横杠的组合手打容易漏字符。另外wx.cloud.init应该在App.onLaunch里执行并且只执行一次不要在页面里重复init否则可能覆盖掉已有配置。4.5 定时触发器不干活超时时间和触发规则写法现象月底到了工资结算云函数没有自动跑。在云开发控制台手动点击「测试」按钮能运行但定时触发就是没动静。原因第一定时触发器没有正确部署。修改了config.json里的触发器配置后需要重新上传云函数而且必须选择「上传并部署云端安装依赖」只上传代码不会更新触发器。第二云函数超时时间太短正常云函数默认 3 秒超时工资结算要遍历很多报名记录如果超过 3 秒还没跑完会被强制终止看起来就是没执行。第三Cron 表达式里的星期和日字段容易搞混比如0 0 0 * * 1 *在标准 Cron 里表示每周一执行但在云开发里约定不一样写错了就等不到触发。解决在云函数目录的config.json里把timeout字段调到 20 秒或者更长触发器配置改成0 0 0 1 * * 1这种明确的规则。部署后先到云开发控制台「云函数-触发日志」里看有没有触发记录。更稳妥的做法是不要在触发器里做耗时计算而是让定时触发器只负责往消息队列里投一个任务真正干活的条件逻辑放在另一个函数里由消息队列触发。不过毕设场景数据量小单函数直接跑也够了重点是确认触发日志有记录。5. 从代码到答辩演示端到端验证与数据准备5.1 按角色走一遍主流程项目里至少有三个角色学生、管理员岗位审核老师、岗位负责人。答辩演示前我建议自己用小号模拟两个微信身份来跑一遍避免现场演示时用同一个微信号既当学生又当管理员权限逻辑看起来混乱。主流程验证点可以用下面这个表格来对照步骤角色操作预期结果1学生登录小程序显示真实 openid进入首页2管理员发布岗位岗位状态为待审核学生端看不到3管理员审核通过岗位学生端首页出现该岗位4学生报名岗位报名成功岗位名额减一5管理员录用学生学生端消息通知状态变已录用6学生登记工时工时记录显示待确认7管理员确认工时工时状态变已确认8系统触发结算工资记录生成报名状态变已结算验证的时候重点看权限隔离学生登录后只能看到自己的报名记录和工资不能看到其他学生的数据。管理员端要能看到汇总的报名人数和工时数据。有些源码里会把管理员的入口藏在「我的」页面里长按某个空白处才弹出演示前一定要记住这个隐藏入口否则现场找不到就尴尬了。5.2 用模拟数据填满页面刚部署完的数据库是空的页面全是空白演示效果很差。我一般会写一个一次性的云函数或直接在开发者工具控制台里执行一段 JS批量插入模拟岗位和报名数据。注意插入时要带上合理的时间戳让列表按时间排序时看起来像真实的运营数据。下面这段脚本可以放在开发者工具的「云开发控制台-数据库-右键集合-导入」里或者用 Node.js 脚本直连数据库插入。批量插入岗位数据的简化逻辑const cloud require(wx-server-sdk) cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) const db cloud.database() exports.main async () { const jobs [ { title: 图书馆整理员, salaryPerHour: 18, quota: 2, department: 图书馆 }, { title: 实验室助理, salaryPerHour: 20, quota: 1, department: 信息学院 }, { title: 食堂秩序维护, salaryPerHour: 15, quota: 3, department: 后勤处 }, { title: 校园快递分拣, salaryPerHour: 22, quota: 2, department: 校团委 }, ] const tasks jobs.map((job, index) { return db.collection(positions).add({ data: { ...job, status: index % 2 0 ? approved : pending, filledCount: 0, createTime: Date.now() - (index 1) * 86400000, publisherOpenId: admin_openid } }) }) const res await Promise.all(tasks) return { code: 0, inserted: res.length } }插入时注意把status设置为部分approved这样才能在首页看到岗位。filledCount要置 0否则会干扰后续名额判断。演示用数据不要太假岗位名称一定要真实比如「图书馆整理员」「实验室助理」这类校园里常见的勤工俭学岗位答辩评委看到会觉得业务调研到位。如果时间充裕再给每个岗位配一两张云存储上的图片首页会好看很多。5.3 演示时的网络兜底方案答辩现场的网络不一定稳定尤其是学校机房的 Wi-Fi经常连不上外网。云开发依赖微信服务器断网就全完。我的习惯是在小程序页面里做一个「本地演示模式」开关检测到请求超时或者网络不可用时自动读取本地静态数据。这个开关也可以手动打开方便在没有网络的环境下做 UI 层面的演示。实现方式不复杂在每个页面请求云函数前先判断全局变量app.globalData.demoMode如果为真就直接用本地 mock 数据渲染页面。这要求前端代码里把数据和视图分开页面只依赖一个数据源。很多毕设源码没有做这个分层页面里直接wx.cloud.callFunction然后setData这种情况下临时改成本地数据会动很多代码。我建议在拿到源码包后先看一下首页的数据请求逻辑如果是一个统一的api.js文件那就好办在api.js里加一层判断就行。如果没有统一封装趁早自己抽一个request.js把所有callFunction都收拢到里面这对后续答辩和扩展都是值得的。演示时还有一个细节手机屏幕常亮开发者工具的真机调试二维码提前打开。如果用模拟器演示字号调到适中不要让评委凑近屏幕看蚂蚁字。页面加载时可以故意放慢一点配合讲解「这是云函数在查询数据库」比快速划走更有说服力。6. 进阶技巧把云函数本地调试变成日常习惯拿到这类毕设源码后很多人第一步是直接上传全部云函数然后改 IP 和参数跑通一次就不管了。但真正让你在答辩时底气十足的是能随时进到云函数内部看变量、看调用链。微信开发者工具里对云函数右键有一个「本地调试」功能这个比一遍遍上传云端再查日志高效得多。本地调试会在本地起一个 Node.js 进程模拟云函数运行环境工具会把真实的小程序调用请求转发到本地你可以在index.js里打console.log也可以直接打断点然后在小程序端触发调用代码执行到断点处就会停住event里携带的参数一目了然。我习惯在每个云函数入口第一行就加上一行console.log(event:, JSON.stringify(event))本地调试时先在控制台看入参再决定下一步操作。尤其是submitApplication这类涉及事务的函数入参乱七八糟时第一步就该发现问题而不是等事务报错才回去查。另一个技巧是给云函数加一个test分支例如在event.debug true时返回固定结果这样不需要调整真实数据也能验证前端页面的渲染逻辑。最值得养成的是一个强制流程每次修改任何云端配置数据库权限、云函数代码、触发器之后不要直接点「上传并部署」而是先用本地调试跑一遍再上传然后跑一次端到端的主流程。以前我自己图省事改完权限直接传生产环境结果答辩前发现学生端看不到岗位排查了很久才意识到是权限配置在「所有用户不可读写」和「所有用户可读」之间切换时把approved状态数据遮住了。从那以后我每次动完云端任何配置都强制跑一遍第 5 章的端到端验证清单再收工。这份基于云开发的校园勤工俭学小程序功能上不算花哨但云函数、数据库权限、定时触发器这些知识点覆盖得很扎实能把它的每一条链路都讲明白毕业设计这一关基本就稳了。希望帮到你。本文还有配套的精品资源点击获取
返回列表