news 2026/10/26 1:07:15

微信小程序毕业设计校友会系统:源码落地与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微信小程序毕业设计校友会系统:源码落地与避坑指南

简介:面向毕业设计场景的微信小程序校友会系统完整项目包,适合小程序开发、Java后端与MySQL数据库学习者参考。系统基于微信小程序开发工具与Java后端、MySQL实现B/S架构,覆盖管理员、用户、校友三类角色,包含校友信息管理、生活动态发布、表白墙登记、校园论坛发帖评论、兼职信息审核、校园新闻查看等核心功能,可直接作为课程设计或毕业设计的完整方案复用,从页面交互到后台逻辑均有完整实现。压缩包共1203个文件,约32.91MB,以png图片素材、js与vue前端逻辑、java后端代码、wxml/wxss小程序页面、json配置及sql数据库脚本为主,另含数据库初始化脚本、项目说明文档,并附演示视频和安装运行构建脚本,便于快速搭建环境、对照前后端交互、数据表结构及项目模块划分。目前已有258人学习下载,适合需要快速构建校园社交类小程序并掌握完整项目链路的中高级开发者参考。

1. 微信小程序毕业设计做校友会系统:这套 .rar 交付到底值不值得接

“微信小程序毕业设计”这个组合词出现在搜索栏里,多半是临近开题或者答辩前,时间已经被压缩到按天算的时候。真到了这个节点,源码、演示视频、说明文档和数据库一起打包在这个 .rar 里,意味着你不需要从零设计业务模型,也不用为建表纠结,核心任务变成三件事:把它跑通、把它讲明白、再给它加一点你自己的增量。校友会这个题材之所以高频出现在毕设里,是因为业务面不大不小:注册登录、校友名录、活动报名、留言互动,这几条主流程既够你写满一篇论文的截图和表格,又不会膨胀到工作量收不住。这套东西适合两类人:一是手里还没有成型项目,想用一到两周把全栈流程走通并录出能交代的演示视频;二是代码已经写了一半,但卡在数据库联调和接口对接上,想借这套工程反向梳理自己方案的。

2. 校友会系统的功能骨架:页面、接口与数据库三张图先画在脑子里

毕业设计跟企业项目最大的差别是,老师不只看功能跑没跑起来,还要看功能是不是“成体系”。哪怕交付包里的代码已经全写好,你也要能在答辩时画出三张图:小程序端的页面结构图、后端的接口图、数据库的表结构图。这三张图画顺了,论文的第二章和第三章也就跟着有了骨架。

2.1 小程序端:首页、校友名录、活动中心和“我的”四个页面模块

绝大多数这类校友会小程序,不会超出四个底部 Tab 的范围。底部导航栏(tabBar)的结构通常把首页动态、校友名录、活动列表和个人中心放在一起,页面职责分得很清楚:首页负责展示校友会新闻和最新动态,名录负责按专业或毕业年份搜索校友,活动中心负责活动列表和报名入口,个人中心承载登录态、个人资料和报名记录。

页面结构是微信原生小程序的标准四件套,每个页面由 .wxml、.wxss、.js、.json 四个文件组成,tabBar 在全局文件 app.json 里配置,常见写法是下面这个形式:

{ "pages": [ "pages/index/index", "pages/alumni/alumni", "pages/activity/activity", "pages/my/my" ], "tabBar": { "color": "#999999", "selectedColor": "#1a73e8", "list": [ { "pagePath": "pages/index/index", "text": "首页" }, { "pagePath": "pages/alumni/alumni", "text": "校友" }, { "pagePath": "pages/activity/activity", "text": "活动" }, { "pagePath": "pages/my/my", "text": "我的" } ] } }

这个文件的关键在于 pagePath 必须和 pages 数组里的路径一一对应,少写一个,编译阶段就会直接报错。我拿到一份陌生源码后的第一个习惯,不是急着看业务代码,而是先把 app.json 从头读一遍,确认页面注册和 tabBar 一致,这是所有微信小程序排查的起点。如果你想让顶栏视觉更自由,可以给单个页面配置"navigationStyle": "custom",但一旦自定义,状态栏高度、胶囊按钮位置、顶部导航栏高度都要自己适配,这是搜索“微信小程序顶部导航栏高度”时最常遇到的场景。对毕设来说,用默认导航栏改标题和主题色就够了,自定义导航栏的适配成本不是现阶段该花时间的。

校友名录页的常见实现是 wx.request 拉接口列表,渲染时按毕业年份、专业做下拉筛选。开发阶段因为后端可能还没有上线的 HTTPS 域名,开发者工具右上角的“不校验合法域名”开关能解决模拟器里的请求问题,但真机预览时域名校验依然会生效,这一块在第四章展开。

交付包里如果已经有演示视频,你可以对着视频先把每个页面的功能点标出来。注意,视频里录的页面顺序和源码实际可点的路径可能不一致,这个坑在第四章最后一条单独说。

在“我的”页面,个人信息区和登录按钮是核心。这里往往出现两个小程序的教科书级知识点:页面接受登录态后的条件渲染,以及未登录状态下点击功能时的跳转提示。源码里通常会有一个wx.getUserProfile或者新版头像昵称填写能力的调用,这部分的代码改造成本很低,但它是答辩时老师最容易截图追问的交互点。

2.2 后端模块:校友、活动、留言和审核四条业务线

后端在毕业设计里通常是 Spring Boot 或 Node.js,具体看交付包里的文件类型。不管技术栈是什么,接口设计都绕不开四类业务逻辑:校友注册与信息维护、活动发布与报名、留言发布与管理、管理员对内容的审核和删除。

接口风格基本是 RESTful,路径按资源命名。典型的接口清单长这样:

接口路径(常见命名)方法说明
/user/loginPOST微信登录,code 换 openid 和 session_key
/user/registerPOST完善手机、入学年份、专业、班级等信息
/alumni/listGET校友名录分页列表
/alumni/updatePOST校友修改自己的资料
/activity/listGET活动列表分页
/activity/registerPOST活动报名
/message/addPOST发布留言
/message/listGET留言列表(可带父留言 id 做楼中楼)

拿到源码后在 IDE 里全局搜一下路由映射,把每个接口对应到具体代码文件,这个过程能帮你短时间内建立代码地图。有些工程自带 Swagger 接口文档页面,后端启动后访问/swagger-ui.html就能看到可直接调试的接口列表。带 Swagger 的交付包说明作者工程素养不错,你也要学会在答辩时演示这个页面——它能直接证明“接口是真实可调的”。

管理员端多数不单独做一个小程序页面,而是走另一个后台 Web 项目,或者直接通过修改数据库状态来审核。如果包里的管理员后台比较简陋,第五章会给出一个数据库层的审核状态改造方案,不用大动前端。

2.3 数据库设计:校友表、活动表、报名表和留言表的关系

数据库是这份交付包里的核心资产。“数据库”三个字不只是 .sql 文件本身,还代表你要能画出 E-R 图。校友会系统的核心表通常不超过五张,校友表(alumni)存 openid、姓名、性别、入学年份、专业、班级、城市、行业、公司、职位、手机号;活动表(activity)存标题、封面、详情、开始时间、地点、人数上限;报名表(registration)是校友和活动的多对多中间表;留言表(message)存发送人、内容、创建时间和父留言 id。

用报名表来举例,看一个简化的建表语句:

