JavaWeb电子商城毕设:JSP+Servlet+JDBC+MySQL8实战
简介面向毕业设计的JavaWeb电子商城系统源码与数据库配套包采用JSPServletJSTLELJDBC经典技术栈数据库为MySQL8开发环境为EclipseTomcat7JDK10适合计算机专业学生用于课程设计、毕业设计参考、功能扩展或二次开发。资源包共417个文件压缩后仅9.1MB包含42个Java源码文件、20个JSP动态页面、28个HTML静态页面、12个CSS样式、9个JS交互脚本、1个SQL数据库脚本及4个jar运行依赖另有216张JPG商品图、30张PNG图标等素材用于页面展示文件类型丰富便于按需查看与调试。项目覆盖用户、商品、分类、购物车、订单等商城核心模块代码中包含实体类、DAO类、Servlet控制类与JSP视图层体现了经典JavaWeb分层开发思路可帮助理解JDBC操作MySQL8及数据流转过程。目前已有105人学习下载对正在准备电商类毕业设计的同学而言足以快速导入Eclipse运行验证并在此基础上按需修改完成设计任务。1. 毕业设计不要只做页面这套JavaWeb电子商城能直接跑能答辩每年毕业设计季节总能看到不少同学抱着厚厚的电商系统源码叹气——要么是Spring全家桶堆出来的黑匣子要么是只有前端页面的静态Demo。而这份基于JavaWeb的电子商城系统走的是最经典的JSP Servlet JSTL EL JDBC MySQL8技术路线没有花哨的框架每一行代码都能在答辩现场讲清楚。它涵盖用户注册登录、商品分类浏览、购物车管理、订单查询这些电商核心链路连验证码工具类都给你写好了拿到手导入Eclipse配置好环境就能启动。这套项目对两类人尤其合适一是准备毕业设计需要「能讲明白、能现场改」的JavaWeb课题二是刚学完Servlet想看看一个完整商城项目该怎么组织代码结构。它不是教学Demo那种一个文件写到底的写法而是把Dao层、Servlet控制层、JSP视图层分开Controller里逻辑清晰改起来容易写论文时画架构图也有东西可画。下面我把这套源码的项目结构、核心流程、启动步骤和改造方向一次讲透。2. 技术选型与项目结构JSP Servlet JDBC 为什么还能打2.1 这套技术栈的组合逻辑先说一个反直觉的事实Spring Boot 虽然火但很多高校的JavaWeb课程设计和毕业设计评审老师更看重你是否理解HTTP请求是怎么被处理的、SQL是怎么被执行的。这套项目用 JSP Servlet JSTL EL JDBC 的组合恰好把 JavaWeb 最原始也最核心的全链路展示出来了。Servlet 负责接收浏览器请求、调用业务方法、跳转页面JSP 负责视图渲染配合 JSTL 和 EL 表达式避免在页面里写大量 Java 脚本片段JDBC 负责数据库操作而连接信息统一管理。MySQL8 相比老版本的 MySQL5.7在连接驱动和认证方式上有差异这套源码里已经处理掉了你用新版数据库也不用担心连不上。2.2 源码包里的类与职责划分从编译后的 class 文件命名来看这套商城系统的分层非常典型。我按 MVC 思路帮你把类归类一下分包类别具体类名职责说明实体模型OEONG_USER、OEONG_PRODUCT、OEONG_CART、OEONG_CATEGORY对应数据库中的用户表、商品表、购物车表、分类表字段和表结构一一映射数据访问层OEONG_USERDao、OEONG_PRODUCTDao、OEONG_CARTDao、OEONG_CATEGORYDao封装对每张表的增删改查SQL使用JDBC操作数据库控制层DoProductAdd、CartAdd、SelectProductView、OrderSelect继承HttpServlet处理具体业务请求工具类CodeUtil验证码生成工具用于登录或注册时的校验这里有一个新手容易忽略的细节这些类名看上去没有用分层后缀区分比如 DoProductAdd 和 CartAdd 直接把动作写在类名里而不是常见的管理员商品管理Servlet。这说明作者是按「页面操作」来划分控制器的这种方式应付课设有个好处——答辩时老师问「点一下加入购物车后台执行什么」你能直接说对应的是 CartAdd 这个Servlet定位非常快。2.3 隐含的数据库设计思路虽然资源里没有直接列出建表SQL但从 Dao 类名和 Servlet 名可以反推核心表结构。用户表至少要包含用户名、密码、邮箱或手机号商品表要有商品名、价格、库存、所属分类ID购物车表一般设计为用户ID 商品ID 数量 加入时间分类表则是分类ID和分类名称。订单相关功能只看到 OrderSelect 类说明这套系统更偏向「前台购物 后台简单管理」的课设定位订单模块以查询为主没有覆盖完整的订单流程。如果你在导入项目时发现数据库连接报错大概率是 root 用户的密码和你本地不一致改数据库配置即可后面第 5 章我会专门讲这个过程。3. 核心模块拆解从用户注册到商品入库的完整链路3.1 用户模块注册时的表单处理与数据落库用户操作是商城系统的入口。以注册为例典型流程是用户在 register.jsp 填写用户名、密码、验证码提交后由对应的注册Servlet接收参数先调用 CodeUtil 校验验证码再通过 OEONG_USERDao 查询用户名是否已存在最后执行插入操作。下面是符合这套源码风格的注册Servlet核心逻辑WebServlet(/register) public class RegisterServlet extends HttpServlet { private static final long serialVersionUID 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding(UTF-8); String username request.getParameter(username); String password request.getParameter(password); String code request.getParameter(code); // 校验验证码防止机器注册 String sessionCode (String) request.getSession().getAttribute(code); if (!code.equalsIgnoreCase(sessionCode)) { request.setAttribute(msg, 验证码不正确); request.getRequestDispatcher(register.jsp).forward(request, response); return; } OEONG_USER user new OEONG_USER(); user.setUsername(username); user.setPassword(password); OEONG_USERDao dao new OEONG_USERDao(); boolean success dao.insert(user); if (success) { response.sendRedirect(login.jsp); } else { request.setAttribute(msg, 用户名已存在); request.getRequestDispatcher(register.jsp).forward(request, response); } } }这段代码有几个关键参数需要说明。request.getParameter()负责从表单取出用户提交的数据request.setCharacterEncoding(UTF-8)必须写否则中文用户名会变成乱码sessionCode是从 Session 中取出生成验证码时存入的值这里用equalsIgnoreCase比较可以让验证码不区分大小写提升用户体验。加入购物车的Servlet CartAdd 逻辑逻辑与这段同构拿到商品ID和数量参数先查库存再写入购物车表。3.2 商品展示SelectProductView 如何联动分类和商品表商品浏览是商城门面。分类导航通常通过左侧菜单展示所有 OEONG_CATEGORY点击某个分类后SelectProductView 这个Servlet接收分类ID参数调用商品Dao查询该分类下的商品列表转发到商品列表页。商品详情页展示单个商品的完整字段加入购物车按钮直接通过URL参数把商品ID传给购物车Servlet。以下是典型的商品列表查询实现protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int categoryId Integer.parseInt(request.getParameter(categoryId)); OEONG_PRODUCTDao productDao new OEONG_PRODUCTDao(); ListOEONG_PRODUCT productList productDao.findByCategory(categoryId); request.setAttribute(productList, productList); request.getRequestDispatcher(productList.jsp).forward(request, response); }findByCategory内部执行 SQL 时使用了 PreparedStatement 防止SQL注入这是 JDBC 开发中必须养成的习惯。分类ID参数从请求中解析如果前端传入非数字字符直接用Integer.parseInt会抛异常所以生产级代码一般会加一层 try-catch 或正则校验但课设层面做到这一步已经足够应对答辩。3.3 核心JSP页面调度与JSTL渲染这套系统没有使用前后端分离页面由 JSP JSTL 渲染。以商品列表页为例Servlet 把 List 对象放到 request 域后JSP 页面通过 EL 表达式${productList}获取集合用 JSTL 的c:forEach标签循环遍历商品再搭配c:if做条件判断。这种做法的好处是页面里不写 Java 代码JSP 更干净而且 JSTL 标签的语义直观答辩时老师扫一眼就明白页面在干什么。% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % div classproduct-grid c:forEach items${productList} varproduct div classproduct-item h3${product.name}/h3 p价格${product.price}/p p库存${product.stock}/p a hrefCartAdd?productId${product.id}加入购物车/a /div /c:forEach /div这里有一个非常实用的参数说明c:forEach的items属性指向Servlet传入的集合变量名var是循环变量名两者可以任意起名但要保持一致。如果页面显示空白优先检查Servlet里request.setAttribute(productList, productList)的key是否和页面一致这是新手最常见的翻车点。3.4 下单与订单查询OrderSelect 的定位理解从类名看OrderSelect 负责订单查询。在很多课设项目中订单模块会做成「购物车生成订单 → 订单列表展示状态」扣除库存的操作放在提交订单的事务里。如果需要扩展这块正常的改造思路是新增一个 OrderAdd Servlet 负责接收购物车数据、生成订单号、批量插入订单明细同时用事务保证多张表操作的安全。我在实现时一般会用 mysql8 的Transactional概念代替手动事务控制但既然这套项目是 JDBC 直连就在 Service 层用 Connection 手动控制 commit 和 rollback。对于课设答辩只要把 JDBC 的事务步骤讲清楚老师的通过率反而会更高。4. 运行环境配置Eclipse JDK10 Tomcat7 MySQL8 的兼容性处理4.1 为什么是这个环境组合很多同学看到 Tomcat7 和 JDK10 会觉得奇怪——Tomcat7 不是只支持到 Java7 吗这个组合在实际运行时需要注意一个兼容性问题JDK10 编译的 class 文件版本高于 Tomcat7 支持的范围直接部署会报 UnsupportedClassVersionError。常见解决办法有两个一是把开发环境改成 JDK8 Tomcat8 或 Tomcat9这也是我推荐的方案二是在 Eclipse 里把项目编译级别设置为 1.8确保编译产物兼容 Tomcat7 运行时。如果你本机已经装了 JDK8建议直接用 JDK8 Tomcat8 的组合稳定且资料好查如果你只有 JDK10 或更高版本可以在 Eclipse 项目的 Java Compiler 设置里把 Compliance Level 调到 1.8Project Facets 里 Dynamic Web Module 选 3.0Tomcat 版本过高或过低都会影响 JSP 的编译Tomcat8.5 是最省心的版本4.2 导入 Eclipse 的完整步骤拿到源码后先别急着看代码把项目导入 IDE 是第一步。由于这套源码打包结构不是 Maven 标准目录导入时选择「导入已存在项目」而不是「导入 Maven 项目」。以下是步骤清单将源码解压到本地目录确认包含 src 目录、WebContent 或 webroot 目录、以及 .classpath 和 .project 文件Eclipse 中选择 File → Import → General → Existing Projects into Workspace选择源码根目录后Eclipse 会自动识别项目不要勾选 Copy projects into workspace保持源码原地引用如果项目没有自动添加 Tomcat 运行时右键项目 → Properties → Targeted Runtimes勾选你配置的 Tomcat 版本把 mysql-connector-java-8.0.x.jar 放到 WebContent/WEB-INF/lib 下Eclipse 会自动将其加入构建路径导入完成后在控制台切换到 Servers 视图启动 Tomcat浏览器访问http://localhost:8080/项目名/就能看到首页。如果报 404检查项目访问路径一般右键项目 → Properties → Web Project Settings 里可以修改 Context Root。4.3 数据库初始化脚本的处理这套源码附带数据库文件你需要先在本地 MySQL8 中创建数据库并导入数据。具体操作是先启动 MySQL 服务然后用命令行或可视化工具执行 SQL 脚本。命令行导入语句如下mysql -u root -p ecs.sql数据库连接信息一般在 jdbc.properties 或 DBUtil.java 里配置。JDBC URL 默认使用3306端口MySQL8 的驱动类名是com.mysql.cj.jdbc.Driver连接串要加上serverTimezoneAsia/Shanghai参数防止时区报错。如果连接失败先在命令行测试 root 密码是否正确再看驱动 jar 是否放在了正确位置。5. 常见踩坑与问题排查从编译报错到运行期异常5.1 页面中文乱码现象商品名称和用户名显示为问号。 原因JSP 文件编码和 Servlet 请求编码不一致或者数据库连接串没指定字符集。 解决统一将 JSP 页面pageEncoding设为 UTF-8Servlet 在 doGet/doPost 开头写request.setCharacterEncoding(UTF-8)JDBC 连接串加characterEncodingutf8。这三处全部处理后再测试问题基本消失。5.2 Tomcat 启动立即崩溃现象Tomcat 启动后几秒内自动停止日志中显示严重错误。 原因大多是缺少数据库驱动 jar或 web.xml 中的 Servlet 映射类找不到。 解决先查看 Tomcat 的 localhost 日志如果提示 ClassNotFoundException 且类名包含 jdbc说明 mysql-connector jar 不在 WEB-INF/lib如果是 Servlet 类找不到检查 web.xml 中 servlet-class 的包路径是否和源码一致。5.3 JDK 和 Tomcat 版本不匹配导致无法编译 JSP现象首次访问页面时 500 错误日志显示 UnsupportedClassVersionError。 原因JRE 运行环境版本高于 Tomcat 支持的字节码版本。 解决在 Eclipse 中右键项目 → Properties → Java Compiler勾选 Use compliance from execution environment并选择 JavaSE-1.8。注意这只是编译级别实际运行时仍要保证 Tomcat 使用的 JDK 是 8。5.4 登录成功却跳不回首页现象注册成功或登录成功后点击跳转一直停留在原页面。 原因用了 forward 而不是 sendRedirect地址栏不变或者 Session 写入后又因为页面跳转被清掉。 解决登录成功后使用response.sendRedirect(index.jsp)而不是request.getRequestDispatcher(index.jsp).forward()。forward 是服务器内部跳转浏览器地址不变刷新会重新提交表单sendRedirect 是重定向相当于重新发起一次请求更符合登录后跳转的业务语义。这是答辩时老师经常问的一个点一定要能讲出区别。6. 二次开发建议把课设变成能写进简历的项目拿到这套源码不建议直接提交。花一个星期做下面三个方向的改造项目深度就会完全不同。第一个方向是把购物车功能升级当前 CartAdd 只是向购物车表插入记录你可以补充购物车列表页、修改数量、删除商品、计算总价四个功能数据库表增加一个小计字段这样「购物车」就从一个Servlet变成了一个完整模块。第二个方向是引入 Maven 管理依赖并拆分子系统。如果你对 Maven 熟悉把项目转成 war 包会是个加分项——把 WEB-INF/lib 下的 jar 全部删除在 pom.xml 里声明 Servlet API、JSTL、MySQL Connector 的依赖构建时用mvn clean package打包。这样项目就从 Eclipse 深度绑定变成了标准化的Web工程扔到任何机器上都能构建。但要注意JDK8 是兼容性最稳的版本Maven 编译器插件把 source/target 设为 1.8不要追求高版本。第三个方向是补一个后台订单管理模块。课设中订单查询是前台视角你可以在 admin.jsp 页面增加订单列表、按用户查订单、按时间筛订单三个查询入口对应新增一个 AdminOrderSelect Servlet。我发现很多同学喜欢把代码堆在一个Servlet里但拆成多个Servlet反而容易讲代码。我自己在做一个类似的模块时习惯每个Servlet只处理一个动作参数校验放最前面业务逻辑次之跳转放最后。这套项目由于作者本身已经按功能拆分了Servlet你在加新功能时尽量沿用这个习惯整体代码风格保持一致。拿到这套源码后建议你在本地先跑通流程再用两天时间把上面提到的购物车增强做完然后项目就能作为「个人独立开发的电商系统」写进简历——技术栈虽然偏基础但完整度足够证明你的 JavaWeb 能力。切记一点用它做课设没问题但答辩时要把每一个类为什么这样命名、每一个Servlet对应哪个页面、数据库表为什么这么设计都理清楚。祝你的课设顺利过审希望帮到你。本文还有配套的精品资源点击获取

相关新闻

x3650 M5服务器部署与维护实战:从IMM2到RAID配置

x3650 M5服务器部署与维护实战:从IMM2到RAID配置

简介:《Lenovo System x3650 M5-5462 安装维护指南》是一份面向服务器管理员、运维工程师和IT技术支持人员的官方设备手册,围绕该机型从部署、配置到售后维护的完整链路展开。内容先解析前后面板、操作员信息面板、LCD显示面板、导轨与机架规格以及服务器…

2026/10/18 4:43:33 阅读更多 →
Java Web记单词网站:Servlet+JSP+MySQL教学级全栈实现

Java Web记单词网站:Servlet+JSP+MySQL教学级全栈实现

简介:这是一套基于JavaWeb技术栈开发的背单词网站及配套安卓APP的完整源码项目,面向Java初学者与Web开发练习者,解决词汇记忆类应用从后端到前端、数据库到移动端的全链路实践需求。资源包含542个文件,涵盖56个JAR依赖库、37个核心…

2026/10/18 4:43:33 阅读更多 →
软件开发合同避坑指南:从条款拆解到自动化排期与验收

软件开发合同避坑指南:从条款拆解到自动化排期与验收

简介:这份软件开发合同文档面向需要签订或参考软件委托开发协议的甲方客户、乙方开发团队及法务人员,用于规范会员积分制刷卡消费管理系统、公司宣传网站、微信公共服务平台、店铺零售结算系统等多模块项目的合作流程。资源包内含1个doc文件,…

2026/10/18 4:43:33 阅读更多 →

最新新闻

国庆AI行业盘点:模型更新、开源生态与智能体落地加速

国庆AI行业盘点:模型更新、开源生态与智能体落地加速

国庆长假这两天,AI圈跟过年似的。10月1日到10月8日,前后八天,不断有模型更新、开源仓库爆点、智能体应用密集落地。作为一个长期跟踪这条赛道的人,我几乎每天都要刷好几遍测试榜单和社区讨论串,很多信息还没来得及沉淀…

2026/10/18 5:37:42 阅读更多 →
程序员必备20个网站:技术阅读、刷题、接单与效率工具盘点

程序员必备20个网站:技术阅读、刷题、接单与效率工具盘点

程序员必备网站这个老话题,几乎每隔几个月就会被重新拿出来聊一轮。技术、接单、刷题这三类网站,每个开发者的收藏夹里都躺着不止一个,但真到要用的时候,很多人会发现:收藏了 300 个网站,能稳定打开、准时解…

2026/10/18 5:37:42 阅读更多 →
全大写提示词触发AI风控?解析Claude互审封禁真相与安全写法

全大写提示词触发AI风控?解析Claude互审封禁真相与安全写法

有意思。“让Claude管Claude”本身没问题,问题是这句提示词是用全大写敲出来的。我是在一个技术讨论群里看到这件事的:某人做了个自动化流程,让一个Claude会话去审核另一个Claude会话生成的文案,这本来是个很常见的质检思路&#…

2026/10/18 5:37:42 阅读更多 →
Image GPS Editor实战:照片GPS数据的读取、修改与批量处理

Image GPS Editor实战:照片GPS数据的读取、修改与批量处理

前阵子帮朋友整理一趟长途自驾的素材,几百张照片导进电脑,结果发现相机里明明开了GPS记录,出来的照片却有一大半坐标信息是空的。另一批用手机拍的照片倒是带位置,但其中有几张因为当时在船上漂着,定位偏到了海里。用看…

2026/10/18 5:37:42 阅读更多 →
变量之路:理清编译与链接中的符号、地址与重定位机制

变量之路:理清编译与链接中的符号、地址与重定位机制

先问一个问题:你在 IDE 里写了int counter 0;,点一下运行按钮,程序跑起来了。可是那个叫counter的变量,它的地址到底是谁给它的?它为什么能从一个名字变成一个真实存在于内存里的地址?我在带新人的时候发现…

2026/10/18 5:37:42 阅读更多 →
律所案件管理系统设计与落地:角色权限、流程引擎与文书协同实践

律所案件管理系统设计与落地:角色权限、流程引擎与文书协同实践

1. 这个系统到底在解决什么问题做律师的朋友应该都有过这种体验:一个案子从收到材料到最终归档,中间要经过立案、排期、取证、文书起草、审核、盖章、送达、开庭、归档这么一串流程。传统做法是什么?微信群接龙、Excel表格、共享文件夹、Outl…

2026/10/18 5:36:42 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/16 14:23:36 阅读更多 →