SpringBoot影楼管理系统实战:订单、权限与统计报表全解析
1. 项目到底在做什么——先别急着跑代码看到Springboot影楼管理系统这个标题很多同学脑子里第一反应是又是一个普通的CRUD项目。这话对了一半但影楼这个业务场景其实比你想的要有意思得多。我当时接手一个类似的模拟项目X时第一件事不是打开IDEA看代码而是花半天去搞懂影楼到底是怎么运作的。你只有理解了业务才能写出真正可交付的代码也才能在论文里把需求分析讲得有理有据而不是照搬别人的模板。影楼的业务核心是什么是订单驱动。一个顾客进店从咨询、预约、到店拍摄、选片、精修、出册再到拿到成品这整条链路都围着订单转。而你做系统本质上是把这套线下流程搬到线上让门店能管住客户、排好摄影师档期、算清套餐价格、最后能看明白这个月到底赚了多少。所以这个系统通常涵盖的模块是用户登录权限、客户信息管理、摄影套餐管理、订单管理、摄影师排班、案例作品展示、统计报表。有些版本还会做基础的库存管理比如相册物料、服装道具这就看初始项目的边界怎么划的了。我个人建议在你动手改代码之前先把这个项目的现有模块在草稿纸上画出来标清每个模块之间的关联。比如订单表要关联客户表、套餐表、摄影师表这个关联关系一旦搞错后面报表统计出来的数字就会对不上排查起来非常头大。把业务的地图先画明白了后面无论是二次开发还是写论文你都会比别人多花一倍的时间去理解错了——不对是多省一半的时间。2. 核心功能模块拆解——知道系统里藏着哪些机关2.1 登录与权限别让员工看到老板的报表影楼管理系统里最常见的权限划分是管理员和普通员工。管理员看得到营收统计、订单明细、客户全量数据普通员工可能只能看到自己的待办订单或者拍摄任务。这个模块的技术实现在SpringBoot里往往依赖于拦截器Interceptor或者AOP切面登录后把用户信息存进Session然后在访问特定接口前做角色校验。这里有一个初学者容易踩的坑只在前端做了按钮隐藏后端接口没有任何拦截。这是不行的懂行的人用Postman直接调接口就能绕过前端拿到数据。你在这个系统上做二次开发时务必要确认后端有没有做真正的权限控制。这既是功能问题也是安全问题放在论文里就是系统安全性设计的素材。2.2 客户管理CRUD里面藏着的细节客户管理说白了就是增删改查但影楼场景下有几个字段需要特别留意客户来源渠道美团、小红书、朋友转介绍、意向等级高意向/中意向/低意向、跟进记录。为什么要记录这些因为影楼获客成本高销售需要持续跟进如果你只是做一个简单的姓名电话登记表那这个模块就少了商业价值论文里也写不出深度。实操心得做客户列表的时候分页查询和模糊搜索是标配。前端用Bootstrap Table或者Layui的Table组件都能快速实现。但注意数据库层面要给查询字段建立索引尤其是手机号这种高频搜索字段。我当时在这个模拟项目X里就吃过亏数据量到了几千条之后不带索引的模糊查询明显卡顿加上索引后速度立刻恢复正常。2.3 订单管理这个模块是整张大网的中心订单管理是整个影楼系统里最复杂的模块。一个订单里通常包含订单编号、客户ID、套餐ID、摄影师ID、订单金额、定金、拍摄时间、订单状态。状态流转可能是待支付 - 已支付 - 待拍摄 - 已完成 - 已取消。这里有一个非常容易出错的设计细节订单金额和套餐价格的关系。很多同学会把套餐价格直接冗余到订单表里这样做的好处是如果未来套餐涨价已存在的订单金额不会跟着变。这是合理的做法但要在表设计上用冗余字段保存下单时的快照价格而不是用关联查询去实时取套餐表的价格。后者一旦套餐价格被修改历史订单的金额就全乱了。这个细节你在二次开发时要特别注意也是答辩时老师喜欢追问的点。2.4 排班与统计拉开差距的分水岭摄影师排班、统计报表这两个模块做得深不深直接决定这个项目在毕业论文里是中规中矩还是有亮点。排班可以做成按周视图显示每个摄影师每天的档期状态空闲/已约/休息。统计报表则可以用ECharts展示月度营收趋势、套餐销量Top5、员工业绩排行。技术上的切入点是用聚合查询比如统计某个时间段内各状态订单的数量。SQL大概长得像这样SELECT DATE_FORMAT(create_time, %Y-%m) AS month, SUM(order_amount) AS total_amount, COUNT(id) AS order_count FROM orders WHERE create_time BETWEEN #{startDate} AND #{endDate} GROUP BY DATE_FORMAT(create_time, %Y-%m) ORDER BY month DESC;这类SQL写出来再用MyBatis的Select注解或者XML映射文件封装好前端接ECharts的json接口就能出图。图表好看、SQL有深度论文里放两张截图整篇文章的档次立刻就不一样了。3. 技术选型与核心配置——搭建这套系统的地基3.1 为什么SpringBoot是这种项目的主流选择说实话影楼管理系统这种体量用纯SSHStruts2 Spring Hibernate也能做但SpringBoot之所以成为绝对主流核心是约定大于配置内嵌的Tomcat让你不用再去装一个独立的服务器打一个jar包直接跑起来。对课设和毕设场景来说这意味着排查环境问题的成本被大大降低了。SpringBoot整合MyBatis更是常规搭档MyBatis灵活控制SQL的好处在你写统计报表那类复杂查询时体现得很彻底。前端模板方面很多初始项目用的是Thymeleaf配合Bootstrap或者Layui也有一些版本是前后端分离使用Vue。拿到项目后先分清是哪一种架构后续调试思路完全不同。3.2 环境搭建与启动配置标准配置清单如下JDK 8 或 11大多数SpringBoot 2.x版本在这两个环境下运行最稳Maven 3.6依赖管理和打包MySQL 5.7 或 8.0数据库IDEA开发工具社区版也够用Navicat 或 DataGrip数据库可视化操作拿到项目源码后不要急着启动先做三件事第一检查pom.xml里到底用了哪个SpringBoot版本这决定了你本地的JDK版本要不要对上。第二看application.yml或properties里的数据源配置里面一般有数据库名、用户名、密码。第三找到项目附带的SQL文件先把它导入到本地MySQL。我在第一次跑这个模拟项目X的时候卡在最基础的地方MySQL命令直接导入SQL文件遇到Unknown database报错。原因是SQL文件里建库语句是有的但用Navicat运行时没先选中一个库。正确做法是在命令行执行mysql -u root -p init.sql或者打开Navicat先创建一个同名数据库比如studio_system字符集选utf8mb4然后右键该数据库选择运行SQL文件。注意如果SQL文件本身有CREATE DATABASE语句直接运行也不会报错。总之先确认数据表都建好了再谈启动。3.3 页面跳转与资源路径的坑SpringBoot Thymeleaf的项目Controller里return login会去找templates目录下的login.html。这个机制很简单但有一个高频问题静态资源CSS、JS、图片加载不出来。如果你在页面上发现样式全丢了先打开浏览器F12看Network标签页看看404的资源路径是什么。Thymeleaf模板里资源引用要写成这样link th:href{/css/style.css} relstylesheet注意那个th:href属性不能少。如果你在模板里直接写href/css/style.css而项目又设置了context-pathserver.servlet.context-path那么路径就会对不上。这是我在帮人排查这个项目时遇到最多的报错之一原因五花八门但解决思路都一样先看请求路径再对照项目里静态资源的实际存放位置默认是src/main/resources/static。4. 完整部署与调试实操——把项目真正跑起来4.1 数据库初始化与连接配置在导入数据库后打开application.yml检查配置。常见的样子是spring: datasource: url: jdbc:mysql://localhost:3306/studio_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver这里有两个值得注意的细节。第一serverTimezoneAsia/Shanghai必须加上MySQL 8.x的默认时区设置会导致连接报错。第二driver-class-name如果你是JDK 8 MySQL 5.7的组合驱动类可以用com.mysql.jdbc.Driver但如果是MySQL 8.x就必须用com.mysql.cj.jdbc.Driver。这两个细节如果错了启动时大概率看到的是Unable to obtain connection from database: The server time zone value ... is unrecognized这属于环境性问题按上面的配置改好即可。4.2 启动项目与验证接口用IDEA打开项目后等待Maven把依赖下载完。这一步要有点耐心因为首次下载spring-boot-starter-web、mybatis-spring-boot-starter这些依赖会花几分钟。如果下载速度太慢可以配置Maven镜像为阿里云仓库在settings.xml里加mirror idaliyunmaven/id mirrorOfcentral/mirrorOf urlhttps://maven.aliyun.com/repository/public/url /mirror依赖就绪后找到主启动类就是标注了SpringBootApplication的那个类右键运行。启动成功的标志是控制台出现Started Application in x.xxx seconds之类的日志。接下来用浏览器访问http://localhost:8080看到登录页就说明基本通了。再用项目自带的初始账号通常在SQL文件里能查到比如admin/admin123登录进去逐个模块点一遍确认数据能被正常展示和操作。4.3 改代码、加功能的常见调试流程这种项目的二次开发通常是从改一个页面字段开始的。比如客户列表想要增加一列客户生日完整的操作链路是在数据库表里增加字段ALTER TABLE customer ADD COLUMN birthday DATE NULL;在实体类Customer.java里增加属性private Date birthday;注意类型对应在CustomerMapper.xml或注解SQL里insert语句加上字段和值select语句把birthday查出来在前端列表页面加一列在新增/编辑表单里加一个日期输入框重启项目验证增删改查全流程这套流程说起来简单但每一步都暗藏细节。第3步里很多初始项目的SQL是手写字段的不是SELECT *那你就得把字段列表改全。漏改一处页面上就报Unknown column报错时间是必然的但是位置不一定好找。所以做改动时尽量在同一时段把数据库、实体类、SQL、前端页面四个层面一起改通。5. 排查实录——高频问题的定位和解决5.1 端口被占用启动时看到Web server failed to start. Port 8080 was already in use.意思是8080端口被其他进程占了。可以执行netstat -ano | findstr 8080找到占用端口的PID后在任务管理器里结束对应进程。如果你不想关掉其他项目也可以在application.yml里把server.port改成8081再重启。5.2 页面显示Whitelabel Error Page这个错误页提示是SpringBoot默认的兜底错误页出现它通常意味着请求有异常。信息根本不够用你需要去控制台看具体的Exception。最常见的两类一类是500异常多是因为SQL语句写错、空指针之类的逻辑问题另一类是404多是因为Controller里的路径写错或者Controller没扫描到。关于Controller没扫描到我再分享一个排查点主启动类的位置。SpringBoot默认扫描的是主启动类所在包及子包。如果你把Controller放在了这个包的外面Spring容器根本不会加载它请求自然全部404而且控制台没有任何错误。所以拿到项目后先看一眼包结构是否规范清晰。这一点对后面自己加新模块也至关重要新写的Controller、Service、Mapper都要放在合理的位置别破坏扫描范围。5.3 MyBatis映射文件路径报错项目启动时报类似BindingException: Invalid bound statement (not found)这是因为Mapper接口和Mapper.xml文件没有正确绑定。常见原因有三个XML文件没放在resources目录下对应的mapper包路径里application.yml里的mybatis.mapper-locations配置路径写错了或者idea没把XML文件编译到classes目录。解决办法是在pom.xml里确保resources配置包含XML文件resources resource directorysrc/main/java/directory includes include**/*.xml/include /includes /resource /resources其实更标准的做法是把XML文件放在resources/mapper目录下然后在application.yml里配mybatis: mapper-locations: classpath:mapper/*.xml这样路径最清晰也不容易出问题。5.4 常见问题速查表症状常见原因第一排查点启动时报时区错误MySQL中serverTimezone参数缺失或错误检查JDBC URL页面无样式Thymeleaf资源路径写错检查th:href和静态资源位置登录功能一直失败数据库初始账号密码不对检查SQL文件中的用户表数据新增记录报SQL错误字段与表结构不匹配对比实体类和表字段中文乱码数据库字符集不对确认建库时使用utf8mb46. 论文素材该怎么组织——不只是贴代码6.1 需求分析把业务背景写透论文第一章通常是绪论第二章是需求分析。很多同学的薄弱点在需求分析写得像产品说明书全是系统需要实现用户管理、订单管理这种空话。影楼管理系统的需求分析建议从三个角色说起管理员关心营收和排班前台/销售关心客户跟进和订单录入摄影师关心自己的拍摄任务和档期。每个角色列需求场景再画用例图。这一写篇幅有了逻辑也顺了。6.2 系统设计重点画好架构图和E-R图技术架构方面画出三层结构图表现层Thymeleaf页面 - 业务层Service - 持久层MyBatis DAO。数据库设计画E-R图重点把订单表作为核心标注它跟客户、套餐、摄影师之间的关系。表结构设计要列出关键表每张表说明用途和关键字段不需要把所有字段全贴上去但核心的表结构和字段含义要说清楚。这里有一个实用的经验提醒论文里的核心代码不要整段大段地贴而是挑关键逻辑来展示。比如订单状态流转的逻辑、统计报表的聚合查询SQL、权限拦截器的实现。答辩老师翻论文时看得最多的就是这几个地方。6.3 测试部分是拉分的细节系统测试部分不要糊弄也不要只会写页面显示正常。建议至少列出登录功能测试用例、订单新增功能测试用例、统计报表数据准确性测试用例。注意测试用例里要有正常路径和异常路径。比如录入订单时把必填字段留空系统应该给出提示而不是直接报500错误。这类测试用例能体现你的工程素养比空话强很多。7. 我踩过的那些坑你最好别再踩了项目调试过程中踩坑是常态关键是踩完要总结出来。下面这几条是我在这个模拟项目X上实际遇到过、并且花了不少时间才解决的问题分享出来希望能帮你省掉这个时间。第一个坑是Maven依赖版本不匹配。SpringBoot 2.3.x和2.7.x的行为在一些细节上有差异比如路径匹配规则、配置项的名称。如果你在网上照着别人的教程改配置先看看你的版本和教程里的版本是否一致。最典型的例子是spring-boot-starter-web内置的Tomcat版本不同对URL中特殊字符的处理结果完全不同。第二个坑是前端表单提交后发现数据库里是NULL。排查了很久发现是form表单里input的name属性跟后端实体类的字段名对不上。前端写的是namecustomName后端实体类字段是name字段。这种情况SpringBoot虽然有自动绑定机制但要求名字对得上才行。这也是一个非常典型、用眼睛看代码很容易漏掉的低级错误。第三个坑是在IDEA里改了代码但页面没变化。这通常是因为启动了多个实例旧实例的端口还没释放。实际测试时确保只跑了一个SpringBoot实例改完代码后重启不要热部署之后刷新一下就完事。热部署有时会失效特别是在模板页面修改后需要手动Rebuild。这种我明明改了为什么不生效的挫败感相信每个做Web开发的人都有体会。第四个坑是导出Excel报表功能。如果初始项目里有导出功能通常是用Apache POI实现的。这一步在Windows本地跑没问题但如果部署到了Linux服务器中文文件名有可能导出乱码。解决办法是设置响应头的时候统一用UTF-8编码并使用URLEncoder处理文件名。最后想说的是这个影楼管理系统从功能上看也许不算惊艳但胜在业务场景完整、技术栈主流是一块非常好的练手田。你在上面花的时间不会白费因为SpringBoot MyBatis MySQL这套组合在国内中小型企业管理系统的开发里实在太太太常见了。把这里的CRUD、权限、统计、部署玩明白你去任何一家公司做Java后端实习生上手速度都会快人一步。我自己的体会是做完这个项目再回头看真正的成长不仅来自把代码跑通更来自跑通过程中被迫去了解的那些为什么——为什么用拦截器而不是过滤器做登录校验、为什么聚合查询要用GROUP BY而不是在Java代码里遍历相加、为什么数据库表要设计冗余字段。把这些想明白了你才算真正消化了这个项目。

相关新闻

基于YOLOv8的安全帽佩戴检测:从数据构建到边缘部署全流程实战

基于YOLOv8的安全帽佩戴检测:从数据构建到边缘部署全流程实战

1. 工地安全监管的真实痛点与视觉检测的切入点干了这么多年计算机视觉落地项目,我越来越觉得,真正有价值的不是模型在公开数据集上刷到多高的mAP,而是能不能在工地上那台满是灰尘的工控机上,顶着大太阳和逆光,把没戴安…

2026/10/19 11:05:50 阅读更多 →
diagram-design:从草图到系统,构建可复用的图表设计资产

diagram-design:从草图到系统,构建可复用的图表设计资产

1. 从一张草图到一套系统:diagram-design 到底在解决什么问题第一次看到 diagram-design 这个词,很多人会以为它只是一个画图工具的别名。但真正在项目里摸爬滚打过的人会明白,它指向的是一套完整的“图表设计系统”——从需求梳理、结构规划…

2026/10/19 11:05:50 阅读更多 →
图表设计是信息压缩和认知引导的工程能力:从架构图到流程图的实战方法

图表设计是信息压缩和认知引导的工程能力:从架构图到流程图的实战方法

很多人一听到“diagram-design”就觉得是画个框、连几条线,没什么技术含量。但真正做过复杂系统设计图、架构图、流程图的开发者或者设计师都知道,一张烂图能把一个完美的方案活活讲成事故现场。我在实际项目里反复改过几十版图表之后,最大的…

