尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
C#停车场收费系统WinForm实战:从数据模型到计费规则
简介这是一份C#停车场收费系统的Winform桌面应用源码包面向正在学习C#窗口编程、SQL Server数据库操作以及真实业务逻辑组织的开发者。系统覆盖车辆入场登记、出库计费、停车收费规则、收费记录查询与管理模块内置按时、按日、按次等多种收费算法支持灵活调整收费标准并记录车辆入场与出场时间自动计算费用。压缩包共95个文件大小仅1.32MB主体为37个C#源文件同时包含窗体资源文件、SQL附加脚本、数据库数据文件及可直接运行的程序目录结构清晰便于快速运行和对照阅读。其中数据库包含车辆信息表、停车记录表、收费记录表等能完整体现典型管理系统的数据模型。目前已有1323人学习下载。研读源码可以掌握Winform事件驱动开发、数据库连接与增删改查的基本模式理解停车场计费场景中时间差计算、费用结算和权限管理的实现方法从界面设计到数据持久化提供完整参考也能帮助初学者熟悉面向对象编程和分层设计思路有效缩短上手周期。1. C#停车场收费系统(winform项目)不是简单 CRUD先想清楚计费模型再动手C#停车场收费系统(winform项目)是很多 .NET 开发者会遇到的第一个完整业务项目有界面、有数据库、有计费规则还要面对道闸、车牌识别相机和收银员手误。只看表面它无非是“入场写一条、出场算个钱”但做出来和能上线是两个完全不同的量级。这篇记录以一套单机版 WinForm 停车场收费系统为主线从表结构、计费规则、界面刷新到收费计算、打包部署逐步说清楚怎么做中途会标注哪些参数容易被人忽略、哪些场景必须测试覆盖。适合正在做毕业设计、给物业开发内部工具或者接手老项目做维护的开发者。读完你可以照着搭一套能用的系统也能提前避开那些上线就翻车的坑。2. 先把数据模型和计费状态拆清楚三张表加一个“未出场”字段2.1 进出场表为什么不能只存“入场时间”和“出场时间”很多初学者会把所有信息塞进一张“车辆进出表”入场时间、出场时间、金额、支付方式全放一起听起来没问题做上两个月就会发现临时车、月卡、内部车、免费车混在一起报表和对账根本拆不开。我一般会把核心数据分成三块车辆进出记录、收费规则、支付流水。进出场记录表里不要单独放一个“状态”字段来表示在库或已出场直接用ExitTime为空表达“还在场内”反而更不容易出现状态不一致。下面是一份 SQLite 建表脚本字段名按便于理解的来。CREATE TABLE ParkingRecord ( Id INTEGER PRIMARY KEY AUTOINCREMENT, PlateNumber TEXT NOT NULL, CardNo TEXT, VehicleType INTEGER NOT NULL DEFAULT 0, ChargeRuleId INTEGER NOT NULL DEFAULT 1, EntryTime TEXT NOT NULL, ExitTime TEXT, EntryOperator TEXT, ExitOperator TEXT, PaidFlag INTEGER NOT NULL DEFAULT 0, Amount DECIMAL(10,2) NOT NULL DEFAULT 0 ); CREATE INDEX idx_parking_plate_exit ON ParkingRecord(PlateNumber, ExitTime); CREATE INDEX idx_parking_entrytime ON ParkingRecord(EntryTime);逻辑上看ExitTime IS NULL就是“这辆车在库里”查询时不需要再维护一个容易写错的Status字段。VehicleType我建议用整数码0 临时车、1 内部车、2 免费车、10 月卡只在界面上做文字映射不要让数据库里到处飘着“临时”“免费”这样的中文字段。参数上要注意ChargeRuleId非常重要。收费规则单独建表车辆记录只引用规则 ID。将来某一类车的价格变了只改规则表不用回改历史数据。两个索引也值得保留PlateNumber ExitTime联合索引用于“找某车牌当前在场记录”EntryTime索引用于出场列表和报表统计。2.2 收费规则表免费时长、首小时单价、封顶金额怎么落库收费规则看起来只是“每小时多少钱”实际上每个停车场都会追问首小时多少钱、超过一小时按什么单位计费、免费时长有多久、单日封顶多少、跨天怎么算。这些问题如果全写死在代码里下一次调价就得重新发版。我常用的规则表是这样CREATE TABLE ChargeRule ( RuleId INTEGER PRIMARY KEY, RuleName TEXT NOT NULL, FreeMinutes INTEGER NOT NULL DEFAULT 0, FirstMinutes INTEGER NOT NULL DEFAULT 60, FirstFee DECIMAL(10,2) NOT NULL DEFAULT 0, UnitMinutes INTEGER NOT NULL DEFAULT 60, UnitFee DECIMAL(10,2) NOT NULL DEFAULT 0, DailyCap DECIMAL(10,2) NOT NULL DEFAULT 0 );FreeMinutes表示入场后多少分钟内免费FirstMinutes和FirstFee组合表达“首小时 5 元”UnitMinutes和UnitFee表达“超过首小时后每 60 分钟 2 元”。DailyCap是每日封顶0 表示不封顶。这个表还可以继续加字段比如EffectiveDate、IsHoliday但单机版收费系统先保证上面七个字段够用别一开始就把规则表设计成通用计费引擎。有了规则表内部车和免费车就不要再靠“这辆车的车牌在不在白名单”来判断。免费车也是一个ChargeRuleId不过它的FreeMinutes可能设成 1440 分钟或者UnitFee设为 0。这样报表里可以统一统计“免费车有多少次”而不是靠一堆散落的 if 判断。2.3 选 SQLite 还是 SQL Server先本地跑通再连中心库停车场收费系统最常见的选择有三个SQLite、SQL Server Express、Access。我一般建议新项目从 SQLite 起步因为部署最简单单文件挪到哪都能跑等出现多岗亭、需要集中汇总时再考虑换 SQL Server Express。选型适合场景需要注意的点SQLite单个岗亭、离线优先、几十万条记录多进程并发写会锁库要开 WAL 模式收费端尽量避免多线程写同一张表SQL Server Express多岗亭共享、对账和报表实时要装服务、配置端口和防火墙Express 有单库容量限制Access老项目迁移历史代码不好动并发弱日期格式容易踩坑新项目不建议选实际上很多物业项目最终跑在普通办公电脑上没有专职 IT。SQLite 这种“数据库就是一个文件”的方式反而最好排障。如果后续要做历史流水归档批量导入数据时可以用 SqlBulkCopy但注意目标表字段有变动时列名映射会报错最好先读取目标表 Schema 再动态生成映射。提示如果收费电脑掉电或程序被强杀SQLite 的 WAL 和事务能保住已提交数据但前提是每个收费操作都用了事务不能一条 UPDATE 丢在外面裸奔。3. 用 WinForm 搭收费界面从主窗体布局到防卡死的刷新方式3.1 主窗体分区车辆列表、收费操作、通道状态各自独立WinForm 收费界面最容易犯的错误是把所有控件堆在一个窗体里。入场、出场、查询、报表、设置全放一屏现场操作时误点率非常高。我一般用SplitContainer把主窗体分成左右两区左边放当天车辆列表右边放收费操作面板。左侧 DataGridView 展示“当前在场车辆”关键列有车牌号、入场时间、车辆类型、是否已支付。右侧操作区从上到下是车牌输入框、查询按钮、收费金额、支付方式、确认出场按钮。不要把所有按钮塞进 DataGridView 的单元格里收费员每天要面对几百辆车键盘回车和 Tab 键比鼠标快得多界面上一定要保证 Tab 顺序合理。通道状态可以放在窗体底部状态栏比如“入口道闸在线”“出口相机在线”“数据库连接正常”。如果这些状态标识也用 Timer 轮询去刷新注意不要在 Timer 里直接做耗时查询否则 UI 线程会被拖死。状态栏内容用ToolStripStatusLabel更新和业务按钮区分开。3.2 用 BindingList 加 BackgroundWorker 刷新车辆列表别直接操作 DataGridViewWinForm 的 UI 线程只有一个收费员连续出入场时如果还同步去做数据库查询和车牌识别回调界面就会卡住点哪个按钮都没反应。C# 里有几种做法BackgroundWorker、Task.Run、async/await老项目里 BackgroundWorker 仍然很常见尤其 VS2015 的 .NET Framework 4.6.1 工程。下面这段代码是在加载车辆列表时用 BackgroundWorker 把查询放到后台线程状态栏同时给出提示var bw new BackgroundWorker(); bw.WorkerReportsProgress true; bw.DoWork (s, e) { var rows new ParkingRepository().GetParkingRows(DateTime.Today.AddHours(-6), DateTime.Now); bw.ReportProgress(50); var view new BindingListParkingRecordView(rows); e.Result view; }; bw.ProgressChanged (s, e) { toolStripStatusLabel1.Text 正在加载车辆列表...; }; bw.RunWorkerCompleted (s, e) { if (e.Error ! null) { toolStripStatusLabel1.Text 加载失败请查看日志; return; } dataGridView1.DataSource e.Result as BindingListParkingRecordView; toolStripStatusLabel1.Text 就绪; }; bw.RunWorkerAsync();逻辑上要注意DoWork里跑的代码在线程池线程上绝对不能直接碰dataGridView1或toolStripStatusLabel1这类控件控件只能由 UI 线程更新。ReportProgress和RunWorkerCompleted事件会回到 UI 线程所以状态栏和 DataGridView 的赋值都放在这两个事件里。参数上WorkerReportsProgress true才能使用ReportProgress如果只是加载列表不更新进度条这个开关可以不打开。用BindingListT绑定 DataGridView 的好处是后续有车辆入场或出场可以从后台刷新列表时只更新某些行不需要每次dataGridView1.DataSource null再重新赋一遍否则焦点和选中行会被重置。3.3 界面美化与 DPI 适配哪些钱值得花WinForm 界面美化是个很有意思的话题但收费系统不是用来展示设计能力的。我见过把窗体背景做成大图、按钮全是渐变色的收费软件结果在低分辨率老电脑上字都看不清。真正值得花时间的是三件事字体大小、行高、DPI。收费岗亭常常阳光直射屏幕对比度差字号小于 14 就很容易看错。DataGridView 里我一般会做下面这些设置dataGridView1.EnableHeadersVisualStyles false; dataGridView1.ColumnHeadersDefaultCellStyle.BackColor Color.FromArgb(45, 62, 80); dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor Color.White; dataGridView1.RowTemplate.Height 34; dataGridView1.AutoSizeColumnsMode DataGridViewAutoSizeColumnsMode.Fill; dataGridView1.SelectionMode DataGridViewSelectionMode.FullRowSelect;这里EnableHeadersVisualStyles false是让列头颜色生效的关键否则系统会按当前主题覆盖你的设置。RowTemplate.Height 34保证手指粗也不容易点错行。FullRowSelect让用户点任何一列都能选中整行配合双击填充车牌号非常顺手。如果现场显示器是竖屏建议窗体的AutoScaleMode设为Dpi并在主要控件上用TableLayoutPanel布局避免不同缩放比例下按钮错位。我一般不会为了外观引入第三方皮肤库收费系统重点在“看得清、点得快、不容易误操作”。4. 收费计算的核心逻辑把分钟差换算成金额的三个边界分支4.1 首小时计费和免费时长先扣免费分钟再算单位小时收费计算是所有业务逻辑里最不能靠“感觉”写的地方。第一次做时我以为就是“总分钟数 / 60 * 每小时单价”后来发现首小时、免费、封顶三个规则叠在一起时直接算总时长一定会出错。先看单日、单次的最基础算法入场时间到出场时间先减掉免费分钟然后再判断是否在首小时范围内。这里有一个关键点免费分钟必须从总时长里先扣掉而不是先算出总金额再减免费金额因为收费规则通常只免时间不免金额。private static decimal CalcSingleDay(DateTime entry, DateTime exit, ChargeRule rule) { if (exit entry) throw new ArgumentException(出场时间必须晚于入场时间); decimal minutes (decimal)(exit - entry).TotalMinutes; if (minutes rule.FreeMinutes) return 0m; decimal billable minutes - rule.FreeMinutes; decimal fee; if (billable rule.FirstMinutes) { fee rule.FirstFee; } else { decimal extra billable - rule.FirstMinutes; decimal unitCount Math.Ceiling(extra / rule.UnitMinutes); fee rule.FirstFee unitCount * rule.UnitFee; } if (rule.DailyCap 0 fee rule.DailyCap) fee rule.DailyCap; return fee; }这段逻辑里billable是真正要收费的分钟数比如停车 70 分钟、免费 20 分钟billable就是 50 分钟。如果首小时收费 5 元50 分钟小于FirstMinutes60直接收首小时费。参数上最容易改错的是Math.Ceiling。这里用的是“不足一小时按一小时”的常见规则所以extra / UnitMinutes向上取整。如果你们停车场按 15 分钟计费只要把UnitMinutes改成 15代码结构不用动。要格外小心浮点误差钱一律用decimal不要用double否则会出现 0.3000000000004 这种没法入账的金额。4.2 跨天与每日封顶按自然日分段计算不直接乘总时长停车跨天时很多规则是“每天封顶 X 元”这个封顶按自然日计算。比如第一晚停了 22 小时某停车场每日封顶 30 元那首日最多收 30 元第二天再停 2 小时按当天规则重新算。如果直接把总时长算成 24 小时再乘单价封顶就会失效。正确做法是把出场时间按自然日拆成多段每天单独用首小时、单价、封顶算一遍最后再把每一天的费用累加。public decimal Calculate(DateTime entry, DateTime exit, ChargeRule rule) { if (exit entry) throw new ArgumentException(出场时间必须晚于入场时间); decimal totalFee 0m; var dayStart entry.Date; var dayEnd dayStart.AddDays(1); bool firstDay true; while (dayStart exit) { var segStart firstDay ? entry : dayStart; var segEnd exit dayEnd ? exit : dayEnd; decimal segMinutes (decimal)(segEnd - segStart).TotalMinutes; if (firstDay) { if (segMinutes rule.FreeMinutes) return 0m; segMinutes - rule.FreeMinutes; } decimal segFee CalcSingleDay(segStart, segStart.AddMinutes((double)segMinutes), rule); if (rule.DailyCap 0 segFee rule.DailyCap) segFee rule.DailyCap; totalFee segFee; dayStart dayEnd; dayEnd dayStart.AddDays(1); firstDay false; } return totalFee; }这里segStart是每段的开始时间segEnd是这一段和出场时间的较小值。第一天要把免费分钟从第一段里扣掉后面每一天不再扣。每天单独DailyCap截断最后累加才符合“每日封顶”的业务直觉。这段代码有个前提免费时长只享受一次而且是从入场开始算。如果你们的规则是“每天都有免费时长”那要把segMinutes - rule.FreeMinutes从if (firstDay)里挪出来改成每一天都扣。不要在代码里猜规则上线前拿纸面规则逐条确认。4.3 金额精度与收费单生成用 decimal 和数据库事务收口金额计算只要涉及优惠、零头、取整就一定要在数据库事务里和出场动作一起完成。否则会出现数据库里车辆已经显示出场但没有生成收费单或者收费单生成了但车辆还挂在库里。我一般的流程是出场时先读取车辆记录和收费规则算出金额然后在一个事务里同时更新ParkingRecord.ExitTime和插入PaymentRecord。更新语句必须带ExitTime IS NULL这是防止重复收费的最后一道防线。using (var conn new SQLiteConnection(_connStr)) { conn.Open(); using (var tx conn.BeginTransaction()) { var update conn.CreateCommand(); update.Transaction tx; update.CommandText UPDATE ParkingRecord SET ExitTime exit, ExitOperator op, PaidFlag 1, Amount amount WHERE Id recordId AND ExitTime IS NULL; update.Parameters.AddWithValue(recordId, recordId); update.Parameters.AddWithValue(exit, exitTime); update.Parameters.AddWithValue(op, operatorId); update.Parameters.AddWithValue(amount, amount); if (update.ExecuteNonQuery() ! 1) { tx.Rollback(); return false; } var insert conn.CreateCommand(); insert.Transaction tx; insert.CommandText INSERT INTO PaymentRecord(RecordId, BillNo, Amount, PayType, PayTime, OperatorId) VALUES(recordId, billNo, amount, payType, payTime, operatorId); insert.Parameters.AddWithValue(recordId, recordId); insert.Parameters.AddWithValue(billNo, GenerateBillNo()); insert.Parameters.AddWithValue(amount, amount); insert.Parameters.AddWithValue(payType, payType); insert.Parameters.AddWithValue(payTime, DateTime.Now); insert.Parameters.AddWithValue(operatorId, operatorId); insert.ExecuteNonQuery(); tx.Commit(); return true; } }这段代码的关键点在ExecuteNonQuery() ! 1。如果这一行早就被处理成已出场事务会回滚不会产生第二笔收费单。BillNo最好用“日期 收费端编号 流水号”组合比如2025061114200001方便和对账单互查。支付方式payType建议统一用整型码0 现金、1 微信、2 支付宝、3 银联。不要同时存“微信”和“WeChat”两种叫法报表统计会痛苦很久。5. 停车场收费系统避坑指南5 个容易上线就翻车的坑5.1 出场时找不到入场记录问题不一定在数据库现象车辆明明在库里出场刷车牌却提示“未找到入场记录”手工去数据库查又能查到。原因最常见的是查询条件漏了ExitTime IS NULL。如果你按车牌倒序取最新一条取到的很可能是这辆车上次出场的历史记录。另一个常见原因是车牌识别把 O 和 0、I 和 1 混在一起存储时是字母后来查询是数字或者相反。解决查询当前在场车辆时条件一定是车牌匹配并且ExitTime IS NULL再按EntryTime DESC取一条。车牌号存入前统一做一次归一化转大写、去空格具体字符替换规则根据你用的相机品牌调。var cmd conn.CreateCommand(); cmd.CommandText SELECT Id, PlateNumber, EntryTime, VehicleType, ChargeRuleId FROM ParkingRecord WHERE PlateNumber plate AND ExitTime IS NULL ORDER BY EntryTime DESC LIMIT 1; cmd.Parameters.AddWithValue(plate, NormalizePlate(textBoxPlate.Text));车牌归一化函数可以先把车牌号.ToUpper()再去掉中间空格然后按现场识别错误做少量替换。不要做太激进的“0 全部换成 O”省字也会换错。5.2 重复收费按两下按钮生成两笔单现象收费员鼠标连点两下或者刚按完回车又点鼠标同一辆车生成了两笔收费流水金额翻倍。原因前端一般会把收费按钮在点击后禁用但回车触发、快捷键触发往往没禁掉。更核心的问题是后端没有幂等保护第二次执行时不知道这辆车已经出场了。解决收费按钮点击后立即禁用收费完成再恢复真正的兜底放在UPDATE ParkingRecord ... WHERE Id recordId AND ExitTime IS NULL。只要影响行数为 0就说明已经处理过直接提示“该车已收费请勿重复操作”。我见过很多系统只在界面上做禁用换一个操作员登录后照样能重复点后端事务必须守住。5.3 内部车和免费车混在一起别在白名单里写死车牌现象内部车辆出场也被正常收费免费车换了司机就收费。原因早期版本用if (plate 辽B12345)这种硬编码方式判断免费车车牌一旦录错或者临时换车规则完全不生效。解决车辆进入时用VehicleType标记类型出场计费时根据ChargeRuleId找对应规则。内部车、免费车也走同一套计算入口只是规则表的UnitFee为 0或者FreeMinutes特别大。这样收费逻辑不必每加一个免费车牌就改代码报表里也能按类型统计免费次数。5.4 现金和扫码对账不平支付流水要有独立表现象交班时现金多 50 元扫码少 50 元两边怎么也对不上。原因很多简单实现是“点一下收费按钮就标记已支付”现金没入账、扫码没到账都算成功。尤其扫码支付如果没有等回调或主动查单就会造成系统收费成功但钱没进来的假象。解决每一笔支付写进独立PaymentRecord表记录支付方式、支付时间、金额、操作员。现金收费时界面要分出“应收金额”和“实收金额”找零单独显示。扫码支付需要在本地标记“待确认”等支付接口回调成功或者收费端主动查单状态后再放行。对账时按支付方式分组求和和每班次现金交款单比。5.5 系统时间被改导致计费异常需要一个时钟校验位现象管理员把系统时间从 14:00 调回 12:00过半小时后出场收费金额变成负数或者直接被 0 元放行。原因单机收费系统依赖本机时间DateTime相减出现负数时如果没有异常拦截某些实现会返回 0 元。解决在本地建一张SystemCheck表记录最后交班时间或最后一次收费时间。程序启动时检查当前时间如果发现比记录时间还要早比如相差超过 5 分钟就直接禁止收费并提示人工处理。收费计算里也加一道守卫exit entry时抛异常不允许生成 0 元单。不要相信操作系统时间一定准收费电脑经常被乱调。6. 把项目交付出去InstallShield 打包、外置配置与 48 小时验证6.1 用 VS2015 的 InstallShield 打包 WinForm 程序收费系统不是开发完就结束现场部署是很重要的一环。VS2015 里做 WinForm 打包常见做法是装好 InstallShield Limited Edition 后在解决方案里右键新增项目选Other Project Types - Visual Studio Installer - InstallShield Limited Edition Project。项目生成后在 Project Assistant 里配置产品名、版本号、公司名并把主输出文件和配置文件加入安装目录。需要特别检查的是 Prerequisites目标收费电脑如果没装 .NET Framework要在安装包里勾上对应版本。这样现场运维拿到的是一个 Setup.exe双击就能装而不是要求人家手工装运行库。安装包做好之后自己一定要在干净虚拟机里跑一遍安装和卸载不要只在开发机双击。开发机装过 .NET 和一堆依赖掩盖不了真实现场缺库、缺权限的问题。6.2 配置外置把数据库连接串和计费参数留给现场运维我不会把数据库路径直接写死在代码里也不会让运维去改编译后的 exe。配置放在安装目录下的文本文件里最好用configSource拆出去这样覆盖安装时不会弄丢现场的数据库路径。configuration connectionStrings configSourceconnectionStrings.config / appSettings configSourceappSettings.config / /configurationconnectionStrings.config里放实际的连接串比如Data SourceC:\Parking\parking.db。appSettings.config里放收费端编号、日志开关、单日封顶开关这类参数。现场改配置时只需重启程序不需要重新编译和重新打包。日志也要写到本地文件按日期命名比如logs\2025-06-11.log。收费系统最容易出问题的就是数据库连接失败日志至少要记录谁操作了哪辆车、收费金额、异常堆栈、支付回调结果。没有日志线上出问题就只能靠猜。6.3 上线前我跑一遍的验证清单最后我会做一轮 48 小时连续压测不是只点两下功能就收工。下面这张表是我每次都会跑的项验证项通过标准连续 48 小时挂机界面不卡死内存占用不持续上涨连点收费按钮 50 次只生成一笔收费单23:59 入场、次日 00:10 出场跨天分段金额与手工账单一致拔掉数据库文件再恢复程序报错后能恢复不丢在场车辆记录修改系统时间后重启收费端拒绝计费提示人工处理跨天和重复点击这两个测试基本能拦下八成上线事故。我的习惯是每改一次计费规则先按真实时间格做一组手工账单让系统逐条对对不上就不允许现场更新。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

C# WinForm连接MySQL实战:从解压到运行图书管理系统

C# WinForm连接MySQL实战:从解压到运行图书管理系统

简介:这是一套面向计算机相关专业在校学生与初学者的C# WinForm图书管理系统课程设计实践资源,适用于期末大作业、课程设计及毕设初期原型开发。系统基于.NET Framework与MySQL 8.0.21构建,完整实现用户登录、图书入库与维护、借阅/续借/还书…

📅 2026/10/8 5:19:48
从策略梯度到PPO:核心机制、代码实现与调参实战

从策略梯度到PPO:核心机制、代码实现与调参实战

强化学习这条路上,PPO(Proximal Policy Optimization,近端策略优化)几乎是绕不开的一座山。不管你是做游戏AI、机器人控制、推荐系统,还是最近火起来的大模型对齐训练,PPO都稳稳地坐在核心算法的位置上。但…

📅 2026/10/8 5:19:48
PPO算法从公式到实战:拆解近端策略优化的裁剪机制与调参避坑指南

PPO算法从公式到实战:拆解近端策略优化的裁剪机制与调参避坑指南

强化学习这块我踩过的坑不算少,但真正让我从“调参玄学”里爬出来的,是认真把 PPO 的每一行损失函数拆开看了一遍。今天这篇不打算写成教科书,就按我自己从看懂公式到跑通训练、再到踩坑排查的顺序,把 PPO 这个算法从头到尾捋一遍…

📅 2026/10/8 5:19:48
MORE NEWS

更多资讯

📰

从囤积到加工:用Obsidian搭建个人知识库工作台的方法论

先别急着把一万篇文章塞进 Obsidian。我是认真做过“收藏控”的,浏览器书签几千条,微信浮窗永远两位数爆满,云笔记里堆满了“改天细读”的文章。结果真到写方案、做周报、复盘项目的时候,一条都用不上。后来我花了几个月时间&…

📰

DeepCFR算法优化与复现:从遗憾最小化到exploitability评估

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

📰

Android UI控件延迟显示:View.postDelayed() 方法使用及思考(TaoToken 统一 Key 通道实践)

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

📰

医院门诊挂号系统毕业设计:基于JSP+MySQL的完整实现与部署指南

简介:面向Java毕业设计者的医院门诊挂号系统全套开源毕业设计资源包,基于SSM与JSP技术构建,采用Mysql数据库,适合毕业设计、课程设计或项目实训使用。压缩包约15.34MB,内含完整Java源码、Mysql数据库脚本、开题报告、毕…

📰

国庆硬核充电总结:从传统 Go 并发模型到 Agentic 状态机的技术心智跃迁

国庆 7 天哪儿也没去。二线城市老城区的书房里,书桌一角放着放凉了的普洱茶,窗外是偶尔划过的汽笛声,屋里只有机械键盘清脆的敲击声。过去两个月,我们技术部所有业务线都在疯狂推进 AI 化改造,作为写了整整十年 Go 的老…

📰

Ponytail插件怎么用?修图特效与AI绘画提示词实战指南

后台连着收到好几条几乎是同一个模板的私信:“Ponytail 插件怎么用?”“求一个 ponytail 插件安装包”“为什么我装的 ponytail 不生效”。我一开始也以为,这又是某个新出的效率工具,毕竟最近带“Skill”“插件”后缀的东西实在太…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