UML核心视图实战:图书管理系统建模从用例图到构件图
简介这份PPT面向软件工程、计算机专业学生及UML初学者围绕统一建模语言UML的核心视图以ABC高校图书管理系统为完整案例讲解从需求分析到静态建模的全过程。内容涵盖用例视图的参与者、用例与关系识别读者借还书、预约取消预约及管理员增删改读者与书籍等业务场景并逐步绘制读者信息管理、书籍信息管理、图书馆业务与信息查询四类用例图随后进入类图部分讲解从事件流中提取名词、抽象边界类、实体类与控制类的方法梳理借书、还书、预约等业务模块的类结构以及关联与泛化关系的判定。资源包共1个PPT文件约401KB适合课堂复习、期末备考与课程设计参考。已有209人学习可帮助读者系统掌握UML核心视图的建模思路与图书管理系统案例的完整分析流程。1. 从一份 PPT 说起UML 核心视图到底怎么给图书管理系统建模很多人第一次接触统一建模语言是在一份流传很广的课件里——标题写着「UML 核心视图图书管理系统建模的案例」内容是一套 PPT。它把用例图、类图、构件图这些概念一股脑塞给你看完觉得懂了真让你动手画一个图书管理系统又不知道从哪下手。问题不在你在于课件只讲了「图长什么样」没讲「为什么这么画、先画哪张、箭头朝哪」。这篇笔记就干一件事把图书管理系统当成一个真实要交付的软件从需求到结构用 UML 核心视图一步步建出来。用例图回答「谁用它、能干什么」类图回答「系统里有哪些东西、它们怎么关联」构件图回答「代码怎么拆、怎么部署」。适合正在做课程设计、软考复习、或者第一次带团队做需求建模的工程师。下面所有画法都能在 StarUML、draw.io、PlantUML 里复现不依赖某份特定文档。2. 用例图先行把图书管理系统的角色和边界钉死用例图是整个建模的入口它不关心你怎么实现只回答两个问题系统边界在哪谁站在边界外面跟系统交互。图书管理系统看着简单恰恰因为「简单」很多人跳过这步直接画类图结果做到一半发现「续借」和「借书」的规则纠缠不清返工。血泪经验是用例图花半小时后面省两天。2.1 先分清主角和配角别把管理员当唯一角色图书管理系统里常见的角色有这么几类我一般会先列一张角色表再动手角色主要诉求是否直接操作系统读者查书、借书、还书、续借、预约是图书管理员办借还、维护书目、处理罚款是系统管理员管账号、配参数、看日志是财务系统接收罚款数据否外部系统注意最后一行。很多新手只画人忘了外部系统也是参与者Actor。罚款这块如果财务系统要对接它就是一个独立的 Actor用「系统边界」把它挡在外面接口关系才清楚。热搜里常出现的「用例图 AI 生成」生成出来的图十有八九漏掉外部系统角色就是因为提示词里只写了「用户和管理员」。2.2 用例粒度一个用例一件事别写成操作流水账用例的命名有个硬标准动宾结构且是「对系统有价值的一个完整目标」。对比一下差的写法「输入用户名」「点击查询按钮」「显示结果」——这是操作步骤不是用例。好的写法「查询图书」「借阅图书」「续借图书」「预约图书」「缴纳罚款」。「借阅图书」这个用例内部可能包含扫码、校验读者资格、校验库存、写借阅记录好几步但这些是实现细节不该拆成四个用例。判断标准很简单如果这个动作单独完成后对读者没有任何可感知的价值它就不该是一个独立用例。2.3 用 PlantUML 把用例图落成可版本管理的文本图形工具画用例图容易但改起来痛苦团队协作时谁改了哪根线根本看不出来。我一般用 PlantUML 写文本进 Git 管理。下面是最小可运行版本startuml left to right direction actor 读者 as Reader actor 图书管理员 as Librarian actor 系统管理员 as Admin actor 财务系统 as Finance rectangle 图书管理系统 { usecase 查询图书 as UC1 usecase 借阅图书 as UC2 usecase 归还图书 as UC3 usecase 续借图书 as UC4 usecase 预约图书 as UC5 usecase 维护书目 as UC6 usecase 处理罚款 as UC7 usecase 管理账号 as UC8 } Reader -- UC1 Reader -- UC2 Reader -- UC3 Reader -- UC4 Reader -- UC5 Librarian -- UC2 Librarian -- UC3 Librarian -- UC6 Librarian -- UC7 Admin -- UC8 UC7 -- Finance UC4 . UC2 : extend enduml逻辑说明rectangle圈出系统边界边界外的 actor 才是参与者。UC4 . UC2表示续借是对借阅的扩展extend只有在「借阅已存在且未超期」的条件下才触发这个约束后面在类图里要落到属性上。参数上left to right direction只是排版不影响语义extend和include别混用——include 是必然发生的公共步骤比如借书必然要「校验读者」extend 是条件触发的可选行为。提示用例图里不要画箭头表示数据流那是数据流图DFD的活。UML 用例图里箭头只表示参与者和用例之间的关联或者用例之间的 include/extend 关系。3. 类图是重头戏图书管理系统的实体、关系和箭头方向类图是 UML 里信息量最大、也最容易画错的一张图。热搜里「类图的各种箭头」「uml 类图怎么画」「staruml 类图怎么画」常年霸榜说明大家卡的就是箭头。这一章把图书管理系统的核心类拆开逐个说清楚每个箭头为什么这么画。3.1 先找实体类再找控制类和边界类一个稳妥的做法是按边界类、控制类、实体类三层来找。图书管理系统里实体类Book图书、BookCopy馆藏副本、Reader读者、Loan借阅记录、Reservation预约记录、Fine罚款。控制类LoanService借还业务逻辑、SearchService检索逻辑。边界类借书界面、查询界面这些在类图里通常简化掉除非要做详细设计。关键区分Book 和 BookCopy 必须分开。一本书《深入理解计算机系统》是 Book图书馆买了 5 本就是 5 个 BookCopy。借阅是针对副本的不是针对书目的。新手最常见的翻车就是把这两者合成一个类结果「库存数量」这种字段到处飞并发借书时超卖。3.2 六种关系对应六种箭头一张表说清类图的关系是考试和实战的双重重点我整理成对照表关系符号语义图书系统例子依赖虚线箭头临时使用LoanService 依赖 FineCalculator关联实线长期持有Reader 关联 Loan聚合空心菱形整体-部分可分离Book 聚合 BookCopy组合实心菱形整体-部分同生共死Loan 组合 Fine泛化空心三角实线is-a 继承学生读者继承 Reader实现空心三角虚线接口实现各类实现 Searchable 接口聚合和组合的区别用图书系统一句话记住图书馆关门了Book 和 BookCopy 都还在聚合可分离但一条借阅记录被删除它产生的罚款记录通常也该一起处理组合生命周期绑定。箭头方向永远指向「被知道的一方」不是数据流向。3.3 用 PlantUML 画出可运行的类图骨架startuml class Book { - isbn : String - title : String - author : String getDetail() : String } class BookCopy { - barcode : String - status : CopyStatus isAvailable() : boolean } class Reader { - readerId : String - name : String - maxLoan : int canBorrow() : boolean } class Loan { - loanDate : Date - dueDate : Date - returnDate : Date isOverdue() : boolean } class Fine { - amount : BigDecimal - paid : boolean } class LoanService { borrow(reader, copy) : Loan returnBook(loan) : void } Book 1 o-- 0..* BookCopy : 拥有 Reader 1 -- 0..* Loan : 发起 BookCopy 1 -- 0..* Loan : 被借 Loan 1 *-- 0..1 Fine : 产生 LoanService .. Loan : 创建 LoanService .. Fine : 计算 enduml逻辑说明o--是聚合*--是组合--是普通关联..是依赖。多重性1和0..*必须标它直接决定数据库外键和集合类型——Reader 1 -- 0..* Loan意味着 Reader 类里有个ListLoanLoan 表里有个 reader_id 外键。Loan 1 *-- 0..1 Fine里的0..1表示一条借阅最多产生一笔罚款这个约束在业务代码里要显式校验。参数说明CopyStatus是个枚举值一般是 AVAILABLE、BORROWED、RESERVED、LOST。maxLoan控制读者可借上限学生 5 本、教师 10 本这种规则就落在这个字段上配合canBorrow()方法实现。BigDecimal用于金额别用 double这是财务类字段的铁律。注意类图里不要出现 getter/setter 之外的业务逻辑细节方法签名写到「能看懂职责」就够了。把整个方法体画进去图就没法看了。4. 构件图与部署视图从类图到能跑的系统还差什么类图画完很多人以为建模结束了。但从类图到真正能部署的系统中间还隔着「代码怎么拆包、服务怎么部署」。这就是构件图Component Diagram和部署图Deployment Diagram要回答的。热搜里「组件图 uml」「构件图 uml」问的多但真正讲清楚和类图关系的少。4.1 构件图把类图里的类按职责打包构件图描述的是软件模块及其依赖。图书管理系统常见的拆法circulation流通构件负责借、还、续借对应 LoanService、Loan。catalog书目构件负责图书和副本管理对应 Book、BookCopy。account账户构件负责读者和罚款对应 Reader、Fine。search检索构件对外提供查询接口。构件之间通过接口交互而不是直接互相引用类。比如 circulation 需要知道读者能不能借它依赖的是 account 暴露的ReaderQuery接口而不是直接 import Reader 类。这样 account 内部怎么改circulation 不受影响。startuml component circulation as C1 component catalog as C2 component account as C3 component search as C4 interface ReaderQuery as I1 interface BookQuery as I2 C1 .. I1 C3 -- I1 C1 .. I2 C2 -- I2 C4 .. I2 enduml逻辑说明--表示构件「提供」接口实现端..表示构件「使用」接口调用端。这个方向别画反画反了就成了循环依赖编译期就报错。参数上接口名用业务语义命名别用IService1这种半年后自己都不认识。4.2 部署图单体还是分层先画清楚再写代码部署图描述物理节点和构件在节点上的分布。图书管理系统规模不大常见两种部署部署方式节点适用场景单体一台应用服务器 一台数据库课程设计、小型图书馆分层Web 服务器 应用服务器 数据库多校区、有并发要求部署图里节点用立方体表示构件放在节点内部。如果做分层Web 节点放前端构件应用节点放 circulation/catalog/account数据库节点放持久化。节点之间的连线标注通信协议比如 HTTP、JDBC。这一步画清楚后面写 Dockerfile 和 Nginx 配置时心里有底不会出现「前端直接连数据库」这种架构事故。4.3 从模型到代码类图字段怎么映射成建表语句建模最终要落地。类图里的类绝大多数会变成一张表关联关系变成外键多重性决定外键放哪边。下面是从前面类图直接推导的建表语句CREATE TABLE book ( isbn VARCHAR(20) PRIMARY KEY, title VARCHAR(200) NOT NULL, author VARCHAR(100) ); CREATE TABLE book_copy ( barcode VARCHAR(32) PRIMARY KEY, isbn VARCHAR(20) NOT NULL, status VARCHAR(16) NOT NULL DEFAULT AVAILABLE, FOREIGN KEY (isbn) REFERENCES book(isbn) ); CREATE TABLE loan ( loan_id BIGINT PRIMARY KEY, reader_id VARCHAR(32) NOT NULL, barcode VARCHAR(32) NOT NULL, loan_date DATE NOT NULL, due_date DATE NOT NULL, return_date DATE, FOREIGN KEY (reader_id) REFERENCES reader(reader_id), FOREIGN KEY (barcode) REFERENCES book_copy(barcode) );逻辑说明Book 1 o-- 0..* BookCopy这个聚合外键isbn放在 book_copy 表因为一个副本只属于一个书目一对多关系外键永远放在「多」的那边。Loan同时引用 reader 和 book_copy两个外键都放 loan 表这是关联类落地的标准做法。status用字符串而不是数字可读性优先配合应用层枚举校验。参数说明barcode用 VARCHAR 而不是自增 ID因为条码是业务主键扫码枪直接读。due_date在借出时计算一般是 loan_date 加借期天数这个天数从 Reader 的maxLoan同级的借期配置里取别硬编码在 SQL 里。5. 建模避坑清单这五个坑我替你踩过了建模这件事画对了都差不多画错了各有各的错法。下面五条是图书管理系统建模里出现频率最高的翻车现场每条按现象、原因、解决来说。坑一用例图里出现「登录」用例。现象几乎每份学生作业的用例图里都有「用户登录」。 原因把技术实现当成了业务目标。登录对读者来说不是目的借书才是。 解决登录作为所有用例的前置条件写在用例规约里不单独画成用例。除非系统有独立的账号管理业务那才归到系统管理员的用例下。坑二类图里 Book 和 BookCopy 合并成一个类。现象借书时库存字段减一还书时加一并发下出现超借。 原因混淆了「书目」和「实物副本」两个概念。 解决拆成两个类借阅关联到 BookCopy库存数量由副本状态统计得出不单独存字段。这样每本副本的借阅历史也能追溯。坑三聚合和组合画反。现象Book 和 BookCopy 用了实心菱形删书目时副本被级联删除。 原因没想清楚生命周期。书目下架副本可能还在别的馆藏里流转。 解决可分离的用聚合空心菱形同生共死的用组合实心菱形。拿不准时问一句「整体没了部分还有没有独立存在的意义」。坑四类图里塞满 getter/setter。现象一张类图几十个方法全是 getXxx/setXxx核心业务方法反而找不到。 原因把 IDE 自动生成的代码直接搬进模型。 解决类图只画体现职责的业务方法比如isOverdue()、canBorrow()。getter/setter 是语言层面的样板不进模型。坑五构件图画出循环依赖。现象circulation 依赖 accountaccount 又反过来依赖 circulation编译不过。 原因接口划分时没做依赖倒置两个构件互相直接引用。 解决把被依赖方需要的能力抽成接口由依赖方实现回调或者引入第三个构件承载共享逻辑。构件图的箭头方向必须形成有向无环图。6. 进阶技巧用 PlantUML 把模型接进 CI让图不再过期模型最大的敌人不是画错是过期。代码改了图没改三个月后没人敢信那张图。我现在的习惯是把 PlantUML 源文件跟代码放同一个仓库用 CI 自动渲染成图片合并请求时如果图没更新评审直接打回。下面是一个最小可用的 GitHub Actions 配置思路本地 Jenkins、GitLab CI 同理# 安装 plantuml 与依赖本地或 CI 镜像里执行一次 apt-get install -y plantuml graphviz # 批量渲染 docs/uml 下所有 puml 文件到 png plantuml -tpng -o ../images docs/uml/*.puml # 校验如果渲染失败命令返回非零CI 直接失败 if [ $? -ne 0 ]; then echo UML 渲染失败检查语法 exit 1 fi逻辑说明-tpng指定输出格式也可以换成-tsvg矢量图放大不糊适合放进文档。-o ../images指定输出目录保持源文件和产物分离。最后那个退出码判断是关键——PlantUML 语法错误时默认只打印警告不阻断流程必须手动检查返回码否则 CI 会「假装成功」。参数上graphviz是 PlantUML 渲染类图、构件图时的布局引擎不装它复杂图会报错。如果图很大渲染慢可以加-DPLANTUML_LIMIT_SIZE8192放宽尺寸限制。再补一个验证模型一致性的技巧类图里的类名和代码里的实体类名做一次字符串比对。写个简单脚本把.puml里的class Xxx抽出来跟 Java 或 Python 源码里的类名求差集差集不为空就说明模型和代码脱节了。这个检查放进 CI比任何文档规范都管用。我自己带项目这些年最大的教训就是图不是画给评审看的是画给三个月后的自己看的。当时觉得「这么简单不用画」三个月后对着代码猜业务规则那才叫后悔药没处买。所以现在哪怕再小的系统我也会先把用例图和核心类图用文本写下来进仓库让 CI 盯着它别过期。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

