news 2026/10/10 9:37:22

超市进销存管理系统源码二次开发:库存扣减、成本核算与对账脚本实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
超市进销存管理系统源码二次开发:库存扣减、成本核算与对账脚本实战

简介:这份超市进销存管理系统源码面向Java初学者、课程设计学生及需要小型零售管理系统的开发者,帮助理解采购、销售、库存等核心业务在代码层面的实现方式。资源包共239个文件,约1.24MB,以146个class编译文件与49个java源码为主,另含25个png、6个jpg界面素材,以及4个db数据库文件、mdf与ldf数据文件、xml配置、fatjar可执行包和doc说明文档,覆盖登录验证、销售管理、商品统计、入库退货等模块,便于对照源码梳理分层结构与数据库交互逻辑。已有48人学习下载,适合作为课程设计参考或二次开发基础,可从中获取完整项目结构、界面资源与数据文件,快速搭建可运行的进销存演示环境。

1. 超市进销存管理系统源码:从“能跑”到“敢用”之间差了什么

很多开发者拿到一份超市进销存管理系统源码,第一反应是打开 IDE 跑起来看看界面长什么样。能登录、能加商品、能开单,就觉得“这套东西能用”。但真正放到一家日均几百单的小超市里跑一周,问题就会集中爆发:库存对不上、并发开单丢数据、退货后成本价算错、盘点差异查不到原因。进销存系统的核心难点从来不在界面,而在库存扣减的时机、成本核算的算法、以及单据之间的勾稽关系。这份源码值不值得投入精力去改,取决于它有没有把这三件事做对。本文面向手里已经有一份源码、或者准备选一套进销存系统二次开发的从业者,把选型判断、核心模块实现、参数配置和常见翻车点拆开讲清楚,让你看完能判断手里的代码能不能用、该怎么改。

2. 拿到源码先别急着改界面:四个模块的验收顺序

一套完整的超市进销存系统,代码结构通常分为基础资料、采购入库、销售出库、库存盘点四大块。很多人上来就调前端样式,结果改到一半发现库存逻辑是错的,前面的工作全白费。正确的验收顺序应该从数据模型开始,往业务逻辑推,最后才是交互层。

2.1 先看数据库表结构能不能撑住业务

打开源码的 SQL 文件或者 ORM 映射文件,重点看这几张表的设计:商品表、库存表、入库单主表/明细表、出库单主表/明细表、库存流水表。判断标准很直接——库存流水表是不是独立存在的。如果源码里只有一张库存表,每次出入库直接 update 数量字段,没有流水记录,这套代码在出现库存差异时你根本查不到原因,直接放弃或者做好重写库存模块的准备。

库存流水表至少要包含这些字段:

CREATE TABLE stock_flow ( id BIGINT PRIMARY KEY AUTO_INCREMENT, goods_id BIGINT NOT NULL COMMENT '商品ID', warehouse_id BIGINT NOT NULL DEFAULT 1 COMMENT '仓库ID,单店默认1', biz_type TINYINT NOT NULL COMMENT '业务类型:1采购入库 2销售出库 3退货入库 4退货出库 5盘点调整 6报损', biz_no VARCHAR(32) NOT NULL COMMENT '关联单据号', change_qty DECIMAL(12,3) NOT NULL COMMENT '变动数量,入库为正出库为负', before_qty DECIMAL(12,3) NOT NULL COMMENT '变动前数量', after_qty DECIMAL(12,3) NOT NULL COMMENT '变动后数量', cost_price DECIMAL(12,4) DEFAULT NULL COMMENT '该次变动的成本单价', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, INDEX idx_goods_time (goods_id, created_at), INDEX idx_biz_no (biz_no) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存流水表';

这张表的关键在于before_qty和after_qty两个字段。它们记录了每次变动的快照,盘点时如果发现账实不符,可以顺着流水逐笔核对,定位到是哪一笔单据出了问题。cost_price字段用于移动加权平均法的成本核算,后面会展开讲。biz_type用枚举值区分业务类型,比用字符串可读性差一点,但查询效率和存储空间都更优。

如果源码里库存表用的是stock单表且没有流水,你需要评估改造工作量。简单做法是在现有出入库逻辑里插入流水记录,但要注意历史数据的初始化——上线前做一次全量盘点,把盘点结果作为第一条流水写入,before_qty设为 0,after_qty设为实际库存。

2.2 采购入库的成本价是怎么算的

采购入库单的明细里通常有采购价,但库存的成本价不一定等于采购价。超市场景下,同一商品不同批次的进价可能不同,出库时用哪个价格算成本,直接影响毛利报表的准确性。常见做法有三种:先进先出、移动加权平均、手工指定。大部分中小超市用移动加权平均就够了,实现也简单。

移动加权平均的公式是:新成本价 = (原库存金额 + 本次入库金额) / (原库存数量 + 本次入库数量)。每次入库后重新计算,出库时按当前成本价扣减。用代码实现时,注意在同一个事务里完成库存更新和成本价更新:

def purchase_inbound(goods_id, qty, price, biz_no): """ 采购入库:更新库存、重算移动加权平均成本、写流水 qty: 入库数量,正数 price: 本次采购单价 """ with db.transaction(): stock = db.query_one( "SELECT qty, cost_price FROM stock WHERE goods_id=%s FOR UPDATE", (goods_id,) ) old_qty = stock['qty'] old_cost = stock['cost_price'] old_amount = old_qty * old_cost new_amount = old_amount + qty * price new_qty = old_qty + qty new_cost = new_amount / new_qty if new_qty > 0 else 0 db.execute( "UPDATE stock SET qty=%s, cost_price=%s WHERE goods_id=%s", (new_qty, round(new_cost, 4), goods_id) ) db.execute( """INSERT INTO stock_flow (goods_id, biz_type, biz_no, change_qty, before_qty, after_qty, cost_price) VALUES (%s, 1, %s, %s, %s, %s, %s)""", (goods_id, biz_no, qty, old_qty, new_qty, round(new_cost, 4)) )

这段代码有两个关键点。第一,SELECT ... FOR UPDATE是必须的,否则两个采购单同时入库会导致成本价算错。第二,成本价保留 4 位小数,因为多次加权平均后小数位会累积,保留太少会导致金额对不上。出库时直接用stock.cost_price作为成本单价写入流水,不需要重新计算。

如果源码里用的是先进先出,代码会复杂很多,需要按批次记录库存。中小超市除非有明确的批次管理需求(比如生鲜保质期),否则不建议用先进先出,维护成本太高。

2.3 销售出库的库存扣减时机

销售出库的库存扣减时机是个容易翻车的点。有的源码在收银时直接扣库存,有的在日结时统一扣。两种做法各有适用场景,但超市场景下建议收银时实时扣减,因为库存不准会影响后续销售——顾客要买 10 瓶水,系统显示还有 8 瓶,这单就做不成。

实时扣减的代码逻辑和采购入库类似,只是方向相反:

def sale_outbound(goods_id, qty, biz_no): """ 销售出库:扣减库存、按当前成本价写流水 qty: 出库数量,正数 """ with db.transaction(): stock = db.query_one( "SELECT qty, cost_price FROM stock WHERE goods_id=%s FOR UPDATE", (goods_id,) ) if stock['qty'] < qty: raise BizError(f"库存不足,当前库存 {stock['qty']}") new_qty = stock['qty'] - qty db.execute( "UPDATE stock SET qty=%s WHERE goods_id=%s", (new_qty, goods_id) ) db.execute( """INSERT INTO stock_flow (goods_id, biz_type, biz_no, change_qty, before_qty, after_qty, cost_price) VALUES (%s, 2, %s, %s, %s, %s, %s)""", (goods_id, biz_no, -qty, stock['qty'], new_qty, stock['cost_price']) )

注意change_qty存的是负数,这样在流水表里直接 sum 就能得到当前库存,方便对账。库存不足时抛异常回滚事务,避免超卖。如果源码里没有这个判断,一定要加上,否则会出现负库存,后续盘点全是坑。

2.4 盘点单的差异处理逻辑

盘点单是进销存系统里最容易被忽视的模块。很多源码的盘点功能只是把库存数量改成盘点数量,没有记录差异原因和调整流水。正确的做法是:盘点单保存时生成一条biz_type=5的流水,change_qty等于盘点数量减账面数量,before_qty是账面数量,after_qty是盘点数量。这样盘点差异就变成了库存流水的一部分,可以追溯。

盘点单的明细表还需要一个diff_reason字段,记录差异原因(如破损、丢失、录入错误)。这个字段在后续做损耗分析时很有用。如果源码里没有,加一个 varchar 字段的成本很低,但带来的管理价值很高。

3. 库存扣减的并发问题:从超卖到死锁的排查

库存扣减是进销存系统里并发问题最集中的地方。单机单线程跑没问题,一上多收银台就出各种玄学问题。这一章把常见的并发场景和排查方法讲清楚。

3.1 超卖的三种典型场景

超卖是指库存扣成了负数,或者多个订单同时扣同一批库存导致实际库存不够。第一种场景是两个收银台同时卖同一商品,都查到库存为 1,都判断库存充足,然后都扣减,结果库存变成 -1。第二种场景是收银和退货同时操作,退货先加库存,收银后扣库存,但退货事务还没提交,收银读到的还是旧库存。第三种场景是批量导入历史销售数据时没有加锁,多线程同时更新。

这三种场景的根因都一样:读库存和写库存之间没有原子性保证。解决办法就是在读取库存时加行锁,SELECT ... FOR UPDATE是最直接的方式。但加锁会带来性能问题,如果商品数量多、并发高,锁竞争会很严重。

3.2 用乐观锁还是悲观锁

悲观锁就是上面代码里的FOR UPDATE,优点是实现简单、不容易出错,缺点是并发高时锁等待时间长。乐观锁是在库存表加一个version字段,更新时检查版本号:

UPDATE stock SET qty = qty - 5, version = version + 1 WHERE goods_id = 1001 AND version = 3 AND qty >= 5;

如果影响行数为 0,说明版本号变了或者库存不足,需要重试。乐观锁适合读多写少的场景,但超市收银是写多读少,而且重试逻辑会增加代码复杂度。我的经验是:中小超市(日均 500 单以内)直接用悲观锁,简单可靠;大型超市或者线上线下一体化的场景再考虑乐观锁或者分布式锁。

3.3 死锁是怎么产生的

死锁通常发生在批量操作时,两个事务以不同的顺序锁定多行库存。比如事务 A 先锁商品 1 再锁商品 2,事务 B 先锁商品 2 再锁商品 1,两者互相等待。排查死锁的方法是看数据库的死锁日志,MySQL 用SHOW ENGINE INNODB STATUS可以看到最近一次死锁的详细信息。

避免死锁的做法是统一加锁顺序。在批量扣减库存时,先把商品 ID 排序,再按顺序逐个加锁。这样所有事务的加锁顺序一致,就不会出现循环等待。代码里加一行排序就能解决:

goods_ids = sorted(set(item['goods_id'] for item in items)) for gid in goods_ids: db.query_one("SELECT qty FROM stock WHERE goods_id=%s FOR UPDATE", (gid,))

3.4 事务隔离级别怎么选

MySQL 默认的隔离级别是 RR(可重复读),在这个级别下FOR UPDATE会加间隙锁,可能导致更多的锁等待。如果业务允许,可以把隔离级别降到 RC(读已提交),减少间隙锁。但 RC 级别下可能出现不可重复读,也就是同一个事务里两次读同一行数据结果不一样。对于库存扣减来说,只要加了FOR UPDATE,RC 和 RR 都能保证正确性,RC 的并发性能更好。

设置隔离级别的命令是SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED,可以在连接池初始化时统一设置。如果源码里没有显式设置,默认就是 RR,中小超市够用,不用急着改。

4. 避坑:源码二次开发中最容易翻车的五个地方

这一章记录的是我在改造和部署进销存系统时踩过的坑,每个都按现象、原因、解决来写。如果你手里的源码有类似问题,提前改掉能省很多时间。

4.1 库存流水和库存表对不上

现象:盘点时发现库存表的数量和流水表 sum 出来的数量不一致,差异不大但一直存在。

原因:出入库代码里更新库存表和写流水不在同一个事务里,或者流水写入失败后没有回滚库存更新。还有一种情况是历史数据初始化时只写了库存表,没有写初始流水。

解决:把所有库存变动逻辑收敛到一个统一的函数里,库存更新和流水写入必须在同一个事务中。初始化时用盘点单的方式写入初始流水,before_qty=0,after_qty=实际库存。上线后定期跑对账脚本,发现差异立即排查。

4.2 退货后成本价算错

现象:顾客退货后,库存数量对了,但毛利报表里的成本金额不对。

原因:退货入库时用了销售时的成本价,但移动加权平均法下,退货应该按当前成本价入库,而不是原销售成本价。如果源码里退货逻辑直接取原单的成本价,就会导致成本价偏差。

解决:退货入库时重新计算移动加权平均成本,和采购入库用同一套逻辑。退货单的biz_type设为 3,cost_price取退货时的当前成本价。如果业务上需要按原单成本退货,那成本核算方法就要改成先进先出,不能混用。

4.3 盘点后库存被覆盖

现象:盘点单审核后,库存数量变成了盘点数量,但盘点期间发生的出入库单据被覆盖了。

原因:盘点逻辑是直接UPDATE stock SET qty = 盘点数量,没有考虑盘点期间的新增流水。正确做法是盘点单审核时,计算盘点数量与当前库存的差异,生成调整流水,而不是直接覆盖。

解决:盘点单保存时记录盘点时的账面数量,审核时用盘点数量 - 当前库存作为调整量,写入流水。这样盘点期间的出入库不会被覆盖,差异也能追溯。

4.4 并发开单时单据号重复

现象:两个收银台同时开单,生成的单据号一样,导致后续查询和退货找不到单。

原因:单据号生成用了SELECT MAX(biz_no) + 1的方式,并发时两个事务读到同一个最大值。

解决:单据号生成用数据库序列或者 Redis 自增,不要用 max+1。如果源码里用的是 max+1,改成时间戳加随机数或者数据库自增 ID。单据号只要求唯一,不要求连续,所以用 UUID 也可以,只是可读性差一点。

4.5 商品条码重复导致入库错乱

现象:扫码入库时,扫 A 商品的条码,系统识别成了 B 商品。

原因:商品表没有对条码做唯一约束,或者条码字段允许为空,多个商品条码为空时扫码查询返回了错误记录。

解决:商品表的条码字段加唯一索引,允许为空但不允许重复。扫码查询时如果返回多条记录,提示用户手动选择。如果源码里没有唯一索引,加索引前先清理重复数据。

5. 从单店到多店:库存调拨和权限控制的实现要点

单店跑通之后,如果业务扩展到多店,源码需要支持库存调拨和门店权限隔离。这一章讲两个进阶功能的实现思路和关键参数。

5.1 库存调拨的单据设计

调拨本质上是两次库存变动:调出门店出库,调入门店入库。但这两次变动不能独立发生,必须在一个事务里完成,否则会出现货已发出但对方没收到的情况。调拨单的主表记录调出和调入门店,明细表记录商品和数量。审核时执行:

def transfer_approve(transfer_id): """ 调拨单审核:调出门店扣库存,调入门店加库存 """ items = db.query("SELECT * FROM transfer_item WHERE transfer_id=%s", (transfer_id,)) with db.transaction(): for item in items: # 调出门店出库 outbound(item['from_warehouse_id'], item['goods_id'], item['qty'], transfer_id) # 调入门店入库,成本价取调出门店的当前成本价 cost = get_cost_price(item['from_warehouse_id'], item['goods_id']) inbound(item['to_warehouse_id'], item['goods_id'], item['qty'], cost, transfer_id)

调入门店的成本价取调出门店的成本价,这样调拨不会产生利润,只是库存位置的转移。如果源码里调拨时重新按采购价入库,会导致毛利虚高。

5.2 门店权限隔离的三种方案

多店场景下,每个门店只能看自己的库存和单据。实现方案有三种:按门店 ID 过滤、按仓库 ID 过滤、按数据权限角色过滤。最简单的是在库存表和单据表加warehouse_id字段,所有查询都带上这个条件。如果源码里没有这个字段,改造工作量较大,需要评估。

权限控制建议用角色加数据范围的方式。角色定义能操作哪些菜单,数据范围定义能看哪些门店的数据。这样新增门店时只需要配置数据范围,不用改代码。如果源码里权限是硬编码的,建议先重构权限模块再扩展多店。

5.3 调拨在途库存的处理

调拨单审核后、调入方确认前,这批货处于在途状态。严格来说,在途库存既不属于调出门店也不属于调入门店,需要单独记录。简单做法是调拨单审核时调出门店直接扣库存,调入门店直接加库存,不记录在途。这样账面上库存是准的,但实物在途时两边都查不到。如果业务上需要跟踪在途,可以在调拨单加一个状态字段,审核后状态为“在途”,调入方确认后状态改为“已完成”,库存变动在确认时才执行。

两种做法各有取舍。不记录在途的实现简单,适合调拨频繁但距离近的场景;记录在途的实现复杂,但能准确反映实物位置,适合跨城市调拨。根据实际业务选,不要为了技术先进而增加复杂度。

5.4 多店库存查询的性能优化

多店场景下,库存查询需要跨门店汇总。如果门店数量多,直接 join 查询会很慢。优化方式有两种:一是加汇总表,定时把各门店库存汇总到一张表里,查询时直接读汇总表;二是用缓存,把库存数据缓存到 Redis,查询时先读缓存。汇总表适合对实时性要求不高的场景,缓存适合对实时性要求高的场景。

如果源码里没有做这些优化,门店数量在 10 家以内时直接查询问题不大。超过 10 家再考虑加汇总表或缓存。不要过早优化,先把业务跑通。

6. 用对账脚本验证库存准确性:一个可复用的排查方法

库存准确性是进销存系统的生命线。不管代码写得多好,上线后都要定期对账。这一章给一个可复用的对账脚本,以及我平时排查库存问题的习惯。

6.1 对账脚本的核心逻辑

对账脚本要回答三个问题:库存表的数量是否等于流水表的 sum,流水表的 before_qty 和 after_qty 是否连续,成本价是否在合理范围内。下面是一个 Python 脚本的骨架:

def reconcile_stock(): """ 库存对账:检查库存表与流水表是否一致 返回差异列表 """ diffs = [] # 1. 数量对账 rows = db.query(""" SELECT s.goods_id, s.qty AS stock_qty, COALESCE(SUM(f.change_qty), 0) AS flow_qty FROM stock s LEFT JOIN stock_flow f ON s.goods_id = f.goods_id GROUP BY s.goods_id, s.qty HAVING s.qty != COALESCE(SUM(f.change_qty), 0) """) for row in rows: diffs.append({ 'type': 'qty_mismatch', 'goods_id': row['goods_id'], 'stock_qty': row['stock_qty'], 'flow_qty': row['flow_qty'] }) # 2. 流水连续性检查 flows = db.query(""" SELECT goods_id, before_qty, after_qty, change_qty FROM stock_flow ORDER BY goods_id, id """) last_after = {} for f in flows: gid = f['goods_id'] if gid in last_after and f['before_qty'] != last_after[gid]: diffs.append({ 'type': 'flow_discontinuous', 'goods_id': gid, 'expected_before': last_after[gid], 'actual_before': f['before_qty'] }) if f['before_qty'] + f['change_qty'] != f['after_qty']: diffs.append({ 'type': 'flow_calc_error', 'goods_id': gid, 'before': f['before_qty'], 'change': f['change_qty'], 'after': f['after_qty'] }) last_after[gid] = f['after_qty'] return diffs

这个脚本跑一次就能把大部分库存问题暴露出来。qty_mismatch说明库存表和流水表不一致,通常是事务问题;flow_discontinuous说明流水中间有断档,可能是历史数据初始化没做;flow_calc_error说明流水本身的 before+change 不等于 after,是代码 bug。

6.2 对账频率和差异处理

对账频率根据业务量定。日均 100 单以下每周跑一次,100 到 500 单每天跑一次,500 单以上建议实时对账——每笔单据完成后异步检查一次。差异处理的原则是:先查原因再调整,不要直接改库存表。找到差异原因后,用盘点单的方式调整库存,这样调整本身也会留下流水记录。

如果差异金额较小(比如几分钱),可能是小数位精度问题,可以设置一个容差范围,比如 0.01 以内忽略。如果差异金额较大,一定要查到具体单据,不能放过。

6.3 我平时排查库存问题的习惯

我排查库存问题的第一步永远是看流水表,不是看库存表。库存表是结果,流水表是过程。过程对了结果一定对,过程错了结果对了也是暂时的。看流水时重点看三样:变动时间是否连续、变动数量是否合理、成本价是否突变。成本价突变通常意味着加权平均算错了,或者有人手工改了库存。

第二个习惯是复现问题。找到可疑单据后,在测试环境用同样的数据跑一遍,看能不能复现。能复现的问题都好解决,不能复现的问题通常是并发导致的,需要加日志或者压测。

第三个习惯是留后悔药。每次调整库存前先备份库存表和流水表,调整后立即对账。调整操作要记录操作人和原因,方便后续追溯。这些习惯看起来麻烦,但比出了问题再翻日志快得多。

6.4 一个具体的排查案例

某次对账发现商品 A 的库存表数量比流水 sum 多了 3 个。查流水发现三天前有一笔采购入库单,流水记录的数量是 10,但库存表只增加了 7。进一步查代码发现,那笔入库单的明细里有三行同一个商品,代码在处理时只更新了第一行的库存,后两行被跳过了。原因是明细表的主键设计有问题,同一个商品多行时主键冲突,后两行插入失败但事务没有回滚。

修复方式是给明细表加自增主键,不要用商品 ID 做联合主键。同时把库存更新逻辑改成按商品汇总后更新,避免同一商品多次更新。这个案例的教训是:明细表的主键设计要在开发初期就定好,后期改成本很高。

6.5 对账脚本的自动化部署

对账脚本建议做成定时任务,每天凌晨跑一次,结果发到工作群或者邮件。如果差异条数超过阈值(比如 5 条),触发告警。脚本本身要幂等,重复跑不会产生副作用。日志保留至少 30 天,方便回溯。

如果源码里没有对账功能,把这个脚本加进去是投入产出比很高的一件事。它不能防止问题发生,但能让你在问题扩大之前发现它。我见过太多超市因为库存不准导致盘点时才发现亏了几万块,如果有对账脚本,这个损失可以降到几百块。

希望帮到你。

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

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

英语报警口语速成:5W框架与六大紧急场景应对

1. 报警电话的5W框架&#xff1a;先搞清楚接警员想听什么很多人学英语报了十多年培训班&#xff0c;雅思也考过&#xff0c;真到了国外碰上抢劫、车祸或者朋友突然倒地不起的那一刻&#xff0c;大脑直接一片空白&#xff0c;嘴里只剩下“Hello”和“Help”。这不是个别现象&…

作者头像 李华
网站建设 2026/10/10 9:35:46

银行排队系统:从数据结构到事件驱动仿真全解析

简介&#xff1a;一份面向数据结构课程期末作业的银行排队系统实现资源&#xff0c;重点演示队列先进先出结构以及VIP与普通用户的多队列优先级调度。压缩包共九个文件&#xff0c;大小约1.03MB&#xff0c;包含C源码、用户信息文本、可执行程序及Code::Blocks工程文件&#xf…

作者头像 李华
网站建设 2026/10/10 9:35:05

高校社区生鲜配送系统实战:从Spring Boot部署到订单状态机设计

简介&#xff1a;面向高校社区场景的生鲜配送系统项目&#xff0c;是一份基于Java技术的Web前后端完整工程&#xff0c;适合计算机专业学生用于毕业设计、课程设计或项目实训。系统覆盖用户管理、商品管理、订单处理、库存控制、配送调度、支付接口、数据分析、客服和移动端适配…

作者头像 李华
网站建设 2026/10/10 9:34:30

Slaunt:AI Agent可观测性与行为监控工具解析

这次我们来看一个和 AI Agent 可观测性相关的项目&#xff1a;Slaunt。一句话说清它的定位&#xff1a;当你本地或生产环境里跑了一堆 Agent&#xff08;智能体&#xff09;任务时&#xff0c;它帮你搞清楚这些 Agent到底在做什么、做到哪一步了、有没有卡住或出错。现在做 LLM…

作者头像 李华
网站建设 2026/10/10 9:34:27

VMware虚拟机摄像头打不开?从物理机到客户机全链路排查指南

启动虚拟机准备开会&#xff0c;视频软件里点开摄像头&#xff0c;画面却一直黑着&#xff0c;右下角显示找不到相机。在物理机上试明明一切正常&#xff0c;一进虚拟机就掉链子。这个问题我帮不少朋友处理过&#xff0c;标题里的“wmware”其实就是VMware Workstation/Player这…

作者头像 李华
网站建设 2026/10/10 9:33:20

REA模式:用资源事件代理人重构业务数据建模与库存系统

做后台业务系统或者数据建模做久了&#xff0c;手头难免积压一堆“看着差不多但谁都不敢动”的表&#xff1a;销售订单、出库单、销售发票、收款单、库存流水&#xff0c;字段越加越多&#xff0c;关联越绕越深&#xff0c;最后连写一条“这个月到底赚了多少”的SQL都要折腾半天…

作者头像 李华