C# Winform 连接 SQL Server 环境配置与避坑指南

简介:这份资源面向C#与数据库开发的入门学习者,聚焦Winform桌面端如何同时实现SQL Server的网络连接与本地连接,并完成增删改查这一企业级应用的核心数据管理能力。包内共28个文件,以cs源码、resx与resources资源文件、exe可执行程序、pdb调试符号为主,另附sql查询脚本、sln解决方案、csproj工程文件及说明文档,压缩包约168KB,结构完整可直接运行调试。资源中给出了连接字符串写法、ADO.NET组件用法、T-SQL增删改查语句示例,以及app.config配置方式,并涉及异常处理、事务管理与DataGridView数据绑定等实用要点,便于新手对照源码理解网络与本地两种连接模式的差异。目前已有2675人学习下载,适合希望快速上手Winform数据库编程、需要一份可运行范例来练习增删改查与连接配置的初学者参考。

1. 从一次“连不上数据库”的翻车说起:这套环境到底装什么

如果你正在搜“C# Winform 连接 SQL Server 怎么配置”,大概率已经卡在某个环节了。我见过太多新手在这一步翻车:代码写得没问题,SqlConnection也 new 出来了,结果一运行就弹“连接超时”或者“登录失败”。更玄学的是,同一份代码,在别人机器上跑得好好的,换到自己电脑就报错。问题往往不在 C# 代码本身,而在 SQL Server 的安装配置、连接字符串的写法、以及本地和网络两种连接方式的差异上。

这套环境说白了就三样东西:Visual Studio(写 Winform 界面和逻辑)、SQL Server(存数据)、以及两者之间的连接通道。听起来简单,但版本选不对、服务没启动、协议没开、防火墙拦了,任何一个环节都能让你卡半天。这篇笔记就是把我自己装这套环境时踩过的坑、验证过的步骤完整记下来,适合刚接触 Winform 数据库开发的新手,也适合想理清本地连接和网络连接区别的熟手。装完的目标很明确:Winform 程序能通过本地或网络两种方式连上 SQL Server,增删改查四个操作都能跑通。

2. 装之前先把版本和环境定下来:SQL Server 与 Visual Studio 怎么选

2.1 SQL Server 版本选择:Express 够用,但别装错位数

新手最容易在 SQL Server 版本上纠结。我的建议很直接:本地开发用 SQL Server Express 就够,免费且支持 10GB 数据库,增删改查完全没问题。但要注意两个点:一是位数,二是实例名。

位数方面,现在基本都是 64 位系统,装 64 位的 SQL Server Express。如果你之前装过 32 位的,卸载不干净会导致新装实例起不来。常见做法是装之前先在“控制面板 → 程序和功能”里把所有带 SQL Server 字样的条目卸掉,再手动删掉C:\Program Files\Microsoft SQL Server残留目录。

实例名方面,默认实例名是SQLEXPRESS,连接字符串里要写Data Source=.\SQLEXPRESS或者Data Source=localhost\SQLEXPRESS。如果你装的时候选了命名实例,比如MSSQLSERVER,那连接字符串就得跟着改。我一般会统一用默认实例,省得后面写连接字符串时搞混。

Visual Studio 这边,装 2019 或 2022 社区版都行,关键是安装时勾选“.NET 桌面开发”工作负载。这个工作负载里包含了 Winform 设计器、.NET Framework 或 .NET 的桌面运行时,不勾的话新建项目时找不到 Winform 模板。

2.2 安装 SQL Server Express 的具体步骤

下载安装包后,运行安装程序,选择“基本”安装类型。这一步会默认装一个SQLEXPRESS实例,身份验证模式选“混合模式”,并设置 sa 账户密码。混合模式的意思是既支持 Windows 身份验证,也支持 SQL Server 账户密码登录,后面网络连接时用 sa 账户更方便。

安装完成后,打开“SQL Server 配置管理器”,检查两件事:一是 SQL Server 服务是否正在运行,二是 TCP/IP 协议是否已启用。默认情况下,Express 版的 TCP/IP 是禁用的,网络连接必须手动开启。

# 在 SQL Server 配置管理器中操作: # 1. 展开“SQL Server 网络配置” → “SQLEXPRESS 的协议” # 2. 右键“TCP/IP” → 启用 # 3. 双击“TCP/IP” → “IP 地址”选项卡 → 找到“IPAll” # 4. 确认 TCP 端口为 1433(或自定义端口),TCP 动态端口留空 # 5. 重启 SQL Server 服务使配置生效

这段操作的核心是让 SQL Server 监听 TCP 端口。默认实例通常用 1433,命名实例可能用动态端口。如果你在 IPAll 里看到 TCP 动态端口有值,把它清空,只保留 TCP 端口 1433,这样连接字符串里就不用写端口号,省事。

2.3 验证 SQL Server 是否装好

装完后别急着写代码,先用 SQL Server Management Studio(SSMS)连一下。SSMS 可以单独下载,也可以在安装 SQL Server 时勾选安装。打开 SSMS,服务器名称填.\SQLEXPRESS,身份验证选“Windows 身份验证”,点连接。如果能连上,说明服务正常。然后再试一次“SQL Server 身份验证”,用 sa 账户和刚才设的密码登录,能连上就说明混合模式配置正确。

如果 SSMS 连不上,先看服务是否启动,再看 TCP/IP 是否启用,最后看防火墙有没有拦 1433 端口。这三步排查完,基本能解决 90% 的安装问题。

3. 本地连接怎么配:连接字符串与 Winform 项目搭建

3.1 创建 Winform 项目并引入数据库依赖

打开 Visual Studio,新建项目,选“Windows 窗体应用 (.NET Framework)”,项目名随便起,比如DbDemo。框架版本选 4.7.2 或 4.8 都行,这两个版本对 SQL Server 的支持都很稳定。

项目建好后,不需要额外引入 NuGet 包,因为System.Data.SqlClient已经包含在 .NET Framework 里了。如果你用的是 .NET 6 或更高版本的 Winform,那需要单独装Microsoft.Data.SqlClientNuGet 包。这里以 .NET Framework 为例,直接在代码里using System.Data.SqlClient;就能用。

3.2 本地连接字符串的写法与参数说明

本地连接指的是 Winform 程序和 SQL Server 在同一台机器上,用 Windows 身份验证或 SQL Server 身份验证都行。我一般用 SQL Server 身份验证,因为后面切换到网络连接时改动最小。

// 本地连接字符串,使用 SQL Server 身份验证 string connStr = "Data Source=.\\SQLEXPRESS;Initial Catalog=TestDb;User ID=sa;Password=你的密码;"; // 如果是 Windows 身份验证,写法如下: // string connStr = "Data Source=.\\SQLEXPRESS;Initial Catalog=TestDb;Integrated Security=True;";

参数逐个说:Data Source是服务器地址,.\SQLEXPRESS表示本机默认实例;Initial Catalog是数据库名,这里假设你已经建了一个叫TestDb的数据库;User ID和Password是 sa 账户的凭据;Integrated Security=True表示用当前 Windows 账户登录,不需要输密码。

注意:连接字符串里的反斜杠要转义,.\SQLEXPRESS在 C# 字符串里写成.\\SQLEXPRESS。如果你在配置文件里写,就不用双反斜杠,直接写.\SQLEXPRESS。

3.3 建库建表与增删改查代码落地

先在 SSMS 里建一个测试数据库和一张表,方便后面验证。

-- 建库 CREATE DATABASE TestDb; GO -- 建表 USE TestDb; GO CREATE TABLE Users ( Id INT PRIMARY KEY IDENTITY(1,1), Name NVARCHAR(50) NOT NULL, Age INT NOT NULL ); GO

然后在 Winform 窗体上放四个按钮:新增、删除、修改、查询,再放一个 DataGridView 用来显示数据。下面是增删改查的核心代码。

using System; using System.Data; using System.Data.SqlClient; using System.Windows.Forms; namespace DbDemo { public partial class Form1 : Form { // 本地连接字符串 private string connStr = "Data Source=.\\SQLEXPRESS;Initial Catalog=TestDb;User ID=sa;Password=你的密码;"; public Form1() { InitializeComponent(); } // 查询 private void btnQuery_Click(object sender, EventArgs e) { using (SqlConnection conn = new SqlConnection(connStr)) { try { conn.Open(); string sql = "SELECT * FROM Users"; SqlDataAdapter adapter = new SqlDataAdapter(sql, conn); DataTable dt = new DataTable(); adapter.Fill(dt); dataGridView1.DataSource = dt; } catch (Exception ex) { MessageBox.Show("查询失败:" + ex.Message); } } } // 新增 private void btnInsert_Click(object sender, EventArgs e) { using (SqlConnection conn = new SqlConnection(connStr)) { try { conn.Open(); string sql = "INSERT INTO Users (Name, Age) VALUES (@Name, @Age)"; SqlCommand cmd = new SqlCommand(sql, conn); cmd.Parameters.AddWithValue("@Name", "张三"); cmd.Parameters.AddWithValue("@Age", 25); int rows = cmd.ExecuteNonQuery(); MessageBox.Show("新增成功,影响行数:" + rows); } catch (Exception ex) { MessageBox.Show("新增失败:" + ex.Message); } } } // 修改 private void btnUpdate_Click(object sender, EventArgs e) { using (SqlConnection conn = new SqlConnection(connStr)) { try { conn.Open(); string sql = "UPDATE Users SET Age = @Age WHERE Name = @Name"; SqlCommand cmd = new SqlCommand(sql, conn); cmd.Parameters.AddWithValue("@Age", 30); cmd.Parameters.AddWithValue("@Name", "张三"); int rows = cmd.ExecuteNonQuery(); MessageBox.Show("修改成功,影响行数:" + rows); } catch (Exception ex) { MessageBox.Show("修改失败:" + ex.Message); } } } // 删除 private void btnDelete_Click(object sender, EventArgs e) { using (SqlConnection conn = new SqlConnection(connStr)) { try { conn.Open(); string sql = "DELETE FROM Users WHERE Name = @Name"; SqlCommand cmd = new SqlCommand(sql, conn); cmd.Parameters.AddWithValue("@Name", "张三"); int rows = cmd.ExecuteNonQuery(); MessageBox.Show("删除成功,影响行数:" + rows); } catch (Exception ex) { MessageBox.Show("删除失败:" + ex.Message); } } } } }

这段代码里,using语句确保连接用完就释放,避免连接池耗尽。SqlDataAdapter用于查询并填充 DataTable,SqlCommand配合Parameters.AddWithValue防止 SQL 注入。每个操作都包在 try-catch 里,出错时弹窗提示,方便定位问题。

4. 网络连接怎么配:从本地到远程的迁移与防火墙设置

4.1 网络连接与本地连接的本质区别

本地连接和网络连接在代码层面只有一个区别:Data Source的值不同。本地写.\SQLEXPRESS或localhost,网络连接写目标机器的 IP 地址或主机名,比如192.168.1.100或192.168.1.100,1433。但背后涉及的东西多得多:目标机器的 SQL Server 必须启用 TCP/IP、防火墙必须放行 1433 端口、sa 账户必须允许远程登录、SQL Server 必须配置为允许远程连接。

我见过最常见的情况是:代码里把Data Source改成 IP 后,运行报“连接超时”或“找不到服务器”。这时候别急着改代码,先按下面几步排查。

4.2 目标机器上的 SQL Server 远程访问配置

在装 SQL Server 的那台机器上,打开 SQL Server 配置管理器,确认 TCP/IP 已启用,并且 IPAll 里的 TCP 端口是 1433。然后打开“SQL Server Management Studio”,右键服务器 → 属性 → 连接,勾选“允许远程连接到此服务器”。

接着检查 sa 账户是否启用。在 SSMS 里展开“安全性 → 登录名”,找到 sa,右键属性 → 状态,确认“登录”是“启用”。如果 sa 被禁用,右键启用即可。

最后是防火墙。在目标机器上新建入站规则,放行 TCP 1433 端口。

# 在目标机器上以管理员身份运行 PowerShell New-NetFirewallRule -DisplayName "SQL Server 1433" -Direction Inbound -Protocol TCP -LocalPort 1433 -Action Allow

这条命令创建一条入站规则,允许 TCP 1433 端口的流量进入。如果你改了 SQL Server 的端口,把 1433 换成实际端口。执行完后,在另一台机器上用telnet 目标IP 1433测试端口是否通。如果 telnet 不通,说明防火墙或网络还有问题。

4.3 网络连接字符串的写法与测试

网络连接字符串和本地几乎一样,只改Data Source。

// 网络连接字符串,假设目标机器 IP 为 192.168.1.100 string connStr = "Data Source=192.168.1.100,1433;Initial Catalog=TestDb;User ID=sa;Password=你的密码;";

注意 IP 和端口之间用逗号分隔,不是冒号。如果目标机器用的是默认实例且端口是 1433,也可以省略端口,直接写Data Source=192.168.1.100。但写上端口更稳妥,避免因动态端口导致连接失败。

测试网络连接时,我一般会先写一个简单的控制台程序,只做conn.Open()和conn.Close(),确认能连上再改 Winform 代码。这样能把网络问题和 Winform 代码问题分开排查。

5. 避坑与排查:这五个坑我踩过,你别再踩

5.1 坑一:连接字符串里反斜杠没转义

现象:代码编译通过,运行时报“不支持关键字”或“初始化字符串格式不正确”。

原因:C# 字符串里\是转义字符,.\SQLEXPRESS被解析成.SQLEXPRESS,SQL Server 找不到这个实例。

解决:写成.\\SQLEXPRESS,或者用@前缀写@".\SQLEXPRESS"。在配置文件里写则不需要双反斜杠。

5.2 坑二:SQL Server 服务没启动或 TCP/IP 没启用

现象:本地连接正常,网络连接报“连接超时”或“无法连接到服务器”。

原因:目标机器的 SQL Server 服务停了,或者 TCP/IP 协议没启用,或者端口不是 1433。

解决:在目标机器上打开 SQL Server 配置管理器,确认服务运行中,TCP/IP 已启用,IPAll 的 TCP 端口为 1433。改完后重启 SQL Server 服务。

5.3 坑三:防火墙拦了 1433 端口

现象:telnet 目标 IP 1433 不通,但目标机器上 SQL Server 服务正常。

原因:Windows 防火墙默认阻止入站 1433 端口。

解决:在目标机器上添加入站规则放行 1433 端口,或者临时关闭防火墙测试。生产环境不建议关防火墙,加规则更稳妥。

5.4 坑四:sa 账户被禁用或密码错误

现象:连接时报“登录失败,用户 sa 登录失败”。

原因:sa 账户被禁用,或者密码输错,或者 SQL Server 只允许 Windows 身份验证。

解决:在 SSMS 里启用 sa 账户并重置密码,确认服务器属性里允许 SQL Server 身份验证和 Windows 身份验证混合模式。

5.5 坑五:连接字符串里数据库名写错

现象:连接时报“无法打开登录所请求的数据库”。

原因:Initial Catalog指定的数据库不存在,或者当前账户没有权限访问。

解决:在 SSMS 里确认数据库名拼写正确,并给 sa 账户授予该数据库的访问权限。

6. 装完怎么验证跑通:一个最小可复现的检查清单

装完环境后,别急着写复杂业务,先按这个清单走一遍,确认每一步都通。

检查项操作预期结果
SQL Server 服务打开配置管理器查看服务状态正在运行
TCP/IP 协议查看 SQLEXPRESS 协议属性已启用,端口 1433
SSMS 本地连接用.\SQLEXPRESS连接连接成功
SSMS 网络连接用192.168.1.100,1433连接连接成功
防火墙端口在另一台机器 telnet 1433端口通
Winform 本地查询运行程序点查询按钮DataGridView 显示数据
Winform 网络查询改连接字符串为 IP 后查询DataGridView 显示数据
增删改操作分别点新增、修改、删除弹窗提示影响行数

这个清单里,前五步是环境层面的验证,后三步是代码层面的验证。如果前五步都通,后三步基本不会出问题。如果后三步有问题,先回看前五步,大概率是环境没配好。

我自己的习惯是:每次换机器或者重装 SQL Server 后,都强制走一遍这个清单,尤其是 telnet 那一步。因为防火墙和端口的问题最隐蔽,代码写得再对也连不上。从那以后我每次部署新环境都先跑一遍这个清单,省得后面调试代码时怀疑人生。希望帮到你。

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

相关新闻

AI数据分析翻译官:把Excel表格变成会说话的业务结论

AI数据分析翻译官:把Excel表格变成会说话的业务结论

看到数据就头大?我可太懂了。我见过不少朋友,一提到“看报表”就开始眼神放空,运营、产品、市场,甚至部分管理者,几乎天天被Excel糊脸,却不知道从哪里下嘴。这种状态下,写周报、做复盘、准备汇报…

2026/10/20 19:46:36 阅读更多 →
SpringBoot全国降水数据分析与可视化系统实战:从数据清洗到ECharts联动

SpringBoot全国降水数据分析与可视化系统实战:从数据清洗到ECharts联动

上个月有个同学拿了个毕业设计题目来问,题目大概是"基于SpringBoot的全国降水数据分析与展示可视化系统"。他当时第一反应是:这不就是一个地图页面,后端查数据返回,前端把点和颜色画出来就行了吗?等我让他把…

2026/10/20 19:46:36 阅读更多 →
ST-LINK固件升级指南:V2.37.26救砖实操与避坑全解析

ST-LINK固件升级指南:V2.37.26救砖实操与避坑全解析

简介:本资源是ST官方STLink调试编程器的固件升级工具包STSW-LINK007 V2-37-26正式发布版,面向STM32/STM8嵌入式开发者、硬件工程师及高校实验教学人员,解决STLink设备固件陈旧导致的IDE兼容性异常、新MCU型号识别失败、调试连接不稳定等实际问…

2026/10/20 19:45:34 阅读更多 →

最新新闻

YOLO26目标检测训练到RK3588部署:ONNX与RKNN适配实践

YOLO26目标检测训练到RK3588部署:ONNX与RKNN适配实践

YOLO26 目标检测的训练到瑞芯微平台适配,这条链路我最近刚完整跑通一遍。先说结论:真正卡人的地方不在训练本身,而在从 PyTorch 模型走向 RKNN 运行时的那几步——ONNX 导出、算子兼容、INT8 量化,每一个都埋着不少雷。我是在给一…

2026/10/20 20:43:28 阅读更多 →
梯度增强PINN:攻克Allen-Cahn方程多陡峭界面难题

梯度增强PINN:攻克Allen-Cahn方程多陡峭界面难题

Allen-Cahn方程是我调过的最“拧巴”的PDE之一。它表达式极简,一个∂u/∂t ε∂u/∂x u - u,但解的画面完全不简单:能量驱动下的相分离会让解在空间里劈出好几条尖锐的界面,这些界面随时间演化、移动、合并。所谓“多非常陡峭区…

2026/10/20 20:43:28 阅读更多 →
计算机教材内容策划与写作:从概念到工程实践

计算机教材内容策划与写作:从概念到工程实践

抱歉,我无法处理这个请求。

2026/10/20 20:43:28 阅读更多 →
从图像到数据:HaoCurve曲线提取实战与避坑指南

从图像到数据:HaoCurve曲线提取实战与避坑指南

简介:HaoCurve(薅曲线)是一套面向科研人员、工程师与数据分析者的MATLAB曲线绘制工具源码,适合需要在MATLAB环境中快速生成、编辑和分析数据曲线图的用户,尤其对希望深入理解绘图脚本实现、进行二次开发的进阶使用者更…

2026/10/20 20:43:28 阅读更多 →
CLI编码代理失败过程解剖:从轨迹日志到根因分析

CLI编码代理失败过程解剖:从轨迹日志到根因分析

读到一篇很有意思的论文,标题叫《Failure as a Process: An Anatomy of CLI Coding Agent Trajectories》。这两年命令行AI编程工具越来越多,从最初的“能写一段函数”到现在能在真实仓库里自己定位问题、改代码、跑测试,甚至提交补丁。但大多…

2026/10/20 20:43:28 阅读更多 →
小橘子V4.790:本地可调试塔防策略模拟器

小橘子V4.790:本地可调试塔防策略模拟器

简介:本资源是《向僵尸开炮》游戏的自动化对局辅助工具——小橘子V4.790版本完整部署包,面向游戏AI开发者、自动化测试工程师及休闲游戏技术爱好者,用于快速实现人机对战环境下的策略执行、界面识别与操作模拟。压缩包共741个文件&#xff0c…

2026/10/20 20:42:25 阅读更多 →

日新闻

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/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

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

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

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

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

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在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/20 10:02:08 阅读更多 →
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/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练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/20 9:50:45 阅读更多 →