2026/10/19 11:04:46 阅读更多 →

最新新闻

微服务商城对接支付宝支付:独立支付服务与异步回调实战

微服务商城对接支付宝支付:独立支付服务与异步回调实战

1. 支付服务在微服务架构里的定位做电商项目,前面把商品、库存、订单、用户这些服务都搭起来之后,早晚要面对一个绕不开的环节——支付。我这次在基于Vue和SpringCloudAlibaba的微服务商城项目里,把支付单独拆成了一个平台服务,专…

2026/10/20 7:12:54 阅读更多 →
前缀表达式求值:从右往左扫描的栈式算法详解

前缀表达式求值:从右往左扫描的栈式算法详解

这是一道很经典的数据结构题目,很多朋友在学栈和递归的时候都会遇到。我当年第一次做这题也卡了一阵子,倒不是代码写不出来,而是方向搞反了,一直在想怎么从左往右处理。后来想通前缀表达式的本质之后,代码其实就几行。…

2026/10/20 7:12:54 阅读更多 →
QoS原理与实战:从拥塞控制到带宽分配,一套完整的网络服务质量配置指南

QoS原理与实战:从拥塞控制到带宽分配,一套完整的网络服务质量配置指南

网络时不时卡顿、视频会议断断续续、后台同步任务把带宽占满,这种场景在现网里太常见了。QoS(服务质量,Quality of Service)就是专门用来处理这类问题的机制集合:在有限的带宽条件下,按业务的重要程度重新分…

2026/10/20 7:12:54 阅读更多 →
AI芯片软硬件协同设计:算子映射、指令集与存储调度

AI芯片软硬件协同设计:算子映射、指令集与存储调度

每个做AI加速器的团队,几乎都遇到过这种场景:硬件团队说MAC阵列利用率跑到了98%,软件团队盯着执行时间说这绝对没到预期,两边各拿出一套数据,结果谁都没错。问题就出在软硬件协同设计上,而且多半不是单点失…

2026/10/20 7:12:54 阅读更多 →
Delphi 11数据库界面增强:EhLib 10.0.031实战指南

Delphi 11数据库界面增强:EhLib 10.0.031实战指南

简介:EhLib 10.0.031 是一款专为 Delphi 11(特别是 11.1.5 环境)深度适配的高性能第三方组件库,面向中高级 Delphi 桌面与数据库应用开发者,显著提升图形处理、多源数据库交互、专业报表生成及数据可视化开发效率。资源…

2026/10/20 7:12:54 阅读更多 →
Repast多智能体建模实战:从SIR模型到Headless批量仿真

Repast多智能体建模实战:从SIR模型到Headless批量仿真

简介:一份针对 Repast 建模与仿真平台的英文原版教程与配套实例,面向社会科学、经济学及复杂系统领域的研究者,也适合希望快速上手多智能体仿真的学生和工程师。整个资源包内共包含72个文件,主体为66个HTML/HTM格式的教程页面&…

2026/10/20 7:11:54 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 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/19 2:54:50 阅读更多 →
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/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →