打开微信,扫一下老师发的课程二维码,课表、作业、提交情况一目了然;该交的作业提前一天收到提醒,不用再反复翻群聊记录。这是我这个项目最终做出来的效果。
这个基于微信小程序的教学辅助管理系统,是一个完整的课程设计/毕业设计级别的项目,带全套源码、配套开发文档和调试说明。简单来说,它把课堂教学里几件最麻烦的事——排课、布置作业、收作业、发通知、签到考勤——全部搬进了一个微信小程序里,学生、老师各有一个视角,各干各的事。
项目适合三类人:计算机相关专业的在校生,正在为课程设计或毕业设计选题发愁;想入门微信小程序开发但缺少完整实战项目的开发者;以及确实有教学管理需求、想低成本给自己学院或班级做一个轻量工具的老师。
下面我按项目的实际开发顺序,把从技术选型到功能实现、再到调试上线的完整过程拆开讲一遍,包括我踩过的坑和最后总结出来的方案,希望能帮你少走弯路。
1. 项目定位与技术选型解析
1.1 为什么把系统做成微信小程序而不是Web或App
这是接项目后第一个要回答的问题:同样一套教学辅助功能,为什么不做成网页、不做成App,非要选微信小程序?
最直接的原因是触达成本。教学辅助系统的用户是老师和学生,这两类人有一个共同特点——他们不会为了一个课程工具特意去下载一个App,但几乎每个人每天都在用微信。微信小程序做到了“不用安装、扫码即用”,学生扫一下老师分享的二维码就能进入系统,这个体验远比下载注册一个App顺畅。
第二点从开发角度讲,微信小程序的技术栈接近Web开发,WXML和WXSS学起来几乎没有门槛,底层的页面逻辑、数据绑定、组件化开发思路跟Vue这类前端框架高度相似。如果你已经有一点前端基础,上手速度会非常快;就算零基础,照着文档和源码走一遍,也能在一两周内把项目跑起来。
第三点是调试和发布的便利性。微信开发者工具自带模拟器、真机调试、性能面板、网络面板,一个工具全搞定。相比之下,App开发要配置Android SDK/Xcode、处理签名、过应用商店审核;Web开发要自己搞定服务器、域名、HTTPS证书。小程序虽然有发布审核,但审核流程和成本都远低于App。
这里还会被问到一个常见问题:为什么不直接用uniapp开发一套,以后还能多端复用?我的答案是:uniapp确实是好方案,但作为教学项目/毕设项目,原生小程序的结构更简单、依赖更少、报错更直观,而且和微信生态(订阅消息、云开发、微信登录)的集成最原生。如果未来确实有跨端需求,再迁移uniapp也不迟,这个在第五节我会单独展开。
1.2 技术栈与整体架构规划
确定用小程序之后,第二个关键决策是后端怎么选。这里我提供两套方案,选的时候看你的侧重点。
方案A:微信云开发。小程序免费版自带云函数、云数据库、云存储三个能力,相当于把“服务器+数据库+文件存储”全部托管给了微信。优点是省事,不需要自己买服务器、配域名、配HTTPS,尤其适合以学习小程序前端为主、不想折腾运维的新手。缺点是它用了云开发的NoSQL数据库,和传统的MySQL建模方式不一样,以后迁移到传统Web项目需要做数据导出适配。
方案B:自建服务端。用Node.js(Express/Koa)或Java(Spring Boot)写一套RESTful API,数据库用MySQL,小程序端通过wx.request调用接口。优点是可以完整地学到“小程序前端+服务端API+关系型数据库+接口文档”的全链路知识,这也是企业面试中更认可的项目经历。缺点是需要自己搞定服务器环境,开发调试周期长一些。
我这个项目最终做了两套兼容:核心业务逻辑同时支持云开发方式和HTTP API方式。如果你只是想快速跑通看效果,直接用云开发;如果你打算拿它应付答辩或者放简历里,我建议走“自建后端”的路线,至少能在答辩时讲清楚接口是怎么设计的、数据是怎么存的关系型表。
整体架构可以概括为三层,前端再细分,用的是经典的pages + components + utils结构。每个页面一个页面文件包(.js + .wxml + .wxss + .json),通用组件独立放在components目录,请求封装和工具函数放在utils目录,一个简单的目录规划就能让后续维护省大力气。目录结构细节我在第五小节讲,先记住这个分层思路。
| 层级 | 职责 | 关键内容 |
|---|---|---|
| 表示层 | 小程序客户端 | 页面、组件、交互逻辑 |
| 业务层 | 云函数/后端API | 鉴权、课程管理、作业管理、签到、数据统计 |
| 数据层 | 云数据库/MySQL | 用户表、课程表、作业表、提交记录表等 |
2. 核心功能模块与数据库设计
2.1 一屏看穿:教师端、学生端、管理端功能拆解
教学辅助系统听起来有点玄,落到具体功能其实就是三类用户各干各的事。我把功能拆成了三个端,权限通过role字段控制。
教师端:
- 课程管理:创建课程、维护上课时间地点、生成课程二维码/邀请码。
- 作业管理:布置作业(标题、要求、截止时间、附件)、查看提交名单、在线评分批注。
- 通知公告:给选课学生发送课程通知,支持以订阅消息形式推送到微信。
- 签到管理:发起课堂签到,查看签到统计,支持定位签到和口令签到。
- 学生管理:查看选课名单、逐个或批量移除学生。
学生端:
- 课程中心:查看自己的课程列表和课表,扫描二维码加入课程。
- 作业中心:查看未交/已交作业,在线提交文本或上传文件,查看老师评分。
- 通知中心:接收课程通知、作业提醒、成绩提醒。
- 签到:一键签到,查看个人签到历史。
- 个人中心:绑定学号姓名、修改头像昵称、查看学习统计。
管理端(可选,用于系统运营):
- 用户管理:查看所有用户,处理异常账号,重置密码/身份。
- 课程审核:审核教师创建的课程,处理课程举报。
- 数据统计:按学院/年级/教师/课程维度看使用数据。
功能拆解完成之后,一个很现实的提醒:毕设项目功能不是越多越好,核心功能做完做稳,远远好过一堆半成品模块堆在一起。我当时就栽过这个跟头,一口气规划了十几个功能入口,最后赶进度做得漏洞百出。后来砍到上面这套,老师端和学生端的核心闭环才真正跑通。
2.2 数据库表设计与权限模型
不管你选云开发还是自建后端,业务层面的表结构是通用的。我直接给出一套经过实践验证的表设计,字段不用全抄,但关系可以照着理。
users(用户表)
- openid:微信唯一标识,主键
- unionid:多端统一标识,可选
- role:身份字段,teacher / student / admin
- student_no:学号,teacher_no:教师工号
- name:姓名,avatar:头像,nickname:昵称,phone:手机号
courses(课程表)
- course_id:主键
- course_name:课程名称
- teacher_id:关联users表的老师
- schedule:上课时间(JSON格式,存周次+星期+节次)
- location:上课地点
- invite_code:邀请码
- status:课程状态
assignments(作业表)
- assignment_id:主键
- course_id:关联课程
- title:标题,content:描述,attachment:附件路径
- deadline:截止时间
- created_at:创建时间
submissions(提交记录表)
- submission_id:主键
- assignment_id:关联作业
- student_id:关联学生
- content:提交内容,file_path:附件文件路径
- score:分数,comment:评语,graded_at:批改时间
- status:状态(未交/已交/已批改)
notifications(通知表)
- notification_id:主键
- course_id:关联课程
- 标题、内容、发布时间、是否推送
attendance(签到表)
- 签到ID、课程ID、签到码、开始时间、结束时间、签到方式
- 以及签到明细表:用户ID、签到时间、定位信息、有效/无效
权限模型这里说一个关键点:权限校验必须放在后端,前端只控制显示。很多新手会犯的错误是只在页面上用if判断role来决定“显示教师入口还是学生入口”,但接口层不做校验,懂技术的同学直接改请求参数就能越权访问教师接口。后端在每个API入口都校验当前用户身份和资源归属,这一步是答辩时很加分的点,也是真实项目中绝对不可缺少的。
2.3 一个重要的设计细节:微信登录与身份绑定
微信小程序和传统Web登录最大的区别在于,不需要用户输入用户名密码。小程序端调用wx.login()拿到临时code,传给后端,后端拿着code加上AppID和AppSecret换到用户的openid和session_key。openid是用户在某个小程序下的唯一标识,微信保证不会重复。
首次进入系统,用户是“未绑定身份”状态。小程序端引导用户走绑定流程:学生填学号+姓名,教师填工号+姓名,后端和基础数据做比对,比对通过才可以把openid和用户表关联起来。这一步我强烈建议做成“二次确认”——弹窗展示绑定的账号信息,让用户点确认,避免填错。
session_key是微信的会话密钥,用来解密用户的手机号和微信运动数据等敏感信息。教学系统用到的情况不多,但注意session_key千万不要存数据库,也不要在客户端使用,这是微信明文规定的安全红线,只需要在服务端短暂使用后丢弃即可。
3. 关键功能实现与调试实录
3.1 登录鉴权全流程的代码实现
登录这块是整条系统的地基,我直接贴核心代码。前端部分:
// pages/login/login.js Page({ data: { loading: false }, onLoad() { this.login(); }, async login() { if (this.data.loading) return; this.setData({ loading: true }); // 1. wx.login 获取临时 code const { code } = await wx.login(); if (!code) { wx.showToast({ title: '获取登录凭证失败', icon: 'none' }); return; } // 2. 将 code 发送到服务端 const result = await request({ url: '/api/auth/login', method: 'POST', data: { code } }); // 3. 服务端返回 openid + token if (result.code === 0) { wx.setStorageSync('token', result.data.token); wx.setStorageSync('userInfo', result.data.userInfo); this.navigateByRole(result.data.userInfo.role); } else { // 未绑定身份,跳转绑定页面 wx.redirectTo({ url: `/pages/bind/bind?code=${code}` }); } } });服务端对应逻辑(以Node.js为例):
// services/authService.js const crypto = require('crypto'); async function loginWithCode(code) { // 1. 用 code 向微信接口换取 openid 和 session_key const url = 'https://api.weixin.qq.com/sns/jscode2session'; const params = { appid: APP_ID, secret: APP_SECRET, js_code: code, grant_type: 'authorization_code' }; const wxResponse = await fetch(`${url}?${querystring.stringify(params)}`); const wxData = await wxResponse.json(); if (wxData.errcode) { throw new Error(`微信登录失败: ${wxData.errmsg}`); } // 2. 根据 openid 查用户 let user = await User.findOne({ where: { openid: wxData.openid } }); // 3. 如果用户不存在,返回未注册状态,让前端走绑定流程 if (!user) { return { needBind: true, openid: wxData.openid }; } // 4. 生成 token 返回给前端 const token = jwt.sign( { userId: user.id, role: user.role }, JWT_SECRET, { expiresIn: '7d' } ); return { token, userInfo: { ...user } }; }这里有一个非常容易被忽略的细节:token的有效期。我习惯设为7天,然后在每个请求中检查token的剩余有效期,如果不足2天,返回一个特殊状态码让前端静默刷新token,而不是等7天到了直接踢用户下线。教学系统的用户使用频率不高,如果到期就重新登录,体验会非常差。
绑定身份的流程,我建议做成一个极简的表单页:学号 + 姓名,选“我是学生/我是老师”,提交后由后端匹配基础数据。基础数据怎么来?可以从教务系统导出的Excel名单导入数据库,也可以由管理员在管理端手工录入。注意,绑定接口要有校验逻辑:防止一个账号被多个openid反复绑定;如果学生转班或者换号,管理员要能解绑。
3.2 作业提醒与倒计时:那些和时间打交道的细节
作业模块是整个系统最核心的东西,做得好不好,学生感受最直接。我在作业列表上做了三件事:倒计时展示、截止状态区分、订阅消息提醒。
倒计时展示,前端拿到后台的deadline时间戳,计算当前时间与截止时间的差值。这个倒计时不能只在页面加载时算一次,否则用户停留很久后时间就不准了。我的处理是在onShow里更新一次,再用setInterval每分钟刷新一次,页面onUnload时清除定时器。代码:
// pages/assignment/list.js let timer = null; Page({ onShow() { this.loadAssignments(); this.updateCountdown(); timer = setInterval(() => this.updateCountdown(), 60000); }, onUnload() { if (timer) clearInterval(timer); }, updateCountdown() { const assignments = this.data.assignments.map(item => { const remain = item.deadline * 1000 - Date.now(); if (remain <= 0) { item.statusText = '已截止'; return item; } const days = Math.floor(remain / 86400000); const hours = Math.floor((remain % 86400000) / 3600000); const mins = Math.floor((remain % 3600000) / 60000); item.statusText = days > 0 ? `${days}天${hours}时${mins}分` : `${hours}时${mins}分`; return item; }); this.setData({ assignments }); } });订阅消息这块,微信有一个限制:一次性订阅消息需要用户触发授权,每次授权只能发送一次。我的实践经验是:让学生在提交作业成功后弹窗引导订阅“截止提醒”,这样每次交一次作业就可以得到接下来一次性提醒的额度。后台在作业截止前24小时和1小时两个时间点各扫一遍数据库,给已经订阅且尚未提交的学生发提醒。这个功能做出来之后确实是刚需,亲测学生很少因为漏看通知而迟交。
对了,实现的时候记得处理时区问题。后端存时间戳(Unix毫秒)最安全,前端展示时用本地时区格式化。不要直接存“2025-06-30 23:59:59”这种字符串然后按字符串比较大小,不同的服务器时区设置不同,很容易在截止时间判断上出偏差。
3.3 缓存、分页和网络请求:把用户体验做稳
小程序里的wx.request不支持Promise,我第一步就是封装一个request函数,把token注入、loading、错误提示、状态码处理都统一掉。核心代码如下:
// utils/request.js function request({ url, method = 'GET', data = {}, loading = true }) { if (loading) wx.showLoading({ title: '加载中' }); const token = wx.getStorageSync('token'); return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + url, method, data, header: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, success(res) { if (res.data && res.data.code === 0) { resolve(res.data.data); } else if (res.data && res.data.code === 401) { // token过期,清理缓存并回登录页 wx.removeStorageSync('token'); wx.removeStorageSync('userInfo'); wx.reLaunch({ url: '/pages/login/login' }); reject(new Error('登录已过期')); } else { wx.showToast({ title: res.data.message || '请求失败', icon: 'none' }); reject(new Error(res.data.message)); } }, fail(err) { wx.showToast({ title: '网络异常,请检查网络', icon: 'none' }); reject(err); }, complete() { if (loading) wx.hideLoading(); } }); }); }缓存策略是我专门花时间调过的地方。教学系统的数据有几个特点:课表一周内基本不变,作业列表变化频率中等,通知公告变化少但实时性要求高。所以我的配置是:
- 课表缓存1天,进入课程页先读缓存再拉最新的,用静默刷新。
- 作业列表缓存5分钟,下拉刷新时强制更新。
- 通知公告不缓存,每次进页面直接拉取。
- 用户个人信息缓存到本地,修改后立即更新缓存。
缓存过期时间用wx.setStorageSync存数据的存储时间,读取时比对,过期了请求新的。一个容易忽略的点:微信的Storage是全局共享的,所以缓存key一定要带项目前缀,比如“teaching_assist_assignments”,避免和其他业务冲突。
分页逻辑我踩过一个坑。作业列表如果一次加载50条,图片附件比较多的场景页面会卡。我做了触底加载分页:默认每页10条,滚动到底部时加载下一页,用一个hasMore字段标记是否还有更多。注意“下拉刷新”和“触底加载”是两个不同的手势和事件,别混在一起。
4. 常见问题与排查技巧
4.1 微信开发者工具调试的“三大必踩之坑”
第一个坑就是不校验域名。小程序正式环境所有请求域名必须配置在后台的合法域名列表里,并且要求HTTPS。但开发阶段你用localhost或者局域网IP调试,经常会报“不在以下合法域名列表中”。解决办法是在开发者工具的“详情 -> 本地设置”里勾选“不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书”,然后工具设置会自动保存。注意这个设置只对当前项目生效,正式发布前一定要把域名配好。
第二个坑是缓存。开发过程中很常见的情景是改了代码,但在真机预览上看到的还是旧页面。这不是代码没生效,而是微信对小程序包和Storage都有缓存机制。解决办法:开发者工具里“清缓存 -> 清除全部缓存”;真机上删除小程序重新搜索进入,或者在工具里点“真机调试”而不是“预览”来绕过缓存。另外,小程序码扫码进入的版本是开发版还是体验版,页面上会带不同角标,注意分辨。
第三个坑是导航栏高度。iPhone X及其之后的机型都有底部小黑条,顶部状态栏高度也各有不同,直接写死statusBarHeight肯定翻车。正确做法是用wx.getSystemInfoSync()拿statusBarHeight,用wx.getMenuButtonBoundingClientRect()拿到胶囊按钮的位置和高度,然后动态计算导航栏高度。我在课程详情页的自定义导航栏上就被这个坑折磨了一个下午,最后封装了一个navbar组件,所有页面统一调用,才彻底解决。
4.2 白屏、请求失败和SetData卡顿的排查思路
白屏是小程序开发最容易遇到也最让人头皮发麻的问题,很多时候不报错、控制台一片干净,就是页面空白。我的排查顺序是:
- 先看Network面板,确认这个页面的数据请求是否成功,如果返回了数据,说明后端没问题。
- 再看Console面板,把警告信息打开,很多数据绑定问题会以warning形式出现,比如“Component is not found in path”。
- 检查WXML模板里有没有访问不存在的数据字段。例如data里没有定义courseName,模板里写{{courseName}},不会报错但会渲染为空白。
- 如果是有条件渲染的组件,检查wx:if的判断条件是不是永远为false。
- 最后用二分法,把页面里的模块逐个注释掉,定位到具体是哪个组件导致的白屏。
请求失败的问题,大部分是这几种:域名没配/没勾选跳过校验、HTTPS证书不被信任、后端跨域没处理、请求头Content-Type对不上。逐一排查就好,我最常遇到的反而是各种手滑写错接口路径,一个字母之差404,所以先别急着怀疑后端,先看请求URL是不是复制错了。
SetData卡顿,这个要专项说。小程序快速更新性能的关键时刻,我见过有人在一个滚动事件里疯狂setData,直接把页面卡成PPT。正确做法是:合并setData、降低更新频率、内容不变化就不要设置。比如倒计时更新,每分钟一次没问题,但如果做秒级倒计时,就应该只更新那个倒计时文本节点,而不是整个页面数据都setData一遍。列表页的勾选状态,尽量用update()方法去改,而不是整个list替换。
4.3 真机调试、体验版与正式版的管理
做完开发不是终点,上线前的调试才是真正挑毛病的阶段。强烈建议买一块真机来做真机调试,开发工具模拟器和真机在某些渲染效果、键盘弹出、下拉刷新上真的不一样。
微信提供了三个版本:开发版、体验版、正式版。日常调试用开发版,给老师同学看用体验版,对外发布用正式版。还有“真机调试”模式下可以在真机上看到console日志和网络请求,这是排查真机专属问题(比如iPhone字体、安卓webview渲染差异)的法宝。
提审之前做一个检查清单:
- 隐私弹窗有没有做(现在微信强制要求隐私协议说明)。
- 所有测试数据、测试标题清理干净。
- 正式环境中需要配置的域名都配在后台了。
- 把“开发版/体验版”的入口权限调好。
- 页面里不能出现可能被评审驳回的内容(比如诱导分享、低俗等敏感元素)。
- 至少走一遍主流程完整闭环。
我提审的时候被驳回过一次,原因是首页有一个区域放了其他平台的宣传字样,改名之后重新提审就过了。所以提交之前最好找两三个不熟悉项目的人拿体验版走一遍全流程,旁观者的视角往往更能发现问题。
5. 源码结构、文档配套与扩展方向
5.1 项目目录结构与源码阅读指南
拿到一份源码,第一件事不是双击打开就一顿乱翻,而是先看目录。我这个项目的目录结构是这样规划的:
teaching-assistant-miniapp/ ├── app.js # 小程序入口逻辑:全局登录态检查 ├── app.json # 页面路由、窗口样式、tabBar配置 ├── app.wxss # 全局样式 ├── pages/ # 页面 │ ├── login/ # 登录页 │ ├── bind/ # 身份绑定页 │ ├── home/ # 首页 │ ├── courses/ # 课程列表 │ ├── course-detail/ # 课程详情 │ ├── assignments/ # 作业列表 │ ├── assignment-detail/ # 作业详情/提交页 │ ├── notifications/ # 通知列表 │ ├── profile/ # 个人中心 │ └── admin/ # 管理端 ├── components/ # 通用组件 │ ├── navbar/ # 自定义导航栏 │ ├── course-card/ # 课程卡片 │ ├── assignment-card/ # 作业卡片 │ └── empty-state/ # 空状态占位 ├── utils/ │ ├── request.js # 请求封装 │ ├── auth.js # 登录鉴权工具 │ ├── date.js # 日期格式化工具 │ └── constants.js # 常量配置 └── services/ # 接口抽象层 ├── courseService.js ├── assignmentService.js └── userService.js阅读源码的顺序我建议是:先看app.json了解有哪些页面和路由,然后看utils/request.js了解请求怎么发,再看services层了解每个功能对应的API,最后进具体页面看数据绑定。这样三步走,比从入口文件逐行读下来高效得多。
如果是想改功能的开发者,定位更简单:想改作业列表的颜色,进pages/assignments下的wxss;想给作业增加一个“置顶”功能,先改后端数据模型加字段,再改前端页面和接口对接,前后端一条线下来就通了。
5.2 配套文档怎么编:从README到调试手册
标题里写了“文档”,这里多说两句。很多学生的第一反应是“文档就是抄代码写开发报告”,这是最大的误解。一份合格的配套文档至少包括四份:
- README.md:项目是什么、怎么跑起来、依赖什么环境。
- 数据库设计文档:表结构、字段含义、ER关系图(画Excel表格也行)。
- API接口文档:每个接口的路径、请求参数、返回结构、错误码。答辩时老师最爱问的就是这个。
- 部署/调试文档:开发环境怎么配、生产环境怎么部署、常见报错怎么处理。
写文档有一点我特别想强调:接口文档一定要用真实测试数据写示例,不要写“字符串类型”这种抽象描述。比如“支持传入yyyy-MM-dd格式的日期字符串”,比“日期”两个字强十倍。后端改字段的时候,接口文档同步更新,否则调试的时候两个人一对文档一个写错了就全员抓瞎。
调试文档更像是给接手的人的一份“逃生手册”。把环境搭建、起服务、首次登录、遇到某个报错该怎么处理,一步步写清楚。这个文档本身就是展示你工程能力的一部分,面试官和答辩老师都会翻。
5.3 后续扩展:从课程表到AI助教
项目做完不是终点,扩展方向其实非常丰富。我在交付文档里列了几个典型的演进方向,供参考。
第一个方向是把系统从“课程工具”升级成“校园服务入口”。引入校园卡余额查询、图书馆座位预约、校车时刻表等轻功能,直接把小程序变成一个校园生活工具集。这在小程序的生态里是非常成熟的打法,通过高频功能带动低频的登录和使用。
第二个方向是接入AI能力。比如作业提交后自动查重(文本比对),或者做一个基于课程知识库的AI助教,学生在课程群里@一下就能自动回答常见问题。大模型API直接以云函数的形式接入,技术难度不高,但体验提升是立竿见影的。
第三个方向是数据驱动。当系统跑了一个学期,积累了足够多的作业提交时间、签到记录、成绩数据,可以做一个“学习预警”功能:连续三次迟交作业或长期不签到的学生自动生成提醒报告,推送给辅导员或者学生本人。这就是从“教学辅助管理”走向“教学质量管理”了。
第四个方向是跨端复用。如果确定未来要支持更多场景(比如网页端、鸿蒙端),可以考虑用uniapp重写小程序端代码。迁移过程主要工作量在把WXML换成uniapp的模板语法,把wx.request换成uni.request,逻辑层几乎可以复用一半以上。
最后再讲一点我个人的体会。我做过好几个类似的课程设计项目,踩过的最大的坑不是技术不会,而是规划阶段贪多求全,看着哪个方向都想要,最后交出来一个每个功能都没做透的半成品。这个教学辅助管理系统做到最后我砍掉了很多不痛不痒的功能,留下的是最核心的课程、作业、通知、签到闭环,反而在答辩的时候被老师专门夸了产品感和工程感。
如果你也是拿这个项目来做课程设计或毕业设计,我给三个实操层面的建议:第一,先把登录鉴权跑通,再开发任何功能,身份体系不通,其他功能都是空中楼阁;第二,每开发完一个模块,立刻把对应的接口文档更新掉,不要等最后一次性补;第三,至少留一周时间专门做联调和上线前检查,这一步才是调试能力真正体现的地方。
项目本身能改的地方很多,加功能、换皮肤、换数据库都可以,但核心的登录鉴权、权限控制、数据交互这套逻辑是通用的,学会这一套,以后做任何管理系统类小程序都能直接复用。