CREATE TABLE `registration` ( `id` INT PRIMARY KEY AUTO_INCREMENT, `alumni_id` INT NOT NULL, `activity_id` INT NOT NULL, `status` TINYINT DEFAULT 0 COMMENT '0=已报名 1=已签到 2=已取消', `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY `uk_alumni_activity` (`alumni_id`, `activity_id`, CONSTRAINT `fk_reg_alumni` FOREIGN KEY (`alumni_id`) REFERENCES `alumni` (`id`), CONSTRAINT `fk_reg_activity` FOREIGN KEY (`activity_id`) REFERENCES `activity` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

这里有两行值得盯着看。第一行是UNIQUE KEY uk_alumni_activity (alumni_id, activity_id),它保证了同一人对同一活动只能有一条报名记录,这比在代码里先查再插更可靠。第二行是两个外键约束,它们会强制报名表中的校友和活动必须真实存在。很多简化版项目为了导入省事会去掉外键,但论文里的 E-R 图和数据库设计章节需要外键来撑内容,所以导入数据库后要确认外键还在。

拿到 .sql 文件后,不要急着双击导入,先打开文件看三件事:字符集是否 utf8mb4、是否包含预设的演示数据、建表语句里有没有外键。字符集不对会在导入后直接乱码,演示数据决定了你演示时页面是否好看——如果一张空表跑起来,答辩截图会非常尴尬。

3. 从 .rar 到跑通:数据库导入、后端启动和小程序联调的完整路径

“源码”躺在压缩包里不算跑通,你的任务是把它变成在自己电脑上能点来点去的小程序。这一章按最常见的 Spring Boot + MySQL + 微信原生小程序技术栈来拆步骤,每一步都给出能直接抄的指令,也会说明每步失败时最可能的原因。

3.1 环境工具链:微信开发者工具、JDK 和 MySQL 的版本匹配

校友会系统后端若是 Spring Boot,工具链的版本匹配有一条铁律:Spring Boot 2.x 配 JDK 8,Spring Boot 3.x 配 JDK 17。硬拿 JDK 17 跑旧项目,会在编译期遇到 javax 包缺失和不兼容的报错;反过来新项目用旧 JDK 也起不来。拿到项目先看根目录,存在 pom.xml 是 Java Maven 项目,存在 package.json 是 Node 项目,这个判断决定了你接下来安装哪套环境。

微信开发者工具用稳定版即可,不建议追 Beta 版。Beta 版经常会更新底层调试协议,导致老项目里某些生命周期函数的行为发生变化,排查起来非常头疼。MySQL 5.7 和 8.0 都能跑校友会系统,但 8.0 的默认认证插件 caching_sha2_password 会在连接时多一个坑,后面第四章专门讲修复方式。

3.2 数据库导入:命令行导入、Navicat 导入和字符集处理

推荐用命令行导入,出错时反馈最直接。假设 .sql 文件已经解压到 D 盘根目录:

mysql -u root -p < D:\alumni.sql

导入完立刻检查三件事,数据库是否存在、表是否齐全、数据是否在:

SHOW DATABASES; USE alumni; SHOW TABLES; SELECT COUNT(*) FROM alumni;

如果导入报错,常见情况是 .sql 文件里只有建表语句、没有建库语句。此时要先手动建库再导入:

CREATE DATABASE alumni DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE alumni; SOURCE D:\alumni.sql;

参数说明:SOURCE是 MySQL 命令行内部指令,等效于mysql < 文件,适合需要先建库再导数据的场景。字符集选 utf8mb4 而不是 utf8,是因为校友信息里可能出现表情符号和生僻字,用 utf8 会在写入时变成问号。

如果交付包里给的不是 .sql,而是 .db 或 .mdf,处理方式完全不同。.db 常见于 SQLite,后端需要换数据库方言和驱动;.mdf 是 SQL Server 文件,不能直接搬到 MySQL。遇到这两种情况先看说明文档里的技术栈描述,硬导只会浪费时间。

3.3 后端启动:修改数据源、启动服务并用接口自测

以 Spring Boot 为例,解压后端源码后先找src/main/resources/application.yml或.properties,重点核对数据源参数:

spring: datasource: url: jdbc:mysql://127.0.0.1:3306/alumni?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456

四个点必须对着本地环境逐一改:数据库 IP 端口、库名、用户名、密码。serverTimezone=Asia/Shanghai不要删,MySQL 8 时区参数缺失会直接连接报错。如果你用的是 MySQL 8.0 而且驱动版本偏老,url 里还要加allowPublicKeyRetrieval=true,否则会报“Public Key Retrieval is not allowed”。

启动后端可以直接在 IDEA 里运行主类,命令行方式也等价:

mvn spring-boot:run

看到Tomcat started on port(s): 8080后,用 curl 做接口自测:

curl http://127.0.0.1:8080/alumni/list

返回 JSON 数组说明后端和数据库通路已经建立;返回 404 就检查项目里是否配置了 context-path(比如 /api),这个前缀信息直接影响小程序端配置。

3.4 小程序端联调:替换 AppID、修改 baseUrl 和登录链路验证

用微信开发者工具导入解压后的小程序目录,在项目详情里确认 AppID。没有自己的小程序账号可以先用测试号,但测试号会限制部分能力,比如获取手机号和部分开放接口,毕设阶段通常够用。

接口地址配置通常在根目录的 config.js 或 utils/api.js 里,长这样:

// config.js 是小程序端统一维护接口地址的地方 module.exports = { baseUrl: 'http://127.0.0.1:8080' }

注意,127.0.0.1在小程序开发者工具的模拟器里能访问你电脑上的后端,但手机预览时指向的是手机自己。真机调试要把 baseUrl 改成电脑的局域网 IP,同时开发者工具需要勾选“不校验合法域名”,真机调试需要在手机端打开调试模式。大量项目跑在电脑上一切正常、一上手机就白屏,十有八九是这一步没改。

最终验证一条完整链路:打开小程序首页 → 点击登录 → 触发 wx.login → 调 /user/login → 后端拿 code 换 openid → 数据库校友表多一条记录 → 页面显示登录成功。这条链路中任何一步断掉,都能在第四章的排查列表里找到对应位置。

4. 校友会系统落地避坑:5 个高频报错的现象、原因与处置

这一章是拿源码落地时最值钱的部分。这 5 个问题几乎会在这类项目的生命周期里至少出现一次,按“现象 → 原因 → 解决”的顺序写,你也可以把它当作排查手册来用。

4.1 登录一直转圈,接口报“invalid code”或“40029”

现象:点击微信登录后按钮一直 loading,控制台显示 /user/login 返回 500,后端日志里有errcode: 40029, errmsg: invalid code。

原因:wx.login 拿到的 code 是一次性的,有效期只有几分钟,且同一 code 只能用一次。常见误用是页面 onLoad 时就调了一次 wx.login 拿 code,存下来之后在点击登录时拿来用;或者前一次请求超时,用户又点了第二次,第一次的 code 已经失效。

解决:把 wx.login 挪到点击登录的事件回调里,保证 code 是“用户点击瞬间”现场获取的。再检查后端配置里的 AppID 和 secret 是否和小程序账号一致;如果用的是测试号,测试号的 AppID 是企业号配置里没有的,后端要跟着改。

4.2 首页数据空白,Network 面板显示请求失败或 404

现象:小程序能打开但列表是空的,开发者工具 Network 面板显示请求失败、404 或 CORS 错误。

原因:三类情况最常见。后端配置了 context-path(比如 /api),小程序 baseUrl 里没带;后端没有启动,或者端口和 baseUrl 不一致;后端没开跨域,接口本身有数据但小程序被 CORS 拦。

解决:先用 curl 打一次后端接口,确认路径、端口、前缀三者都正确,再回小程序改 baseUrl。CORS 问题在 Spring Boot 里需要配置跨域过滤器,或在控制器上加@CrossOrigin。定位域名校验问题和 CORS 问题时,用抓包工具看一下完整请求和响应头,方向会清晰很多。

4.3 后端连不上 MySQL,报“Public Key Retrieval is not allowed”

现象:启动后端时数据源初始化失败,控制台报Public Key Retrieval is not allowed。

原因:这是 MySQL 8.0 的 caching_sha2_password 认证插件带来的一个典型问题。老版本 JDBC 驱动和部分连接池配置下,客户端无法从服务器获取公钥完成密码交换。

解决:在 JDBC url 末尾加参数,同时用 SQL 检查用户认证插件类型:

# 在 application.yml 的 url 末尾追加 jdbc:mysql://127.0.0.1:3306/alumni?useSSL=false&allowPublicKeyRetrieval=true
SELECT user, host, plugin FROM mysql.user WHERE user = 'root';

如果 plugin 是 caching_sha2_password,可以直接改成 mysql_native_password 做兼容,但更省事的做法是保留插件、让连接 url 带上 allowPublicKeyRetrieval 参数。

4.4 导入数据库后中文全是问号或乱码

现象:导入 .sql 后打开表,中文显示为???或符号乱码,小程序页面渲染出来同样乱。

原因:字符集三层不一致。.sql 文件本身的编码、数据库的默认字符集、命令行客户端的字符集,这三者只要不一致就会出乱码。最常见的是文件是 utf8mb4、数据库是 utf8、Windows 命令行客户端是 gbk。

解决:统一到 utf8mb4。导入前先执行SET NAMES utf8mb4;再 SOURCE。如果数据已经导乱了,最快的办法不是改表,而是重建库重新导。ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4只能改表结构,已经乱掉的数据无法恢复。

4.5 演示视频里的界面和源码实际运行不一致

现象:交付包视频里演示的流程和代码跑出来的效果对不上,比如视频里有通讯录搜索按钮,当前代码里找不到;或者数据库里的演示数据与视频账号不匹配。

原因:交付包的打包时间不一致。演示视频可能是项目早期录制的,后面代码改过、表结构动过,说明文档却没跟上。这是这类交付物最常见的信息差,不是你的电脑出了问题。

解决:以源码实际运行现状为准,重新录制一套演示视频,不要沿用包里的旧视频。论文截图如果用了旧界面,答辩现场一对比就会露馅。重新录制的脚本放在第六章给出,照着走一遍基本能覆盖所有主流程。

5. 拿源码做出差异化:校友审核、防重复报名和页面改造的三个落点

用源码做毕设最大的风险是指导老师一眼看出这是公共模板。不需要重写全部代码,只需要在两三个功能点上做出“有痕迹的增量”,让前端、后端和数据库三个层面都能讲出新方案,这篇论文就有了自己的立论基础。

5.1 给校友注册加审核状态:数据库字段、接口和页面联动一气呵成

最基础的版本往往注册完就直接进入名录,这和企业级场景不符。加一个审核机制,立刻让系统多了一个完整的状态机可以讲:待审核、已通过、已驳回。

数据库层面在 alumni 表加一个字段:

ALTER TABLE alumni ADD COLUMN status TINYINT NOT NULL DEFAULT 0 COMMENT '0=待审核 1=已通过 2=已驳回';

后端新增两个接口,一个供管理员获取待审核列表,一个用于提交审核结果。小程序端做两处联动:个人中心增加“我的审核状态”展示,校友名录页的列表查询只查 status=1 的数据。这个小改造动了数据库、接口、小程序三个层面,论文里的需求分析、流程图、接口设计都能多出一整节,工作量却控制在两天以内。

5.2 活动报名防重复:从代码先查再插升级到数据库唯一约束

前面第二章提到唯一索引,这里把它做成一个完整的毕业设计实验点。最基础的报名功能通常是“service 层先查有没有报名记录,没有就 insert”,在单次点击下没问题,但连点或并发请求时会出现检查与插入之间的时间差,导致同一个人有两条报名记录。

改造分三层:前端按钮在发起请求后立即置 loading 并禁用;后端保留先查再插的逻辑作为第一道拦截;数据库唯一索引作为最终兜底。答辩时可以用一个简单的压测命令对比效果:

# 用 ab 模拟 20 个并发报名请求 ab -n 20 -c 20 -p register.json -T application/json http://127.0.0.1:8080/activity/register

不加唯一约束时大概率会产生重复记录,加了之后后插入的请求会被数据库拒绝。这个对比截图放进论文,“实验验证”这一节就有了实体支撑,相比干巴巴地写“本系统采用了唯一约束”,说服力完全不同。

5.3 小程序端改造三件套:导航栏、表单组件和本地缓存

小程序给答辩评委最直观的感受来自 UI 细节。三个低成本高感知的改造建议:

第一,导航栏和主题色。把默认蓝色换成贴近校友会主题的正式色,比如学校主色调或深红色系,同时在app.json里调整全局的 window 背景色。这一处改动几十秒完成,但会让整个工程看起来像定制过。

第二,注册页和资料页的表单组件。入学年份用 picker 下拉选择,性别用 radio 单选组件,而不是让用户手动输入。原生单选框和 picker 的代码量不大,但交互体验上的提升非常明显。

第三,首页动态列表加缓存。用wx.setStorageSync在首次加载后把列表数据写入本地 Storage,下次打开先渲染缓存,再在后台请求新数据覆盖。弱网环境下用户打开小程序不会长时间白屏,这个体验细节在演示时很有说服力。

如果需要注册时自动带出手机号,会碰到一个现实约束:微信小程序的获取手机号能力要求小程序账号完成企业主体认证,个人主体和测试号无法使用。毕设阶段的合理做法是手机号手动输入加正则校验,在论文需求分析里预留一句“已为后续接入微信手机号快捷验证保留字段”,既展示你对这个能力的了解,又不至于卡在账号资质上。

6. 把演示视频和答辩话术调成同一个版本

演示视频是答辩的门面。包里带的视频是别人录的,你的任务是在自己电脑上重录一版,并且用这版视频反向校验收源码里每个功能点。我的习惯是先重置数据库,恢复到三到五个演示账号、两场活动、两条留言的干净状态,然后按一条固定路径从头点到尾:首页看动态 → 微信登录 → 完善个人信息 → 校友名录搜索 → 活动详情页报名 → 个人中心查看报名记录 → 发一条留言 → 切到管理员视角审核一条注册记录。这条路径覆盖了微信小程序、校友会系统、数据库三个关键词的完整闭环,也是答辩时最容易被连环追问的八个环节。

每录完一步,我会追问自己三个问题:这一步对应哪张数据表?接口路径是什么?如果报错,错会出现在哪个层面?前两个答不上来说明对代码还很生,带着问题回头翻源码;第三个答不上来也不用太慌,说明还没摸清排错路径。毕业设计翻车的高发区,恰好就是演示视频里有、自己却没亲手点过的那一步。最后一个实用技巧:录屏时把微信开发者工具的 Network 面板和 Console 面板一起录进画面。答辩当场出问题不一定丢分,能打开日志定位到具体请求和状态码的人,反而会让评委觉得工程能力扎实。希望这套流程能帮你把压缩包真正变成自己的作品,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/26 1:06:49

CAN总线家族全解析:经典CAN、CAN FD、CAN XL与TTCAN选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/26 1:06:33

电子信息工程四年规划:嵌入式/芯片方向如何攒出作品集?

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/26 1:06:26

图腾柱PFC模拟控制IC:700W/3kW钛金电源设计解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/26 1:05:36

98.6%准确率识别手写数字:Omega-AI CNN卷积神经网络mnist实战

【免费下载链接】Omega-AI Omega-AI is a Java-based deep learning framework that helps you quickly build neural networks for inference and training. Its engine supports automatic differentiation, multithreading, and GPU acceleration with CUDA and cuDNN. 项目…

作者头像 李华
网站建设 2026/10/26 1:04:23

GIS管网资源包:从数据组织到百度地图叠加的完整实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华