数据库小型MIS开发实验:从需求分析到事务处理的完整链路
简介这份南京邮电大学数据库系统小型MIS开发实验报告面向计算机、软件工程等专业修读数据库课程的学生以及需要完成课程设计或实验任务的开发者。报告围绕航班信息、飞机信息、乘客信息和机票信息四类数据完整呈现从建库建表、索引与视图创建到数据插入、查询及存储过程编写的全过程帮助读者理解C/S或B/S结构系统的开发思路掌握ODBC与ADO在界面访问数据库中的作用。资源包共1个doc文件约372KB内容为可直接参考的实验报告文档涵盖CREATE DATABASE、CREATE TABLE、唯一索引、视图与存储过程等关键SQL语句示例并附有航班是否售罄的存储过程逻辑便于对照复现与排错。目前已有242人学习适合作为数据库实验报告撰写与小型MIS系统开发的实操参考。1. 从一份数据库系统小型MIS开发实验报告说起它到底在训练什么能力很多人第一次拿到“数据库系统小型MIS开发实验报告”这个题目时第一反应是去搜一份现成模板把表建好、界面拖出来、截图贴上去就交差。但真正做过一轮的人会告诉你这个实验的核心根本不是“做出一个能跑的界面”而是训练一种把业务需求翻译成关系模型、再把关系模型落成可维护代码的完整链路能力。它通常出现在数据库系统课程的实践环节要求你围绕一个具体场景——比如学生选课、图书借阅、设备报修、小型仓储——完成需求分析、E-R建模、关系模式设计、建表、增删改查、事务处理和简单报表。适合谁适合已经学过SQL基础、但还没独立走完“从需求到系统”全流程的人。这个实验的价值在于它会逼你面对那些课本上一笔带过、实际开发中却天天出现的问题字段类型选错导致排序异常、外键约束让删除操作失败、并发更新把库存扣成负数。把这些坑踩一遍比背十遍范式定义都有用。2. 需求分析与E-R建模把一句业务描述拆成实体和联系2.1 先别急着建表用一句话锁定系统边界小型MIS最怕边界失控。常见做法是先用一句话写清楚系统为谁服务、管理什么、不做什么。比如“为某实验室管理设备借用与归还不涉及采购和财务”。这句话决定了后面所有实体和字段的范围。如果边界模糊你会不自觉地加进“供应商”“发票”“审批流”最后表越建越多实验报告写不完系统也跑不起来。我一般会拿一张纸左边写“谁”右边写“做什么”中间画箭头。谁包括管理员、普通用户做什么包括登记、查询、修改、删除、统计。每个动作追问三个问题操作对象是什么操作前后状态怎么变谁有权做这三个问题的答案基本就是实体、状态字段和权限字段的来源。2.2 用E-R图确定实体、属性和联系基数E-R建模阶段最容易翻车的地方是联系基数搞错。比如“学生选课”场景一个学生可以选多门课一门课可以被多个学生选这是多对多。如果你画成一对多后面建表时就会把课程ID塞进学生表导致一个学生只能选一门课。正确做法是拆出选课关系表把学生ID和课程ID作为联合主键。下面是一个设备借用场景的E-R要素梳理表用表格替代代码块因为这一步不需要写代码实体关键属性联系基数说明用户用户ID、姓名、角色借用1:N一个用户可多次借用设备设备ID、名称、状态被借用1:N一台设备可被多次借用借用记录记录ID、用户ID、设备ID、借出时间、归还时间关联用户与设备N:1 对用户N:1 对设备每次借用一条记录这张表看起来简单但它决定了后面所有SQL的写法。比如“查询某用户当前未归还设备”就需要从借用记录表里筛归还时间为空再关联设备表拿名称。如果E-R阶段没把借用记录独立成实体这个查询会变得非常别扭。2.3 从E-R到关系模式三个必须检查的转换规则转换规则课本上都有但实操中容易忽略三点。第一多对多联系必须独立成表不能合并到任何一端。第二一对一联系如果频率低可以合并到主表但要在实验报告里说明理由。第三自联系要小心比如“设备属于某个上级设备”外键指向同一张表删除时容易触发循环约束。我通常会写一个简单的检查清单每个实体有没有主键每个外键指向的表是否存在有没有字段可以推导出来却单独存储比如“年龄”可以由出生日期算出来就不该单独存否则更新时容易不一致。这一步做完关系模式基本就稳了。3. 建表与约束用SQL把设计意图钉死在数据库里3.1 建表语句里最容易被忽略的四个参数很多实验报告只写字段名和类型不写约束结果系统跑起来全靠应用层兜底。下面是一段设备借用系统的建表SQL我加了注释说明每个参数的作用-- 用户表角色用枚举约束避免应用层写错字符串 CREATE TABLE users ( user_id INT PRIMARY KEY AUTO_INCREMENT, user_name VARCHAR(50) NOT NULL, role ENUM(admin,normal) NOT NULL DEFAULT normal, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 设备表状态字段用枚举库存用无符号整数防止负数 CREATE TABLE devices ( device_id INT PRIMARY KEY AUTO_INCREMENT, device_name VARCHAR(100) NOT NULL, status ENUM(available,borrowed,maintenance) NOT NULL DEFAULT available, stock INT UNSIGNED NOT NULL DEFAULT 1, version INT NOT NULL DEFAULT 0 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 借用记录表外键约束保证引用完整性归还时间允许为空 CREATE TABLE borrow_records ( record_id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, device_id INT NOT NULL, borrow_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, return_time DATETIME DEFAULT NULL, CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(user_id), CONSTRAINT fk_device FOREIGN KEY (device_id) REFERENCES devices(device_id), INDEX idx_user_return (user_id, return_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;逻辑说明users表的role用ENUM而不是VARCHAR是为了让数据库帮你挡住非法角色值应用层传错时直接报错而不是悄悄写进去。devices表的stock用INT UNSIGNED是因为库存不可能为负用无符号类型可以在数据库层面挡住扣减到负数的操作。borrow_records表建了联合索引idx_user_return因为最常用的查询是“某用户当前未归还记录”这个索引能直接命中。参数说明ENGINEInnoDB是必须的因为只有InnoDB支持事务和外键。CHARSETutf8mb4支持中文和特殊字符。version字段是乐观锁用的后面并发控制会讲。3.2 外键约束的代价与取舍外键能保证引用完整性但会带来插入和删除时的额外检查开销。小型MIS数据量不大我一般建议保留外键因为实验报告里能体现你对完整性约束的理解。但要注意删除顺序先删借用记录再删设备否则外键会阻止删除。如果业务允许“软删除”可以加一个is_deleted字段避免物理删除带来的约束冲突。3.3 用CHECK约束和触发器补上业务规则MySQL 8.0之后支持CHECK约束可以写一些简单规则比如“归还时间不能早于借出时间”。但复杂规则还是建议放应用层或触发器。下面是一个触发器示例用于在借用时自动把设备状态改为borrowedDELIMITER // CREATE TRIGGER trg_borrow_update_device AFTER INSERT ON borrow_records FOR EACH ROW BEGIN UPDATE devices SET status borrowed, version version 1 WHERE device_id NEW.device_id AND status available; END // DELIMITER ;逻辑说明这个触发器在插入借用记录后自动更新设备状态避免应用层忘记改状态导致数据不一致。version version 1是为了配合乐观锁每次状态变更都递增版本号。参数说明DELIMITER //是为了让MySQL把整个触发器体当作一个语句处理。AFTER INSERT表示插入成功后执行。NEW.device_id引用新插入行的设备ID。注意触发器虽然方便但调试困难出错时往往只报一个模糊的错误码。建议只在规则非常明确且不常变时使用否则宁可写在应用层。4. 增删改查与事务让系统在并发下不丢数据4.1 四个典型查询的SQL写法与索引命中小型MIS的查询通常围绕“列表筛选分页”。下面四个查询覆盖了大部分场景-- 1. 查询所有可借设备按名称排序 SELECT device_id, device_name, stock FROM devices WHERE status available ORDER BY device_name LIMIT 20 OFFSET 0; -- 2. 查询某用户当前未归还记录 SELECT r.record_id, d.device_name, r.borrow_time FROM borrow_records r JOIN devices d ON r.device_id d.device_id WHERE r.user_id 1001 AND r.return_time IS NULL; -- 3. 统计每个设备的借用次数 SELECT d.device_name, COUNT(*) AS borrow_count FROM borrow_records r JOIN devices d ON r.device_id d.device_id GROUP BY d.device_id, d.device_name ORDER BY borrow_count DESC; -- 4. 分页查询借用历史按时间倒序 SELECT r.record_id, u.user_name, d.device_name, r.borrow_time, r.return_time FROM borrow_records r JOIN users u ON r.user_id u.user_id JOIN devices d ON r.device_id d.device_id ORDER BY r.borrow_time DESC LIMIT 10 OFFSET 20;逻辑说明第一个查询用status筛选如果status字段有索引能快速定位。第二个查询用idx_user_return联合索引user_id和return_time一起命中。第三个查询是聚合注意GROUP BY要包含device_name否则在严格模式下会报错。第四个查询涉及三表连接分页时OFFSET越大越慢数据量大时建议用游标分页。参数说明LIMIT 20 OFFSET 0表示取20条从第0条开始。COUNT(*)统计行数如果表很大可以用COUNT(1)或近似值。ORDER BY的字段最好有索引否则会触发文件排序。4.2 事务边界怎么划一个借用操作的完整事务借用设备通常包含三个动作检查库存、插入借用记录、更新设备状态。这三个动作必须在一个事务里否则可能出现“记录插入了但状态没改”的脏数据。START TRANSACTION; -- 检查库存并锁定行防止并发扣减 SELECT stock FROM devices WHERE device_id 2001 FOR UPDATE; -- 如果库存大于0插入借用记录 INSERT INTO borrow_records (user_id, device_id) VALUES (1001, 2001); -- 更新设备状态和库存 UPDATE devices SET status borrowed, stock stock - 1, version version 1 WHERE device_id 2001 AND stock 0; COMMIT;逻辑说明FOR UPDATE会对该行加排他锁其他事务必须等待从而避免两个用户同时借到最后一台设备。stock 0作为更新条件即使锁没拦住也不会把库存扣成负数。COMMIT提交后锁释放。参数说明START TRANSACTION开启事务COMMIT提交出错时用ROLLBACK回滚。FOR UPDATE只在事务内有效 autocommit模式下单独执行会立即释放锁。4.3 乐观锁与悲观锁的选择悲观锁用FOR UPDATE适合冲突频繁的场景但会降低并发。乐观锁用版本号适合冲突少的场景。小型MIS里设备借用冲突不算高我一般用乐观锁更新时检查version是否变化如果变化说明有人先改了应用层重试。UPDATE devices SET status borrowed, stock stock - 1, version version 1 WHERE device_id 2001 AND version 5 AND stock 0;如果返回受影响行数为0说明版本号不匹配或库存不足应用层需要重新读取再试。这种方式没有锁等待但需要应用层配合重试逻辑。5. 避坑与排查那些让实验报告返工的血泪经验5.1 中文乱码从连接层到字段层要统一现象插入中文后查询显示问号。原因数据库、表、连接三处字符集不一致。解决建库时指定utf8mb4连接字符串加characterEncodingutf8Java项目还要检查serverTimezone。我一般会在建表语句末尾统一写DEFAULT CHARSETutf8mb4连接URL里显式指定字符集。5.2 外键删除失败先查引用再删现象删除设备时报“Cannot delete or update a parent row”。原因借用记录表还有该设备的引用。解决先删借用记录再删设备或者用ON DELETE CASCADE级联删除但级联删除风险高实验报告里要说明业务是否允许。我一般建议先查引用数量确认无未归还记录后再删。5.3 分页查询越翻越慢OFFSET的代价现象第1页很快第100页要几秒。原因OFFSET 2000需要扫描前2000行再丢弃。解决用游标分页记录上一页最后一条的ID下一页用WHERE id last_id LIMIT 20。这种方式在实验报告里能体现你对性能的理解。5.4 事务未提交导致锁等待现象某个操作一直卡住其他操作也超时。原因前一个事务开了FOR UPDATE但没提交锁一直不释放。解决检查代码里是否所有分支都有COMMIT或ROLLBACK异常时也要回滚。我一般用try-catch-finally保证事务结束。5.5 枚举值写错导致插入失败现象插入用户时提示“Data truncated for column role”。原因应用层传了Admin但枚举定义是admin大小写不匹配。解决统一用小写或者在应用层做校验。枚举虽然安全但大小写敏感容易踩坑。6. 从实验报告到可演示系统三个进阶技巧6.1 用视图简化复杂查询实验报告里经常需要展示“借用记录详情”涉及三表连接。可以建一个视图把连接逻辑封装起来CREATE VIEW v_borrow_detail AS SELECT r.record_id, u.user_name, d.device_name, r.borrow_time, r.return_time, CASE WHEN r.return_time IS NULL THEN 未归还 ELSE 已归还 END AS status_text FROM borrow_records r JOIN users u ON r.user_id u.user_id JOIN devices d ON r.device_id d.device_id;之后查询直接SELECT * FROM v_borrow_detail WHERE user_name 张三应用层不用重复写连接。视图的代价是每次查询都展开数据量大时性能不如物化视图但小型MIS足够用。6.2 用存储过程封装借用和归还把借用逻辑写成存储过程应用层只调一个接口减少SQL拼接错误DELIMITER // CREATE PROCEDURE sp_borrow_device(IN p_user_id INT, IN p_device_id INT, OUT p_result VARCHAR(50)) BEGIN DECLARE v_stock INT; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; SET p_result error; END; START TRANSACTION; SELECT stock INTO v_stock FROM devices WHERE device_id p_device_id FOR UPDATE; IF v_stock 0 THEN INSERT INTO borrow_records (user_id, device_id) VALUES (p_user_id, p_device_id); UPDATE devices SET status borrowed, stock stock - 1 WHERE device_id p_device_id; COMMIT; SET p_result success; ELSE ROLLBACK; SET p_result no_stock; END IF; END // DELIMITER ;逻辑说明存储过程内部处理了事务、异常和库存检查应用层只需传参和读结果。EXIT HANDLER捕获异常后回滚避免部分更新。参数说明IN表示输入参数OUT表示输出参数。调用方式CALL sp_borrow_device(1001, 2001, result); SELECT result;。6.3 用EXPLAIN验证索引是否命中写完查询后用EXPLAIN看执行计划确认是否走了索引EXPLAIN SELECT * FROM borrow_records WHERE user_id 1001 AND return_time IS NULL;如果type是ALL说明全表扫描需要加索引。如果key是idx_user_return说明命中。这个习惯能帮你在实验报告里写出有说服力的性能分析。6.4 一个我常犯的错忘记备份就改表结构有一次我直接ALTER TABLE删了一个字段结果发现应用层还在用只能从旧备份恢复。后来我养成习惯改表前先CREATE TABLE backup_table AS SELECT * FROM original_table确认无误再改。这个习惯在实验报告里也能体现你的工程素养。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

SQL Server各版本下载地址全解析:从选型到离线部署避坑指南

SQL Server各版本下载地址全解析:从选型到离线部署避坑指南

简介:SQL Server数据库各版本下载地址集合,面向需要安装、部署或维护SQL Server的开发人员与运维人员。资料以PDF文档形式整理,集中收录从SQL Server 2000到2019的企业版、开发版、标准版下载链接,并附SP1、SP3、SP4等补丁地址&am…

2026/10/11 16:35:47 阅读更多 →
SQL Server 各版本安装包下载避坑全攻略(2008 R2 到 2022)

SQL Server 各版本安装包下载避坑全攻略(2008 R2 到 2022)

简介:这份资源将 Microsoft SQL Server 从 2000 到 2019 的主要版本整理成一份可快速检索的清单,覆盖企业版、开发版、标准版,以及各版本的 32 位/64 位下载地址,并附有部分补丁与服务包链接。对需要安装、测试或维护 SQL Server …

2026/10/11 1:45:03 阅读更多 →
2020-2022成都市矢量数据实战:从清洗到PostGIS空间分析

2020-2022成都市矢量数据实战:从清洗到PostGIS空间分析

简介:这份2020—2022年成都市矢量数据资源面向GIS从业者、城市规划研究者、交通与水文分析人员及地图应用开发者,用于支撑空间分析、地图制图与决策支持等场景。数据覆盖路网(含高速、国道、省道、县道、乡道及铁路地铁轻轨)、河流…

2026/10/11 15:22:50 阅读更多 →

最新新闻

基于A星算法的无人机三维路径规划Matlab实现与优化

基于A星算法的无人机三维路径规划Matlab实现与优化

做无人机的人基本都绕不开路径规划这道坎。“基于A星算法的无人机三维路径规划算法研究(Matlab代码实现)” 这个题目看着规整,但真正落地的时候,坑比想象的多:地图怎么建、邻居节点怎么扩展、启发函数怎么写才能既快又…

2026/10/12 0:51:25 阅读更多 →
VS Code 中直接使用 Codex 教程及连接失败解决方案:TaoToken 统一 Key 接入与排错实录

VS Code 中直接使用 Codex 教程及连接失败解决方案: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/12 0:50:24 阅读更多 →
企业 Agent 提示词注入防御实战:双重护栏与对抗语义检测

企业 Agent 提示词注入防御实战:双重护栏与对抗语义检测

在企业将多智能体(Multi-Agent)系统接入客服咨询、内部知识检索或自动化办公流后,安全攻防的对抗维度发生了一场根本性范式转移:传统的 SQL 注入或跨站脚本攻击(XSS)正在退居二线,而以自然语言为…

2026/10/12 0:47:23 阅读更多 →
Cursor怎么使用:3分钟上手Cursor键盘快捷键速查,用TaoToken统一Key接入GPT4与Claude 3.5辅助编程

Cursor怎么使用:3分钟上手Cursor键盘快捷键速查,用TaoToken统一Key接入GPT4与Claude 3.5辅助编程

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

2026/10/12 0:46:23 阅读更多 →
我喜欢的 VSCode 插件:用 TaoToken 统一管理 AI 编码助手的 Key 与 Base URL

我喜欢的 VSCode 插件:用 TaoToken 统一管理 AI 编码助手的 Key 与 Base URL

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

2026/10/12 0:46:23 阅读更多 →
基于SVDD算法的数据分类MATLAB仿真:原理、代码与避坑指南

基于SVDD算法的数据分类MATLAB仿真:原理、代码与避坑指南

简介:本资源为基于SVDD算法的数据分类MATLAB仿真程序包,面向机器学习初学者、模式识别课程学习者及需要复现单类分类实验的科研人员,帮助理解支持向量数据描述在异常检测与数据分类中的建模流程。包内共16个文件,以12个m脚本为核心…

2026/10/12 0:45:23 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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 阅读更多 →