某东h5st逆向实战:webpack签名参数定位与Python复现

某东h5st逆向实战:webpack签名参数定位与Python复现

简介:这份资源面向具备一定前端基础、希望深入理解移动端加密参数生成机制的爬虫学习者与安全测试人员,围绕某东平台webpack打包方式下的h5st逆向分析,提供一套可运行的完整代码示例。压缩包共2个文件,包含1个Python脚本与1个Java…

2026/10/11 13:55:12 阅读更多 →
PyTorch表情识别模型推理实战:从权重加载到批量处理与调优

PyTorch表情识别模型推理实战:从权重加载到批量处理与调优

简介:这份资源是面向深度学习与计算机视觉学习者的面部表情识别项目模型文件包,由GitHub作者He-Xiang-best开源,适合希望动手实践图像分类、理解CNN类网络结构的中级开发者参考。压缩包共5个文件,约317.46MB,包含3个pk…

2026/10/11 13:55:12 阅读更多 →
Unity系统字体动态加载:TextMeshPro生僻字与多语言渲染方案

Unity系统字体动态加载:TextMeshPro生僻字与多语言渲染方案

简介:UnityNativeOSFont 是一套面向 Unity 开发者的开源工具,用于在运行时获取操作系统本地字体并接入 TextMeshPro 动态字体渲染,解决 TMP 默认字体库无法覆盖各平台系统字体、需手动导入字体文件的问题。它通过 C# 脚本读取系统字体列表并转…

2026/10/11 13:55:12 阅读更多 →

最新新闻

学生学籍管理系统数据库课程设计:从ER图到MySQL事务与索引实践

学生学籍管理系统数据库课程设计:从ER图到MySQL事务与索引实践

简介:面向数据库课程设计学生,这份PDF完整呈现了学生学籍管理系统的开发全过程,针对传统手工学籍管理效率低、数据易丢失、统计易出错等痛点,给出了一套计算机化、可共享数据的解决方案。资源仅含1个PDF文件,压缩包858…

2026/10/11 14:46:44 阅读更多 →
HuggingFace模型权重缓存实践:从共享目录到私有制品中心落地指南

HuggingFace模型权重缓存实践:从共享目录到私有制品中心落地指南

前阵子被朋友拉去帮某实验室排查训练环境,发现一个特别典型的现象:他们三台GPU服务器上,同一个开源对话模型居然被下载了三遍,分别是三个不同的人各自用命令行拉取的;其中两台机器的下载目录里还残留着没下载完的半截权…

2026/10/11 14:46:44 阅读更多 →
Hyperf 日志组件实战指南:基于 Monolog 的协程安全日志体系与多通道配置

Hyperf 日志组件实战指南:基于 Monolog 的协程安全日志体系与多通道配置

后端Web框架微服务RPC框架异步编程 【免费下载链接】hyperf 🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease. 项目地址: https://gitcode.com/hyperf/hyperf 点击查看 免费下载 …

2026/10/11 14:46:44 阅读更多 →
眼镜店管理系统:SpringBoot+Vue全栈实战指南

眼镜店管理系统:SpringBoot+Vue全栈实战指南

简介:本资源是一份面向计算机专业本科生的毕业设计论文文档,聚焦眼镜零售行业信息化管理需求,完整呈现基于JavaVueSpringBoot技术栈的瞳仁眼镜店管理系统的设计与实现全过程。论文涵盖系统需求分析、三层角色权限设计(管理员/员工…

2026/10/11 14:46:44 阅读更多 →
OSLO 光学设计应用实战:从光线追迹到优化避坑指南

OSLO 光学设计应用实战:从光线追迹到优化避坑指南

简介:这份PDF文档面向光学设计初学者与光电专业学生,系统讲解OSLO(Optics Software for Layout and Optimization)软件在光学系统设计中的应用。OSLO源自美国罗切斯特大学光学所,擅长确定光学元件的最佳大小与外形&…

2026/10/11 14:46:44 阅读更多 →
进程地址空间深度剖析:虚拟地址转换、堆栈增长与内存问题定位

进程地址空间深度剖析:虚拟地址转换、堆栈增长与内存问题定位

写进程地址空间第一篇文章的时候,我把虚拟内存的整体框架拆开讲了一遍:从代码段到栈,从堆到内存映射段,把一张内存布局图硬生生画了半小时。文章发出后,有同学私信问我:既然地址空间只是个“虚拟”的概念&a…

2026/10/11 14:45:43 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →