C# WinForms + SQL Server 库存管理系统实战:从建表到出库完整落地
简介这份资源是一套基于C#与C/S架构的库存管理系统源码面向正在学习C#桌面开发、希望动手实践数据库与界面交互的初学者和进阶者。系统围绕商品入库、出库、库存盘点与预警等核心业务展开客户端负责图形界面交互服务端处理数据存储与业务逻辑可作为课程设计或自学练手的参考项目。压缩包共309个文件约4.74MB以62个cs源码文件、25个resx与resources资源文件、83张jpg与50张bmp界面素材为主另含dll依赖库、xsd数据集、db数据库文件及Visual Studio解决方案与项目配置结构完整便于直接打开继续开发。目前已有350人学习下载。读者可从中了解数据库表结构设计、数据操作实现与用户界面搭建思路并借助数据库表注释文档快速理解各表字段含义适合作为构建同类库存管理应用的实践范本。1. 用 C# 写一套库存管理系统从建表到出库一个 C/S 项目的完整落地路径很多做企业内部工具的朋友都遇到过这种场景仓库那边还在用 Excel 记进出库月底对账对到怀疑人生老板一句“能不能做个系统”就落到你头上。这个用 C# 做的库存管理系统就是冲着这个需求去的——它是一套典型的 C/S 架构桌面应用客户端负责界面交互和业务操作数据库负责数据持久化覆盖商品档案、入库、出库、库存查询、预警提醒这几条主线。适合谁适合手里有 C# 基础、想找一个完整项目练手或直接改造成公司内部工具的开发者。它不追求花哨胜在结构清晰、能跑通、能改。下面我按“先看清它是什么再跑起来最后动手改”的顺序拆一遍。2. 项目定位与技术选型为什么是 WinForms SQL Server 这套组合2.1 这套系统到底解决什么问题库存管理系统的核心诉求其实就三件事东西进来了要记清楚、东西出去了要扣得准、账面上的数要随时能查。这个项目围绕这三件事展开功能模块大致分成五块商品管理维护商品编号、名称、规格、单位、分类、库存上下限等基础信息是所有业务的数据源头。入库管理记录采购入库、退货入库等场景入库时自动增加对应商品库存。出库管理记录销售出库、领用出库等场景出库时校验库存是否充足然后扣减。库存查询按商品、分类、时间等条件筛选当前库存和流水记录。预警提醒当某个商品库存低于设定的下限时在界面上给出提示。这套功能划分是库存类项目最通用的骨架不管后面怎么扩展基本都跑不出这个范围。项目正文里没有给出更细的模块说明但按这个场景下合格开发最常采用的做法上面这几块是标配。2.2 技术栈拆解C# WinForms ADO.NET SQL Server项目标题明确写了 C#关键词里带了 C/S所以技术选型基本锁定在桌面端。具体到实现层面常见做法是这样一套组合层次技术选择说明界面层WinForms拖控件快适合内部工具学习成本低业务逻辑层C# 类库/服务类封装入库、出库、库存计算等规则数据访问层ADO.NET直接用 SqlConnection、SqlCommand 操作数据库数据库SQL Server关系型存储事务支持好适合库存扣减场景为什么不用 WPF 或者 Web因为 C/S 内部工具的核心诉求是开发快、部署简单、不依赖浏览器。WinForms 虽然老但拖拽式布局加上事件驱动模型对于表单密集型的库存系统来说效率很高。ADO.NET 虽然写起来比 ORM 啰嗦但胜在可控——库存扣减这种涉及事务的操作手写 SQL 反而更清楚每一步在干什么。提示如果你的团队已经在用 Entity Framework 或 Dapper完全可以替换掉 ADO.NET 那一层业务逻辑不受影响。2.3 数据库表结构设计库存系统的地基是表结构。按这个项目的功能范围核心表大概长这样-- 商品表存基础信息 CREATE TABLE Product ( ProductId INT IDENTITY(1,1) PRIMARY KEY, ProductCode NVARCHAR(50) NOT NULL UNIQUE, -- 商品编号唯一 ProductName NVARCHAR(100) NOT NULL, Category NVARCHAR(50), Unit NVARCHAR(20), StockQty INT DEFAULT 0, -- 当前库存数量 MinStock INT DEFAULT 0, -- 库存下限用于预警 CreateTime DATETIME DEFAULT GETDATE() ); -- 入库记录表 CREATE TABLE StockIn ( InId INT IDENTITY(1,1) PRIMARY KEY, ProductId INT NOT NULL, Quantity INT NOT NULL, InTime DATETIME DEFAULT GETDATE(), Operator NVARCHAR(50), Remark NVARCHAR(200), FOREIGN KEY (ProductId) REFERENCES Product(ProductId) ); -- 出库记录表 CREATE TABLE StockOut ( OutId INT IDENTITY(1,1) PRIMARY KEY, ProductId INT NOT NULL, Quantity INT NOT NULL, OutTime DATETIME DEFAULT GETDATE(), Operator NVARCHAR(50), Remark NVARCHAR(200), FOREIGN KEY (ProductId) REFERENCES Product(ProductId) );这里有个设计取舍值得说库存数量直接存在 Product 表里而不是每次从流水表实时汇总。原因是库存查询是高频操作实时汇总在数据量大了之后会明显变慢。代价是每次入库出库都要同步更新 StockQty 字段必须放在同一个事务里否则会出现流水和库存对不上的情况。这个坑后面避坑章节还会展开。3. 核心模块拆解入库、出库、库存查询的代码实现3.1 数据访问层的封装不管业务怎么变数据库连接和命令执行是重复度最高的部分。我一般会先抽一个简单的数据库帮助类把连接字符串管理和基础执行封装起来public class DbHelper { // 连接字符串实际项目中建议放到配置文件 private static readonly string ConnStr Server.;DatabaseStockDB;Integrated SecurityTrue;; // 执行增删改返回受影响行数 public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters) { using (var conn new SqlConnection(ConnStr)) using (var cmd new SqlCommand(sql, conn)) { if (parameters ! null parameters.Length 0) cmd.Parameters.AddRange(parameters); conn.Open(); return cmd.ExecuteNonQuery(); } } // 执行查询返回 DataTable public static DataTable ExecuteQuery(string sql, params SqlParameter[] parameters) { using (var conn new SqlConnection(ConnStr)) using (var cmd new SqlCommand(sql, conn)) { if (parameters ! null parameters.Length 0) cmd.Parameters.AddRange(parameters); var adapter new SqlDataAdapter(cmd); var dt new DataTable(); adapter.Fill(dt); return dt; } } }这段代码的关键点在于参数化查询。很多新手图省事直接拼 SQL 字符串比如SELECT * FROM Product WHERE ProductCode code 这样写不仅有 SQL 注入风险遇到商品名里带单引号还会直接报错。用SqlParameter传参是必须养成的习惯。另外using语句保证连接和命令对象用完即释放避免连接池被占满。3.2 入库操作事务里同时写流水和更新库存入库看起来简单——加库存、记一笔——但这两步必须原子化。如果流水写进去了、库存没更新账就乱了。所以入库方法要开事务public bool StockIn(int productId, int quantity, string operatorName, string remark) { using (var conn new SqlConnection(ConnStr)) { conn.Open(); using (var tran conn.BeginTransaction()) // 开启事务 { try { // 第一步插入入库流水 string sqlIn INSERT INTO StockIn(ProductId, Quantity, Operator, Remark) VALUES(pid, qty, op, remark); using (var cmd new SqlCommand(sqlIn, conn, tran)) { cmd.Parameters.AddWithValue(pid, productId); cmd.Parameters.AddWithValue(qty, quantity); cmd.Parameters.AddWithValue(op, operatorName); cmd.Parameters.AddWithValue(remark, remark ?? ); cmd.ExecuteNonQuery(); } // 第二步更新商品库存 string sqlUpdate UPDATE Product SET StockQty StockQty qty WHERE ProductId pid; using (var cmd new SqlCommand(sqlUpdate, conn, tran)) { cmd.Parameters.AddWithValue(qty, quantity); cmd.Parameters.AddWithValue(pid, productId); cmd.ExecuteNonQuery(); } tran.Commit(); // 两步都成功才提交 return true; } catch (Exception ex) { tran.Rollback(); // 任何一步失败就回滚 // 实际项目中这里应该记日志 throw new Exception(入库失败 ex.Message); } } } }参数说明productId是商品主键quantity是入库数量正整数operatorName是操作人remark是备注。事务的Commit和Rollback是这段代码的灵魂——要么两步都成功要么都不生效。库存系统里这种“写流水 改余额”的组合操作全都得这么处理。3.3 出库操作先校验库存再扣减出库比入库多一层校验库存不够不能出。而且校验和扣减之间不能有间隙否则并发情况下会出现超卖。常见做法是在事务里用UPDATE ... WHERE StockQty qty这种带条件的更新通过受影响行数判断是否成功public bool StockOut(int productId, int quantity, string operatorName, string remark) { using (var conn new SqlConnection(ConnStr)) { conn.Open(); using (var tran conn.BeginTransaction()) { try { // 带条件的库存扣减只有库存足够时才会更新成功 string sqlUpdate UPDATE Product SET StockQty StockQty - qty WHERE ProductId pid AND StockQty qty; int affected; using (var cmd new SqlCommand(sqlUpdate, conn, tran)) { cmd.Parameters.AddWithValue(qty, quantity); cmd.Parameters.AddWithValue(pid, productId); affected cmd.ExecuteNonQuery(); } // 受影响行数为 0说明库存不足直接回滚 if (affected 0) { tran.Rollback(); return false; } // 库存扣减成功后再写流水 string sqlOut INSERT INTO StockOut(ProductId, Quantity, Operator, Remark) VALUES(pid, qty, op, remark); using (var cmd new SqlCommand(sqlOut, conn, tran)) { cmd.Parameters.AddWithValue(pid, productId); cmd.Parameters.AddWithValue(qty, quantity); cmd.Parameters.AddWithValue(op, operatorName); cmd.Parameters.AddWithValue(remark, remark ?? ); cmd.ExecuteNonQuery(); } tran.Commit(); return true; } catch (Exception ex) { tran.Rollback(); throw new Exception(出库失败 ex.Message); } } } }这里把库存扣减放在前面、流水插入放在后面是因为扣减是可能失败的库存不足先做可能失败的步骤失败就直接回滚不用白写一条流水。WHERE StockQty qty这个条件同时起到了校验和防并发的作用——数据库层面保证不会扣成负数。3.4 库存查询与预警查询模块相对简单主要是条件拼接。预警则是在查询结果上做一层过滤// 查询库存低于下限的商品用于预警提示 public DataTable GetWarningProducts() { string sql SELECT ProductCode, ProductName, StockQty, MinStock FROM Product WHERE StockQty MinStock; return DbHelper.ExecuteQuery(sql); }在 WinForms 里查询结果直接绑到DataGridView上就行。预警可以在主窗体加载时调一次把结果展示在一个专门的提示区域或者用MessageBox弹出来。我一般倾向于在界面上放一个状态栏显示预警数量点进去看详情比弹窗打扰小。4. 跑起来环境准备、建库建表和首次运行4.1 环境准备清单在动手之前先把环境确认一遍Visual Studio2019 或 2022 社区版即可安装时勾选“.NET 桌面开发”工作负载。.NET Framework项目如果是老版本可能是 4.7.2 或 4.8如果是新写的可能是 .NET 6/8 的 WinForms。看项目文件里的TargetFramework确认。SQL ServerExpress 版就够用安装时记住实例名默认实例是.或(local)命名实例类似.\SQLEXPRESS。SSMSSQL Server Management Studio用来建库建表和查数据比在代码里调试方便得多。4.2 建库建表打开 SSMS连上本地实例新建一个数据库叫StockDB然后执行第 2 章里那三段建表 SQL。如果想省事也可以把建表语句存成一个.sql文件在 SSMS 里打开一次性执行。建完表之后往Product表里插几条测试数据INSERT INTO Product(ProductCode, ProductName, Category, Unit, StockQty, MinStock) VALUES (P001, A4 打印纸, 办公用品, 包, 100, 20), (P002, 签字笔, 办公用品, 盒, 50, 10), (P003, 文件夹, 办公用品, 个, 8, 15);注意第三条的StockQty是 8MinStock是 15库存低于下限正好用来测试预警功能。4.3 修改连接字符串并运行项目里数据库连接字符串通常写在App.config或代码里的常量中。找到它改成你自己环境的实例名connectionStrings add nameStockConn connectionStringServer.\SQLEXPRESS;DatabaseStockDB;Integrated SecurityTrue; providerNameSystem.Data.SqlClient/ /connectionStrings如果用的是 SQL Server 身份验证而不是 Windows 身份验证把Integrated SecurityTrue换成User Id你的用户名;Password你的密码;。改完之后在 Visual Studio 里按 F5 运行主窗体应该能正常打开商品列表里能看到刚才插的三条数据。注意如果运行时报“无法打开登录所请求的数据库 StockDB”八成是连接字符串里的数据库名或实例名写错了回到 SSMS 确认一下。4.4 走一遍完整业务流程跑起来之后建议按这个顺序验证一遍在商品管理里新增一个商品确认能保存并出现在列表里。对这个商品做一次入库数量填 10然后去数据库查StockIn表和Product.StockQty确认流水和库存都对。做一次出库数量填 3同样确认两边数据一致。试着出库一个超过库存的数量确认系统拒绝并提示库存不足。把某个商品的库存改到低于下限重新打开主窗体看预警有没有触发。这五步走完核心链路就算通了。哪一步不对问题基本就锁定在对应的模块里。5. 避坑与排查库存系统最容易翻车的几个地方5.1 库存扣成负数现象出库之后StockQty变成负数或者两个操作员同时出库同一商品库存扣多了。原因校验库存和扣减库存分成了两步中间有时间窗口或者扣减 SQL 没带StockQty qty条件。解决把校验和扣减合并成一条带条件的 UPDATE用受影响行数判断是否成功就像 3.3 里那样。整个操作放在事务里不要先 SELECT 再 UPDATE。5.2 流水和库存对不上现象StockIn表里有一笔记录但Product.StockQty没变或者反过来。原因写流水和更新库存没放在同一个事务里其中一步失败后另一部已经提交了。解决所有涉及多表写入的操作一律用BeginTransaction包起来成功一起提交失败一起回滚。这是血泪经验别偷懒。5.3 连接字符串写死在代码里现象换一台机器部署就要重新编译或者把项目发给别人跑不起来。原因连接字符串直接写在.cs文件里没有抽到配置文件。解决放到App.config的connectionStrings节点里代码里用ConfigurationManager.ConnectionStrings[StockConn].ConnectionString读取。部署时只改配置文件不用动代码。5.4 DataGridView 绑定后数据不刷新现象入库成功了但列表里的库存数量还是旧的。原因DataGridView绑定的DataTable是查询时的快照数据库变了它不会自动更新。解决操作成功后重新执行一次查询把新的DataTable重新绑上去。简单粗暴但有效。如果数据量大可以考虑只更新受影响的那一行。5.5 中文乱码现象商品名称存进去变成问号或者乱码。原因数据库字段用了VARCHAR而不是NVARCHAR或者连接字符串没指定字符集。解决所有存中文的字段一律用NVARCHAR参数化查询时SqlParameter会自动处理编码。建表时别图省事用VARCHAR。6. 二次开发从能跑到好用几个改造方向项目跑通之后接下来就是按自己的需求改。我一般会从这几个方向入手按优先级排第一加登录和权限。内部工具不可能谁都能改库存。加一张User表存用户名、密码哈希、角色登录后根据角色控制哪些按钮可用。密码别存明文用SHA256或者BCrypt哈希一下。这个改造涉及面广但价值最高建议优先做。第二把数据访问层换成 Dapper。现在手写SqlCommand和SqlParameter的代码重复度很高换成 Dapper 之后查询可以写成conn.QueryProduct(SELECT * FROM Product).ToList()插入更新也能省掉大量样板代码。事务支持也没问题conn.BeginTransaction()照样用。改造时注意一点Dapper 的参数化查询默认就是安全的但 SQL 字符串本身还是要用参数占位符别拼字符串。第三加操作日志。谁在什么时候改了哪个商品的库存这个在出问题的时候是后悔药。可以加一张OperationLog表记录操作人、操作类型、目标商品、变更前后数量、时间。在业务方法里顺手写一笔就行成本很低。第四库存预警做成后台定时检查。现在是打开窗体才检查如果系统一直开着库存降到下限了也不知道。可以加一个Timer控件每隔几分钟查一次预警商品有新的就弹提示或者改变状态栏颜色。第五导出 Excel。仓库那边经常要把库存表导出来发给别人。用NPOI或者ClosedXML这类库几行代码就能把DataTable写成.xlsx文件。注意导出的时候把列宽和表头格式化一下不然发出去不好看。改造的时候有个习惯我一直保持每改一个模块先把原来的业务流程完整走一遍确认没改坏再继续。库存系统的数据是有连带关系的动了入库逻辑可能影响到库存查询和预警牵一发动全身。从那以后我每次动核心业务代码都强制走一遍 4.4 里那五步验证流程确认流水、库存、预警三边都对得上才敢提交。希望这些能帮到你少走点弯路。本文还有配套的精品资源点击获取

相关新闻

前端RSA加密实战:分段加密解决长文本与中文乱码问题

前端RSA加密实战:分段加密解决长文本与中文乱码问题

1. 前端加密到底在解决什么问题前端做加密这件事,很多刚接触的人第一反应是“前端代码都是明文的,加密有什么意义”。这个疑问很合理,但忽略了一个关键场景:数据在网络上传输的过程中,经过的每一层节点都可能被截获。前…

2026/10/17 6:56:01 阅读更多 →
知识蒸馏、RAG与微调:大模型应用落地的三种核心技术对比

知识蒸馏、RAG与微调:大模型应用落地的三种核心技术对比

很多人第一次接触大模型的应用开发时,都会被这几个术语绕晕:知识蒸馏、RAG检索增强、微调(Fine-tuning)。乍一看都是“让模型变聪明”的手段,真到选型的时候才发现,它们解决问题的层次完全不同——有的改模…

2026/10/17 6:56:01 阅读更多 →
AI智能名片小程序源码二次开发与上线避坑指南

AI智能名片小程序源码二次开发与上线避坑指南

简介:这份小程序源码包以AI智能名片为核心场景,面向具备一定前端与后端基础、希望研究名片类小程序完整实现思路的开发者与学习者。包内共406个文件,以wxss样式、wxml结构、js逻辑与json配置构成小程序主体,另有php接口文件、html…

2026/10/17 6:56:01 阅读更多 →

最新新闻

【共创稿事节】HarmonyOS 7 Agent 开发实战 09:Agent 测试评测集

【共创稿事节】HarmonyOS 7 Agent 开发实战 09:Agent 测试评测集

做 Agent 应用最怕的不是「写不出第一版」,而是「改了第三版之后,发现第一版明明答对的题现在答错了」。大模型有随机性、提示词有耦合、工具调用有边界,靠人肉聊天抽查既覆盖不全又无法回放。这一篇我们给 Agent 配上一套离线评测集&#xf…

2026/10/17 7:41:11 阅读更多 →
智能体密钥管理实战:Hermes与Agent Vault凭据注入与安全审计

智能体密钥管理实战:Hermes与Agent Vault凭据注入与安全审计

1. 为什么智能体需要一个“管钥匙的保安”做过 Agent 项目的人大概都有过这种体验:功能跑通了,Demo 演示也很顺利,但一旦要往生产环境推,心里就开始发虚。原因往往不是模型不够聪明,也不是编排逻辑有 bug,而…

2026/10/17 7:41:11 阅读更多 →
Flink Operator State 深度解析:从原理到批量 Sink 实战

Flink Operator State 深度解析:从原理到批量 Sink 实战

1. 为什么 Operator State 值得单独拎出来讲Flink 的状态体系里,Keyed State 出镜率极高,几乎每篇讲状态的资料都会先拿 keyBy 之后的 ValueState、ListState 举例。但真正落到生产环境,有一类状态是绕不开的:它不依赖 key&#x…

2026/10/17 7:41:11 阅读更多 →
Flink Operator State 深度解析:非键控状态管理实战指南

Flink Operator State 深度解析:非键控状态管理实战指南

1. 为什么 Operator State 值得单独拎出来讲Flink 的状态管理一直是流计算里最容易被低估的一块。大部分人刚上手的时候,注意力都放在窗口、水位线、Checkpoint 这些"显眼"的机制上,等到真正在生产环境里跑起来,才发现状态才是决定…

2026/10/17 7:41:11 阅读更多 →
RPA+大模型:打造外部群聊专家级自动应答系统

RPA+大模型:打造外部群聊专家级自动应答系统

1. 从一线需求说起:为什么群聊回应也能自动到“专家级”做运营和客户成功的朋友,大概率都经历过这种状态:手机里挂着四五个外部群,每个群都在问问题,有的问报价,有的问故障排查,有的纯粹是闲聊。…

2026/10/17 7:41:11 阅读更多 →
地质工程一体化实战:从地质建模到随钻导向与压裂设计的闭环

地质工程一体化实战:从地质建模到随钻导向与压裂设计的闭环

你要是问一个油气田开发工程师,最怕听到哪句话,十有八九是——“模型是这么说的,但井不是这么钻的。”这种地质和工程互相不认账的场面,在非常规油气、复杂油气藏开发里几乎每隔几天就来一次。模型画得再漂亮,现场不买…

2026/10/17 7:40:11 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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 阅读更多 →