做校园墙这类小程序,前期你会觉得最难的是「功能怎么写」,等它真的有人用了,才发现更磨人的是另一件事:上线之后的日常 。
有人投了违规内容,要删;有人被举报,要封;微博又限流了,得知道是哪个令牌出的问题;开学了,校历要改;某个同学说课表绑不上,得去翻是哪一步挂的。这些事如果每一件都要「改代码 → 打包 → 上传服务器 → 重启」,或者每一次都 SSH 上去直接改数据库,用不了多久你就会被它们淹没,而且很容易手滑。
所以「培正森林」后来加上了一个管理后台。它现在已经比业务接口还大了:README 里统计,这个项目 19 个控制器里,12 个是管理端的,管理页有 16 个。一个小程序,管理端比业务端还多,这件事本身就说明了什么是真正在消耗精力。
这篇不讲代码细节,讲讲这个后台到底在替我解决什么问题 ,以及我是怎么想「什么东西该放进后台」的。

一条共同的标准:这东西会不会变,谁来改

小程序有个很现实的约束:发版要提交审核。如果要给后台里的东西找一条共同的标准,大概就是这一句——凡是会变的、而且不该由开发者写代码来改的东西,就不要写死在代码里,做成数据,再给它一个后台页面。
用这个标准一过滤,后台里的东西基本就都出来了。
校历。 补课、放假每个学期都不一样,国庆中秋放几天、哪个周六补周一的课,是学校发了通知才知道的事。如果写在小程序里,每次都要发版。现在它在数据库的一张表里,后台改一下,所有人的小程序下次打开就生效。后端甚至给校历算了一个「内容指纹」,客户端只要比对一下指纹就知道要不要刷新(第 14 篇讲过)。
分享课表用的封面图。 这批「早八」表情包,最开始是打包在小程序里的,想加一张新的,就得发版。后来改成了后端下发,只存图片地址,后台里可以上传、改名、排序、上下架。运营想换就换,小程序拿不到列表时还会回退到包内自带的那几张,不至于空着。
各种阈值。 同一个用户每小时最多发几条、反馈每天最多几条、教务登录之间要随机等多久、微博 @ 转发每轮转几条……这些我都放进了一张 sys_config 表,后台里可调、改了立刻生效 。代码里有一份默认值注册表,数据库里没有对应的行,就用默认值。这样既不会因为漏配而启动失败,也让「被人改过的参数」一目了然。
举个最说明问题的例子:微博 @ 转发的节流。当初是因为零间隔连发,44 秒转了 9 条,被微博判定账号异常。把「每轮转几条」「隔多久拉一次」做成后台可调的参数之后,下次再碰到风控收紧,不用改代码,在后台里把数字调小就行。

第二类:必须有人盯着的东西

有些东西不是「要改」,而是「要看」。如果没有一个地方能一眼看到它的状态,出了问题你只会从用户嘴里知道。
微博令牌的状态。 第 10 篇讲过,项目里有 5 个应用的令牌,按「令牌 × 读写作用域」各自冷却。后台仪表盘里分「读」「写」两栏展示:几个应用还可用、几个在冷却、下次重试倒计时。令牌只显示前十几位,完整的永远不出现在界面上。
教务代理。 这个我要多说两句,因为它是整个项目里最「脆」的一环。学校的教务系统会按出口 IP 拦截,同一台服务器,经过家庭代理(squid)取验证码返回 200,直连返回 403。换句话说,代理一挂,全站绑定和更新课表都会失败 ,而用户看到的只是一句指向不明的「验证码识别失败」。
这种故障最讨厌:不是自己的代码出了 bug,但用户会觉得是你的 bug,而你自己还不知道。所以后端每小时会真的去请求一次教务验证码来探活,同时直连对照一次 ,用来区分「是代理挂了」还是「教务系统本身挂了」。状态一旦翻转(正常变异常,或者反过来),就发邮件通知;持续异常的话,每 6 小时最多再提醒一次,不会刷屏。探测历史和「立即探测」按钮都在后台的「教务代理」页里。
「卡住的用户」。 代理挂过一轮之后,会有一批同学处于这样的状态:登录失败的原因是验证码或代理(不是密码错),而且到现在还没有本学期的课表。他们密码是对的,只是运气不好,重新投一次基本就能恢复。
后台里有个「卡住用户」面板,专门把这批人列出来,可以一键全部重投。后端也会自己慢慢补:默认每 10 分钟补 1 个,而且有三重保护——代理探测正常才投(根因没修好时投了也是白投)、匀速、同一个用户有冷却期,不让反复失败的人一直占着队列。判断「谁值得重投」用的是第 13 篇讲的那套白名单 :密码错、账号不存在、账号已锁定,一律排除,免得越撞越锁。

第三类:内容治理

校园墙绕不开的就是内容管理,后台里这一块的功能是这样的:

  • 微博墙管理 :看帖子和评论,能直接以墙号身份发帖、评论、回复,也能删帖子、删评论,还能按「来源」筛选(小程序投稿,还是 @ 转发进来的);
  • 敏感词 :词库增删改、批量导入,改动即时生效;更实用的是命中记录 ——谁在反复试探,一目了然,还能从这里一键封号;
  • 黑名单 :生效中的封禁列表,可以解封、重新封禁、手动封禁,附带昵称和学号,方便你知道自己封的是谁;
  • 用户 :搜索、查看详情、封号解封;
  • 反馈 :回复并流转状态,同时有定时汇总邮件发到开发者邮箱,不用天天盯着看。

一个有意思的设计:让学生帮运营录入

项目的说明文档里有一段讲「考试倒计时」,我觉得值得单独拿出来说。
这个功能的原型很简单:学生可以自己添加考试,看还剩几天。问题是,运营不可能守着每个考试、每个事件去录入 。于是反过来做:学生各自添加自己的事项(各自可见),后台把大家添加的内容按「日期 + 标题」聚合 起来,哪个事项加的人多,一眼就能看出来;运营觉得确实值得,点一下「升级」,它就变成全校可见的群体事件,首页像校历一样提示。
分类上也没有只限定「考试」:交论文、报名截止都能用,用的是同一套机制。首页显示与否还交给小程序本地偏好,全校事件默认不上首页,学生逐条「关注」后才显示——不是人人都要考四级、考研,默认全推会打扰大多数人。
这件事的思路是:能让用户的使用行为自己产生运营数据,就不要依赖运营去手动维护。 运营只需要偶尔看一眼聚合表。

后台长什么样、怎么放进项目

技术上我想得很简单:不单独起一个项目 。
管理页是一个 Vue 3 + Element Plus + Vite 的单页应用,构建产物直接输出到后端项目的静态资源目录,和后端打进同一个 jar 。于是:

  • 后台页面和 API 同源 ,不用处理跨域;
  • 部署还是那一个 jar,不用多维护一个前端服务;
  • 构建脚本 run_build.py 会先构建后台再打 jar,一条命令搞定。

用 Element Plus 这类现成的组件库,道理也很朴素:后台里表格、表单、弹窗、分页、各种筛选都是成熟的需求,没必要自己造,把精力留给「这个后台到底要管什么」更划算。

最后:每一个按钮背后都有一件具体的事

回头看这份功能清单,很多功能都能对上一个具体的问题,是一件一件被现实推出来的 :微博限流,就有了令牌仪表盘;代理出过故障,就有了探活和卡住用户;被风控过,就有了可调的节流参数;想知道谁在反复触发敏感词,就有了命中记录。
所以如果你也在做类似的小程序,一个建议是:别一上来就规划一个大而全的后台,每次线上出了一件让你手忙脚乱的事,就问自己一句:「如果后台里有个页面,我是不是三十秒就能处理掉?」 然后只做那个页面。
后台暴露在公网上,安全就不能马虎。下一篇讲讲它有哪些防护。

最后修改:2026 年 11 月 12 日
如果觉得我的文章对你有用,请随意赞赏