news 2026/10/1 13:27:04

C#火锅点菜系统实战:数据库设计、事务处理与厨打队列

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C#火锅点菜系统实战:数据库设计、事务处理与厨打队列

简介:这是基于C#开发的火锅点菜系统完整项目,面向餐饮管理方向的学习者、高校课程设计以及需要参考WinForms桌面应用架构的开发者。系统覆盖菜品展示、点菜购物车、订单生成、支付结算与小票打印等完整业务链路,源码中体现了MVC分层、事件驱动、异常处理以及ADO.NET数据库访问等典型实践。压缩包共71个文件、1.55MB,以20个.cs源文件和窗体资源为核心,另含可执行程序、动态库、SQL Server数据库文件、水晶报表及MSI安装工程,可直接运行并对照学习。目前已有141人浏览学习,适合通过源码研读掌握点餐系统的模块划分、数据表设计、打印输出与部署配置。资源中还包含安装项目、数据库日志和设计器文件,能帮助初学者理解从界面到数据库落地的完整开发流程,亦可作为课程答辩或简历项目的实用参考。

1. 弄懂这套 C# 火锅点菜系统:它解决了什么,适合谁拿去用

很多刚入门的 C# 开发者第一次接触实际项目,就是从一个名为 huoguo.rar 的老压缩包开始的——里面装着一套完整的 C# 火锅点菜程序:前台选菜、开台、结账、厨打小票一应俱全。这类工程大多出自早年的课设和私活,界面停留在 WinForm,数据库是 SQLite 或本机 SQL Server,但它的表结构和核心流程放到今天依然能打。火锅场景和普通快餐不一样:一桌多次加菜、多人同时下单、锅底蘸料分开计价,这套程序解决的正是这种高频改动下的订单一致性问题。适合三类人:正在做课设或毕设的 C# 初学者、想低成本给自家小店上线点菜系统的老板,以及接私活后需要快速出方案的开发者。看完这篇,你能把它的数据模型、下单流程、厨打队列和常见坑全部摸清,并直接照着改造成能上线的版本。

2. 数据模型先行:建表 SQL 与 C# 项目骨架怎么搭

拿到一个 C# 点菜系统老工程,第一步不是看界面,而是看数据库脚本。火锅店的点菜节奏和快餐完全不同:一桌客人可能在两小时内加菜五六次,每个人点的锅底、荤菜、素菜、酒水混在同一张单上,如果表设计不合理,加菜、退菜、结账都会变成灾难。这一章先把四张核心表拆清楚,再给出可以直接落地的建表 SQL,最后把 DAL 层的 DbHelper 封装讲明白。

2.1 火锅场景下为什么必须拆订单明细表

最常见的翻车设计,是在一张桌台表里用一个字段存“所点菜品”,比如把“毛肚2份、鸭血1份、锅底1个”用逗号拼成一个字符串塞进去。这种设计在点菜程序里看似简单,实际一加菜就要把整串字符串读出来重写,退菜更是难以处理,结账时想按分类统计还得做字符串解析。

火锅场景的正确做法是把订单拆成主表和明细表。主表(Order)记录桌号、开台时间、服务员、订单状态;明细表(OrderDetail)每一行只记录一个菜品,包含菜品 ID、数量、单价、小计。这样加菜就是在明细表里追加行,退菜就是修改明细行状态,结账就是对明细表做汇总。选型上,C# 点菜系统最常用的是 SQLite 和 SQL Server 两种:单店本地跑用 SQLite 零配置,多收银台联网用 SQL Server。老工程里两种都常见,建表脚本建议同时维护一份。

2.2 四张核心表的建表 SQL(SQLite 版与 SQL Server 版)

菜品、桌台、订单、订单明细,这四张表是点菜系统的地基。下面给出 SQLite 版本,SQL Server 版本只需要把自增主键写法从INTEGER PRIMARY KEY AUTOINCREMENT换成INT IDENTITY(1,1),把TEXT换成NVARCHAR(50)即可。

-- 菜品表 CREATE TABLE Dish ( DishId INTEGER PRIMARY KEY AUTOINCREMENT, DishName TEXT NOT NULL, Category TEXT NOT NULL, -- 分类:锅底/荤菜/素菜/酒水 Price DECIMAL(10,2) NOT NULL, -- 当前售价 IsOnSale INTEGER DEFAULT 1 -- 1=在售 0=停售 ); -- 桌台表 CREATE TABLE TableInfo ( TableId INTEGER PRIMARY KEY AUTOINCREMENT, TableName TEXT NOT NULL, SeatCount INTEGER DEFAULT 4, -- 座位数 Status INTEGER DEFAULT 0 -- 0=空闲 1=占用 2=已结账待清台 ); -- 订单主表 CREATE TABLE "Order" ( OrderId INTEGER PRIMARY KEY AUTOINCREMENT, TableId INTEGER NOT NULL, OpenTime DATETIME NOT NULL, CloseTime DATETIME, WaiterName TEXT, TotalAmount DECIMAL(10,2) DEFAULT 0, Status INTEGER DEFAULT 0 -- 0=进行中 1=已结账 2=已作废 ); -- 订单明细表 CREATE TABLE OrderDetail ( DetailId INTEGER PRIMARY KEY AUTOINCREMENT, OrderId INTEGER NOT NULL, DishId INTEGER NOT NULL, DishName TEXT NOT NULL, -- 冗余菜品名,防止菜品改名后历史单不可读 PriceSnapshot DECIMAL(10,2) NOT NULL, -- 下单时的价格快照 Quantity INTEGER NOT NULL, Status INTEGER DEFAULT 0 -- 0=正常 1=已退 );

参数说明:PriceSnapshot是这张表里最容易被人忽视却最关键的一列。菜品价格会调整,结账和报表统计必须用下单时的价格,而不是当前Dish.Price,否则会出现“改了菜单价格,昨天营业额全变了”的血泪事故。DishName冗余存储也是同一个道理,菜品改名后历史小票仍能显示原名称。

Order表名是 SQL 保留字,建表时必须加双引号,C# 里查询时也要写成SELECT * FROM "Order",这一点在 SQL Server 下同样需要注意。习惯上我建议把表名改成OrderMain或TbOrder来规避保留字,但如果改不了老库,就统一记住加引号这个约定。

2.3 项目骨架与 DbHelper 封装:连接串、命令超时和反射取值

拿到 huoguo.rar 解压后的 C# 点菜系统,项目结构通常是 WinForm 界面层、业务层和数据访问层三层。数据访问层最核心的类就是 DbHelper,所有数据库操作都从这里走。封装时不追求花哨,但连接串管理和参数化查询必须做好。

public class DbHelper { private static readonly string connStr = ConfigurationManager.ConnectionStrings["RestaurantDB"].ConnectionString; // 执行增删改,返回受影响行数 public static int ExecuteNonQuery(string sql, params SqlParameter[] pars) { using (SqlConnection conn = new SqlConnection(connStr)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (pars != null) cmd.Parameters.AddRange(pars); conn.Open(); return cmd.ExecuteNonQuery(); } } // 查询第一行第一列,常用于取单号、统计数量 public static object ExecuteScalar(string sql, params SqlParameter[] pars) { using (SqlConnection conn = new SqlConnection(connStr)) using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (pars != null) cmd.Parameters.AddRange(pars); conn.Open(); return cmd.ExecuteScalar(); } } }

逻辑说明:所有连接都放在using块里,保证用完后自动释放,这是初学者最容易漏掉的一步——连接不释放,跑一晚上后数据库连接池耗尽,点菜系统直接报“连接超时”。参数化查询不是可选项,而是必须项,拼接 SQL 字符串在菜名里有引号时直接报语法错误,中文写入也可能出现乱码。

参数说明:ConnectionString放在App.config里而不是写死在代码中,是这套架构最值得保留的习惯。老工程里最常见的坑就是连接串写死,换一台收银机就得重新编译,正确的做法是放在配置文件中,部署时只改配置不动代码。CommandTimeout默认 30 秒,点菜程序里一般不需要改,但如果生成报表时发现超时,优先优化的应该是 SQL 语句本身而不是盲目调大超时时间,这条经验后面还会再提。

3. 点菜下单、加菜结账与厨打小票:C# 核心流程的代码实现

数据模型搭好后,核心流程就是点菜系统真正值钱的部分。火锅店里最频繁的操作不是点菜,而是加菜——客人边吃边点,前后台需要不停地追加订单。同时服务员手持点菜终端或前台收银机同时操作,并发下单必须处理干净。这一章把下单、加菜、退菜、结账和厨打五个环节逐一实现,并给出关键参数怎么调。

3.1 下单必须包事务:开台、写主表、写明细三步一起提交

一个完整的点菜操作涉及三步:把桌台状态改为占用、往订单主表插入一条记录、往订单明细表插入菜品。这三步必须放在同一个数据库事务里,否则出现“主表写进去了,明细没写上”这种半截单。

public static int PlaceOrder(int tableId, string waiterName, DataTable dishList, out string errMsg) { errMsg = ""; using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); SqlTransaction tx = conn.BeginTransaction(IsolationLevel.ReadCommitted); try { // 1. 锁住桌台行,防止并发重复开台 string lockSql = "SELECT Status FROM TableInfo WITH(ROWLOCK, UPDLOCK) WHERE TableId=@tid"; int status = (int)new SqlCommand(lockSql, conn, tx) .Parameters.AddWithValue("@tid", tableId) .ExecuteScalar(); if (status != 0) throw new Exception("该桌已占用,不能重复开台"); // 2. 插入订单主表并取回新单号 string sqlOrder = "INSERT INTO \"Order\"(TableId, OpenTime, WaiterName, Status) " + "VALUES(@tid, @now, @waiter, 0); SELECT SCOPE_IDENTITY();"; SqlCommand cmdOrder = new SqlCommand(sqlOrder, conn, tx); cmdOrder.Parameters.AddWithValue("@tid", tableId); cmdOrder.Parameters.AddWithValue("@now", DateTime.Now); cmdOrder.Parameters.AddWithValue("@waiter", waiterName); int orderId = Convert.ToInt32(cmdOrder.ExecuteScalar()); // 3. 批量插入明细 foreach (DataRow row in dishList.Rows) { string sqlDetail = "INSERT INTO OrderDetail(OrderId, DishId, DishName, " + "PriceSnapshot, Quantity, Status) " + "VALUES(@oid, @did, @dname, @price, @qty, 0)"; SqlCommand cmdDetail = new SqlCommand(sqlDetail, conn, tx); cmdDetail.Parameters.AddWithValue("@oid", orderId); cmdDetail.Parameters.AddWithValue("@did", row["DishId"]); cmdDetail.Parameters.AddWithValue("@dname", row["DishName"].ToString()); cmdDetail.Parameters.AddWithValue("@price", Convert.ToDecimal(row["Price"])); cmdDetail.Parameters.AddWithValue("@qty", Convert.ToInt32(row["Quantity"])); cmdDetail.ExecuteNonQuery(); } tx.Commit(); return orderId; } catch (Exception ex) { tx.Rollback(); errMsg = ex.Message; return -1; } } }

逻辑说明:先对桌台行加UPDLOCK更新锁,再检查状态,再用SCOPE_IDENTITY()取新订单号——这三步是并发安全的铁三角。两个服务员同时给同一桌下单时,后进入事务的那个人会卡在锁上,等前者提交后才能读到最新的占用状态,从根上杜绝了重复开台。

参数说明:IsolationLevel.ReadCommitted是大多数点菜程序的合理默认值,既防止脏读,又不像Serializable那样把并发压得太低。AddWithValue虽然写法简洁,但遇到字段类型是DECIMAL(10,2)时建议显式指定SqlDbType,否则在某些环境下会因隐式类型转换导致索引失效,量小看不出来,报表数据大了就慢得明显。

3.2 加菜退菜怎么做才不出错:明细只增不改的原则

火锅局里加菜是高频操作,退菜也时有发生。新手最容易犯的错误是退菜时直接执行DELETE FROM OrderDetail WHERE DetailId=...,这样做的后果是:结了账之后想查“今天哪道菜被退得最多”,数据全没了。正确的做法是只把明细行的Status改成 1,数据永远留在表里。

public static bool AddDish(int orderId, DataRow dishRow) { string sql = "INSERT INTO OrderDetail(OrderId, DishId, DishName, " + "PriceSnapshot, Quantity, Status) VALUES(@oid, @did, @dname, @price, @qty, 0)"; SqlParameter[] pars = { new SqlParameter("@oid", orderId), new SqlParameter("@did", dishRow["DishId"]), new SqlParameter("@dname", dishRow["DishName"].ToString()), new SqlParameter("@price", Convert.ToDecimal(dishRow["Price"])), new SqlParameter("@qty", Convert.ToInt32(dishRow["Quantity"])) }; return DbHelper.ExecuteNonQuery(sql, pars) > 0; } public static bool CancelDish(int detailId, string reason) { // 退菜只做标记,不删除 string sql = "UPDATE OrderDetail SET Status=1, CancelReason=@reason " + "WHERE DetailId=@did"; SqlParameter[] pars = { new SqlParameter("@reason", reason), new SqlParameter("@did", detailId) }; return DbHelper.ExecuteNonQuery(sql, pars) > 0; }

逻辑说明:加菜本质上和首次下单插入明细没有区别,只是不需要再动订单主表;退菜则把Status改成 1,同时记下退菜原因。这里需要注意CancelReason字段在原始建表脚本里没有,如果你是按 2.2 的表结构建库,需要补一句ALTER TABLE OrderDetail ADD COLUMN CancelReason TEXT(SQL Server 下用ALTER TABLE OrderDetail ADD CancelReason NVARCHAR(200))。

参数说明:退菜原因建议做成下拉框而不是手填,常见原因就是“上错了”“太慢了”“客人不要了”。这样后期统计退菜率时能按原因分组,也能在结账时对退菜菜品做金额排除。结账汇总时记得用WHERE Status=0,只统计正常明细,否则把退掉的菜也算进营业额,账就对不上。

3.3 结账金额怎么算:折扣、服务费和抹零的策略

结账看起来是算总和,实际细节都在“优惠怎么落库”上。火锅店常见的优惠有整单折扣、会员价、满减和抹零。推荐的做法是:明细单价永远存原价,优惠通过主表字段记录,最后用小写金额只显示不落库。

public static decimal CalcOrderTotal(int orderId, out decimal originalTotal) { string sql = @"SELECT SUM(CASE WHEN Status=0 THEN PriceSnapshot * Quantity ELSE 0 END) AS Total FROM OrderDetail WHERE OrderId=@oid"; originalTotal = Convert.ToDecimal(DbHelper.ExecuteScalar(sql, new SqlParameter("@oid", orderId))); // 从主表读取折扣和抹零参数 string orderSql = "SELECT DiscountRate, RoundUp FROM \"Order\" WHERE OrderId=@oid"; // DiscountRate: 0.88 表示 8.8 折; RoundUp: 0 表示抹零到元 decimal finalAmount = originalTotal * discountRate; if (roundUp == 0) finalAmount = Math.Floor(finalAmount); return finalAmount; }

逻辑说明:SUM里用CASE WHEN Status=0把退掉的菜排除掉,这是结账正确性的底线。抹零用的是Math.Floor,意思是不管 88.7 还是 88.2,一律收 88;如果店里习惯四舍五入,换成Math.Round(finalAmount, 0, MidpointRounding.AwayFromZero)。

参数说明:折扣率在界面上建议用百分比控件录入,传给数据库时统一转成小数。更稳妥的做法是把优惠记录成“优惠金额”而非“折扣率”,比如原价 100 实收 88,就记DiscountAmount=12,这样对账时原价、优惠、实收三列相加能对上,财务查账不用猜。这是个老工程里普遍做得不够好的点,改造成本低收益却很大。

3.4 厨打小票用队列 + 委托:尽量别让 UI 卡在打印机上

厨打是点菜系统里最容易“卡死界面”的环节。直接在主线程里往打印机写数据,打印机缓冲区一满或通讯超时,整个点菜界面就僵在那里。正确的做法是把打印任务丢进队列,由后台线程逐个处理,完成后通过委托/事件通知界面更新状态,这也是 C# 事件与委托最常见的实战场景。

public class KitchenPrinter { private static Queue<string> printQueue = new Queue<string>(); private static Thread workerThread; private static bool isRunning = true; public static event Action<string> OnPrintFinished; // 通知 UI 更新 public static void Start() { workerThread = new Thread(ProcessQueue); workerThread.IsBackground = true; workerThread.Start(); } private static void ProcessQueue() { while (isRunning) { if (printQueue.Count > 0) { string content = printQueue.Dequeue(); // 向串口或并口打印机输出 content // PrinterHelper.WriteToPrinter(content); OnPrintFinished?.Invoke(content); } else { Thread.Sleep(200); // 队列空时休眠,避免空转 } } } public static void Enqueue(string content) { printQueue.Enqueue(content); } }

逻辑说明:Queue保证先点先打,后台线程ProcessQueue在队列为空时休眠 200 毫秒,而不是密集死循环,CPU 占用率能压到接近零。打印完成时触发OnPrintFinished事件,前台界面用Invoke把状态同步到 DataGridView 或状态栏,这样即使用户疯狂点菜,界面也不会因为打印而卡顿。

参数说明:Thread.IsBackground = true很关键,它保证程序退出时后台线程自动终止,不会出现关闭收银机后进程还在后台驻留的情况。队列容量在火锅店高峰期建议至少设 100 条,打印串口超时设为 3 秒,超过直接报错并把任务重新扔回队尾,而不是傻等。这一步就是很多人说的“玄学卡死”真正来源——打印异常没被捕获,异常弹窗挡住界面,服务员以为系统坏了。

4. 老工程最容易翻车的四个地方:现象、原因与排查

C# 点菜系统这类老工程,能跑通和能扛住真实营业是两码事。很多从 huoguo.rar 拿到手就能编译通过的代码,一放到营业现场就出各种诡异问题。这一章整理四个最常踩的坑,每条按现象、原因、排查三部分讲清楚,帮你少走弯路。

4.1 改了菜品价格,历史订单金额跟着变

现象:门店调整了一次毛肚价格,第二天查昨天的营收报表,发现昨天的营业额数字也变了,而且和当天实收对不上。

原因:程序在下单时只存了菜品 ID,没有存价格快照。结账和报表都是通过Dish.Price去联查菜品表求金额。菜品价格一改,历史所有的销售记录金额全部被重新计算,账目根本没法对。

解决:订单明细表必须落PriceSnapshot字段,也就是 2.2 建表 SQL 里那一列。已经跑起来的老库可以用一条 SQL 回填历史数据:UPDATE OrderDetail SET PriceSnapshot = (SELECT Price FROM Dish WHERE Dish.DishId = OrderDetail.DishId),然后修改结账和报表的联查逻辑,全部改用PriceSnapshot。排查时先看 SQL 语句里是OrderDetail.PriceSnapshot还是Dish.Price,后者就是定时炸弹。

4.2 两个人同时给一桌下单,其中一单丢了

现象:前台收银台和后厨触摸屏同时操作同一桌,界面都提示成功,但订单列表里只看到一条记录,有一个菜没进来。

原因:开台和下单之间没有事务保护,也没有对桌台行加锁。两个进程同时读到桌台“空闲”,各自插入订单主表,后插入的人也没发现桌台已经被占用,只是它的明细挂在了同一个桌台的不同订单上或直接插入失败被吞掉异常。

解决:参考 3.1 的写法,事务内先对桌台表执行SELECT ... WITH(ROWLOCK, UPDLOCK)锁行,再检查状态再下单。SQLite 版本注意BEGIN IMMEDIATE事务会锁整个数据库,所以并发高的场景不建议 SQLite 多收银台共用同一个库文件。排查方法是看订单主表有没有同一桌台几乎同时开出的两条订单,有就说明开台环节没加锁,赶紧补事务。

4.3 厨打小票中文乱码、打印到一半卡死

现象:厨房打印机打出来的小票,中文变成一堆问号或乱码;人多的时候打印机打到一半不动了,后面的菜全积压。

原因:乱码十有八九是编码不匹配——程序按UTF-8发送,打印机固件默认GBK/GB2312,或者 ESC/POS 指令里的中文字库没启用。打印卡死则是主线程直接写串口,没有超时控制和后台队列,打印机缓冲区满时程序阻塞在Write调用上,界面整体假死。

解决:字符编码统一在打印机驱动工具里设为GBK,C# 端发送前用Encoding.GetEncoding("GBK").GetBytes()转换。打印逻辑拆到后台线程配合队列,参考 3.4 的做法,并给串口写入加超时。排查时先单独用打印机自带测试页确认硬件没问题,再用串口调试工具直接发送一条固定文本,能打出中文说明是程序编码问题,打不出说明是打印机设置问题,两步就能定位。

4.4 报表查询把界面卡死,翻页像幻灯片

现象:晚上打烊后点“日结报表”,界面卡住十几秒才出来;订单多的月份查流水账,翻一页要等两三秒。

原因:报表 SQL 把几张表JOIN在一起,WHERE条件里对日期列用了函数如WHERE CONVERT(VARCHAR, OpenTime, 112) = '20250601',导致索引完全失效,全表扫描。同时 DataGridView 一次性绑定了几万行数据,界面渲染负担极重。

解决:日期条件改成范围查询WHERE OpenTime >= @start AND OpenTime < @end,让索引能用上。给Order表的OpenTime和OrderDetail表的OrderId建索引。DataGridView 开启虚拟模式或分页加载,只取当前页 100 条到内存。排查时在 SQL Server Management Studio 里看执行计划,出现Table Scan或Index Scan且代价占比超 50%,就说明索引没吃上,优先修 SQL 而不是加服务器内存。

5. 收银对账与两个值得动手改的优化点

老工程跑通后,最值得动手改的第一个地方是收银对账。火锅店营业结束后,老板要的是三张数:实收总额、优惠总额、每个菜品的销售排行。后端用一句 SQL 就能把账对平,我一般会写成店铺的日结脚本:

SELECT SUM(TotalAmount) AS ActualIncome, SUM(CASE WHEN Status = 2 THEN 1 ELSE 0 END) AS VoidOrders FROM "Order" WHERE CloseTime >= @todayStart AND CloseTime < @todayEnd; SELECT DishName, SUM(Quantity) AS TotalQty, SUM(PriceSnapshot * Quantity) AS TotalSales FROM OrderDetail WHERE Status = 0 AND OrderId IN ( SELECT OrderId FROM "Order" WHERE CloseTime >= @todayStart AND CloseTime < @todayEnd) GROUP BY DishName ORDER BY TotalSales DESC;

两个值得动手的优化点:一是给 DataGridView 开启虚拟模式,几千行订单数据一秒加载完,这是界面卡顿的根治方案;二是把多个明细插入改成一个DataTable批量写入,减少数据库往返次数,高峰期下单响应能从几百毫秒降到几十毫秒。我自己的血泪经验是:当年在店里上线时,结账高峰界面卡了整整一个周末,后来定位到是 DataGridView 一次性绑了全月数据,改成虚拟模式后问题消失,从那以后我对“先跑通再优化”这句话多了一层敬畏——跑通只是及格线,扛住饭点高峰才算真正落地。希望帮到你。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 13:26:50

gpt-image-1蒙版与Alpha通道实战:从局部重绘到生产落地

如果你已经在项目里接入了 OpenAI 的图像接口&#xff0c;大概率绕不开 gpt-image-1 这个模型。和早期 DALLE 那套流程相比&#xff0c;它最大的变化是把“生成、编辑、局部重绘”全部收拢到同一个接口里&#xff1a;你不再需要先抠图、再合成、再二次生成&#xff0c;只需要…

作者头像 李华
网站建设 2026/10/1 13:26:34

RK3576启动链深度解析:Maskrom与Loader协同机制

1. 项目概述&#xff1a;RK3576“变砖”不是玄学&#xff0c;是启动链上某个环节的彻底失联你手里的RK3576开发板突然不亮灯、不识别USB、串口无任何输出——连最基础的AT指令都喂不进去&#xff0c;烧写工具报错“device not found”或“no response”&#xff0c;这时候圈内人…

作者头像 李华
网站建设 2026/10/1 13:26:13

中文NER边界识别难题:BERT+BILSTM+CRF实战指南

简介&#xff1a;本资源面向计算机、人工智能、数据科学等专业学生及企业开发者&#xff0c;提供一套基于BERTBILSTMCRF的中文命名实体识别完整项目源码&#xff0c;适合作为毕业设计、课程设计或大作业的实战参考&#xff0c;也可用于初期项目立项演示。压缩包共58个文件&…

作者头像 李华
网站建设 2026/10/1 13:24:46

tushare+TensorFlow2.0:用RNN/LSTM预测贵州茅台开盘价

简介&#xff1a;面向金融时序预测与深度学习入门人群&#xff0c;这份资源以贵州茅台历史行情为例&#xff0c;演示如何通过tushare获取真实A股数据&#xff0c;并基于TensorFlow 2.0搭建RNN和LSTM模型预测开盘价&#xff0c;完整覆盖数据抓取、清洗归一化、模型构建、训练评估…

作者头像 李华
网站建设 2026/10/1 13:24:32

制造业AI智能体落地:五道门槛与选型复制指南

去年年底参加一场制造业数字化转型的交流会&#xff0c;茶歇时有位汽车零部件厂的IT负责人对我说了句印象很深的话&#xff1a;朋友圈里别人的AI智能体都能写代码、自动做报表了&#xff0c;我们车间里连设备报工还得靠人工录&#xff0c;这差距是不是已经追不上了&#xff1f;…

作者头像 李华