Java超市购物系统数据库设计与收银流程实战:从表结构到事务避坑
简介这是一套面向Java初学者与课程设计者的超市购物系统完整源码包包含可运行的Java程序、数据库文件与配套文档适合用于毕业设计、课程作业或Java桌面开发练手。资源共165个文件以105个class编译文件与31个java源码为主另含5个jar依赖、8张png界面截图、2个txt说明及mdf、ldf数据库文件、xls与doc文档等压缩包约2.48MB结构紧凑便于直接导入运行。系统覆盖商品管理、库存出入库、收银结算、会员注册等核心模块数据库表设计、需求分析与设计文档一并提供可帮助读者理解MVC分层、JDBC操作与Swing界面交互的完整实现思路。目前已有349人学习下载适合需要快速获取可运行项目、对照文档梳理开发流程的读者参考。1. 从一张小票倒推Java 超市购物系统到底要解决什么很多人第一次接触「Java 超市购物系统包含数据库和详细的文档」这个题目是在课程设计或者毕业设计里。我见过太多人上来就打开 IDE 建包结果写到一半发现库存扣减和订单对不上收银台结完账库存没变退货之后金额又算错了。问题不在代码写得慢而在于一开始没想清楚这套系统到底在模拟什么。它本质上是一个「商品—库存—订单—支付」四件事互相咬合的小型业务系统。数据库负责把商品、库存、订单、会员这几张表的关系固定下来Java 后端负责在并发收银时保证库存不会卖成负数文档则负责让接手的人知道每张表为什么这么设计。适合谁适合想用一个完整项目把 JDBC、事务、表设计、分层架构串起来的人。它不复杂但每个环节都能踩坑这正是它值得做的原因。2. 数据库表设计五张核心表怎么定字段和约束2.1 商品表与库存表为什么建议分开新手最容易犯的错是把库存直接塞进商品表觉得一个商品一个库存字段就够了。单机跑没问题一旦要做入库记录、盘点、批次管理这个字段就不够用了。常见做法是把商品基础信息和库存数量拆开商品表存名称、条码、进价、售价、分类库存表存商品 ID、当前数量、预警阈值、最后更新时间。这样拆的好处是商品信息变更不影响库存流水库存变动也不会锁住商品表。代价是每次查「商品还剩多少」都要关联一次但这点开销在超市这种规模下完全可以接受。-- 商品表只存不变的属性 CREATE TABLE product ( id BIGINT PRIMARY KEY AUTO_INCREMENT, barcode VARCHAR(32) NOT NULL UNIQUE COMMENT 条码收银扫码用, name VARCHAR(64) NOT NULL, category_id BIGINT NOT NULL, purchase_price DECIMAL(10,2) NOT NULL COMMENT 进价, sale_price DECIMAL(10,2) NOT NULL COMMENT 售价, status TINYINT NOT NULL DEFAULT 1 COMMENT 1上架 0下架, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 库存表只存会变的数量 CREATE TABLE inventory ( product_id BIGINT PRIMARY KEY, quantity INT NOT NULL DEFAULT 0, warn_threshold INT NOT NULL DEFAULT 10 COMMENT 低于此值提醒补货, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, CONSTRAINT fk_inv_product FOREIGN KEY (product_id) REFERENCES product(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字段说明barcode加唯一索引是因为收银扫码必须能唯一定位商品purchase_price和sale_price都用DECIMAL而不是FLOAT金额计算用浮点会出现 0.10.2 不等于 0.3 的经典问题inventory用product_id做主键而不是另起自增 ID是因为一个商品只有一条库存记录没必要多一层映射。2.2 订单主表与明细表的金额字段怎么留订单表的设计直接决定后面退货和对账好不好做。我的习惯是订单主表只存「这一单总共多少钱、实收多少、找零多少、谁收的、什么时候收的」明细表存「这一单里每个商品买了几件、单价多少、小计多少」。关键点是明细表里的单价要单独存一份不能只靠商品 ID 去关联查售价。因为商品售价会变如果退货时按当前售价算金额就对不上了。这是血泪经验很多人第一次做退货功能才发现这个问题。CREATE TABLE orders ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE COMMENT 业务单号对外展示, member_id BIGINT NULL COMMENT 会员ID散客为空, total_amount DECIMAL(10,2) NOT NULL COMMENT 应收, pay_amount DECIMAL(10,2) NOT NULL COMMENT 实收, change_amount DECIMAL(10,2) NOT NULL DEFAULT 0 COMMENT 找零, pay_type TINYINT NOT NULL COMMENT 1现金 2扫码 3会员余额, cashier_id BIGINT NOT NULL, status TINYINT NOT NULL DEFAULT 1 COMMENT 1已完成 2已退货, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE order_item ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT NOT NULL, product_id BIGINT NOT NULL, product_name VARCHAR(64) NOT NULL COMMENT 下单时名称快照, unit_price DECIMAL(10,2) NOT NULL COMMENT 下单时单价快照, quantity INT NOT NULL, subtotal DECIMAL(10,2) NOT NULL, CONSTRAINT fk_item_order FOREIGN KEY (order_id) REFERENCES orders(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;product_name和unit_price这两个快照字段是重点。商品改名或调价后历史订单仍然能还原当时的样子对账和退货都不会翻车。order_no和id分开是因为自增 ID 会暴露单量业务单号可以按日期加随机串生成对外更安全。2.3 会员表与收银员表的权限字段会员表除了手机号、姓名、余额还要有一个level字段区分折扣等级。收银员表则要有role字段区分普通收银和店长因为退货、改价这类操作通常只有店长能做。CREATE TABLE member ( id BIGINT PRIMARY KEY AUTO_INCREMENT, phone VARCHAR(16) NOT NULL UNIQUE, name VARCHAR(32) NOT NULL, balance DECIMAL(10,2) NOT NULL DEFAULT 0, level TINYINT NOT NULL DEFAULT 1 COMMENT 1普通 2银卡 3金卡, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE cashier ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32) NOT NULL UNIQUE, password VARCHAR(128) NOT NULL COMMENT 存哈希不存明文, role TINYINT NOT NULL DEFAULT 1 COMMENT 1收银员 2店长, status TINYINT NOT NULL DEFAULT 1 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;password字段长度给到 128是因为用 BCrypt 这类算法生成的哈希串比较长如果按 32 或 64 建表后面存不下会报错。这个坑我在两个项目里都见过。3. 用 JDBC 把收银主流程跑通从扫码到扣库存3.1 收银主流程的六步拆解一次收银在代码里其实是六步扫码查商品、加入购物车、计算总价和折扣、生成订单主表、批量写订单明细、扣减库存。这六步必须在一个数据库事务里完成否则会出现订单写了但库存没扣或者库存扣了订单没写的情况。我一般会用一个CheckoutService类来编排这六步DAO 层只负责单表操作事务边界放在 Service 层。这样职责清晰出问题也好定位。public class CheckoutService { private final ProductDao productDao new ProductDao(); private final OrderDao orderDao new OrderDao(); private final InventoryDao inventoryDao new InventoryDao(); /** * param items 购物车条目包含商品ID和数量 * param cashierId 收银员ID * param payType 支付方式 * return 生成的订单号 */ public String checkout(ListCartItem items, long cashierId, int payType) throws SQLException { Connection conn null; try { conn DbUtil.getConnection(); conn.setAutoCommit(false); // 开启事务 BigDecimal total BigDecimal.ZERO; // 第一步逐条校验库存并累加金额 for (CartItem item : items) { int stock inventoryDao.getQuantity(conn, item.getProductId()); if (stock item.getQuantity()) { throw new BizException(商品库存不足: item.getProductId()); } Product p productDao.getById(conn, item.getProductId()); item.setUnitPrice(p.getSalePrice()); item.setProductName(p.getName()); total total.add(p.getSalePrice() .multiply(BigDecimal.valueOf(item.getQuantity()))); } // 第二步写订单主表 String orderNo OrderNoGenerator.next(); long orderId orderDao.insertOrder(conn, orderNo, total, cashierId, payType); // 第三步批量写明细并扣库存 for (CartItem item : items) { orderDao.insertItem(conn, orderId, item); int affected inventoryDao.deduct(conn, item.getProductId(), item.getQuantity()); if (affected 0) { throw new BizException(扣减库存失败可能已被其他收银台抢先); } } conn.commit(); return orderNo; } catch (Exception e) { if (conn ! null) conn.rollback(); throw e; } finally { if (conn ! null) conn.setAutoCommit(true); DbUtil.close(conn); } } }逻辑说明整个方法用setAutoCommit(false)开启事务任何一步抛异常都会走到rollback保证订单和库存要么都成功要么都回滚。deduct方法返回受影响行数如果返回 0 说明库存被别的收银台抢先扣了这时候要抛异常触发回滚。参数说明items是购物车列表每个元素带商品 ID 和数量cashierId用于记录是谁收的银payType决定后续是走现金找零还是会员余额扣减。OrderNoGenerator是一个按「日期序列」生成业务单号的工具类保证同一天内不重复。3.2 扣库存的 SQL 必须带条件判断扣库存这一步是并发问题的重灾区。如果先查再扣两个收银台同时查到库存是 1都认为够然后都去扣库存就变成 -1 了。正确做法是把判断和扣减合并成一条 SQL。-- 正确带条件的原子扣减 UPDATE inventory SET quantity quantity - #{qty} WHERE product_id #{productId} AND quantity #{qty};这条 SQL 执行后返回受影响行数。如果返回 1说明扣减成功返回 0说明库存不够或者商品不存在。Java 里拿到这个返回值做判断比先SELECT再UPDATE可靠得多。这是整个收银流程里最不能省的一个细节。3.3 金额计算统一用 BigDecimal前面建表用了DECIMALJava 侧就必须用BigDecimal对应。用double做金额运算0.1 加 0.2 会得到 0.30000000000000004收银时找零就会出错。// 正确写法字符串构造指定精度和舍入方式 BigDecimal price new BigDecimal(12.50); BigDecimal qty new BigDecimal(3); BigDecimal subtotal price.multiply(qty) .setScale(2, RoundingMode.HALF_UP); // 错误写法double 参与运算 double bad 12.50 * 3; // 看似没问题但累加多件后误差会显现setScale(2, RoundingMode.HALF_UP)表示保留两位小数、四舍五入。所有涉及金额的加减乘除都要走这一步尤其是折扣计算比如金卡打 8.8 折乘完必须重新setScale否则会出现 0.005 这种无法支付的小数。4. 详细文档怎么写才有人看四类文档的落地模板4.1 数据库设计文档的必备字段表很多人写的数据库文档就是一张截图接手的人根本不知道每个字段为什么这么设计。我的习惯是用表格把「字段名、类型、是否为空、默认值、说明」五列写全说明列里写清楚业务含义而不是重复字段名。字段名类型允许空默认值说明order_noVARCHAR(32)否无业务单号格式 yyyyMMdd6位序列对外展示用total_amountDECIMAL(10,2)否无应收金额等于所有明细 subtotal 之和pay_amountDECIMAL(10,2)否无实收金额现金支付时可能大于应收change_amountDECIMAL(10,2)否0找零等于实收减应收statusTINYINT否11已完成 2已退货退货后库存回滚这张表放在文档开头后面再配一张 ER 关系说明接手的人五分钟就能看懂数据模型。4.2 接口文档要写清入参出参和异常码接口文档不是把方法名抄一遍。每个接口要写清楚请求参数、返回结构、可能抛出的业务异常码。比如收银接口要写明库存不足时返回什么错误码前端好做提示。接口POST /api/checkout 入参 items: [{productId: long, quantity: int}] cashierId: long payType: int (1现金 2扫码 3会员余额) 返回 { code: 0, data: { orderNo: 20250101000001, total: 35.50, change: 4.50 } } 异常码 1001 库存不足 1002 会员余额不足 1003 收银员无权限异常码要集中定义在一个常量类里前后端共用避免出现「后端说库存不足前端显示未知错误」这种玄学问题。4.3 部署文档要写清 JDK 版本和建库顺序部署文档最容易漏的是环境依赖。要写明 JDK 版本、MySQL 版本、字符集要求以及建库建表的执行顺序。因为订单表有外键指向商品表建表顺序错了会直接报错。# 建库 mysql -u root -p -e CREATE DATABASE supermarket DEFAULT CHARSET utf8mb4; # 按依赖顺序执行建表脚本 mysql -u root -p supermarket sql/01_product.sql mysql -u root -p supermarket sql/02_inventory.sql mysql -u root -p supermarket sql/03_member.sql mysql -u root -p supermarket sql/04_cashier.sql mysql -u root -p supermarket sql/05_orders.sql mysql -u root -p supermarket sql/06_order_item.sql # 导入初始数据 mysql -u root -p supermarket sql/99_init_data.sql脚本按编号命名执行顺序一目了然。99_init_data.sql放测试商品和默认收银员账号方便部署完直接跑通。4.4 测试用例文档要覆盖边界场景测试文档不用写几百条但边界场景必须覆盖库存刚好等于购买数量、库存差一件、会员余额刚好够、余额差一分、同一商品重复扫码、退货后再次退货。这些场景写清楚预期结果测试的人照着点就行。5. 避坑与排查收银系统最容易翻车的五个地方5.1 库存扣成负数现象两个收银台同时卖最后一件商品库存变成 -1。 原因先查后扣两步之间没有锁。 解决把判断和扣减合并成一条带quantity #{qty}条件的 UPDATE用返回的受影响行数判断是否成功。5.2 订单金额和明细对不上现象订单主表总额是 35.50明细加起来是 35.49。 原因明细小计各自四舍五入后再累加和先累加再四舍五入结果不同。 解决统一规则先按明细单价乘数量算出各自小计并setScale主表总额等于所有小计之和不要另算一遍。5.3 退货后库存没回滚现象退货成功订单状态变成已退货但库存数量没加回去。 原因退货逻辑只改了订单状态漏了库存回滚。 解决退货和收银一样要放在事务里先校验订单状态是否为已完成再回滚库存、退还会员余额、更新订单状态三步一起提交。5.4 中文商品名存进去变成问号现象商品名带中文存进数据库变成???。 原因连接串没指定字符集或者建表时用了latin1。 解决建表统一utf8mb4JDBC 连接串加useUnicodetruecharacterEncodingutf8两边都对齐。5.5 收银员密码明文存储现象数据库里能直接看到收银员密码。 原因注册时直接存了明文。 解决用 BCrypt 这类算法存哈希登录时用matches比对永远不存明文也不可逆。这个不是功能问题是底线问题。6. 进阶技巧用一条对账 SQL 验证系统是否可信系统跑起来之后怎么知道它算得对我一般会写一条对账 SQL把订单明细按商品汇总和库存变动做交叉验证。如果两边对不上说明某次扣减或回滚出了问题。-- 对账每个商品的累计售出数量 vs 库存初始值减当前值 SELECT p.id, p.name, IFNULL(SUM(oi.quantity), 0) AS sold_qty, (i.init_qty - i.quantity) AS should_sold_qty FROM product p JOIN inventory i ON i.product_id p.id LEFT JOIN order_item oi ON oi.product_id p.id LEFT JOIN orders o ON o.id oi.order_id AND o.status 1 GROUP BY p.id, p.name, i.init_qty, i.quantity HAVING sold_qty should_sold_qty;这条 SQL 的思路是已售数量应该等于初始库存减当前库存。init_qty是库存表里额外加的一个字段记录上架时的初始数量方便对账。如果查出来有行说明这个商品的库存流水和订单流水不一致需要人工排查。除了对账还有一个实用技巧是给关键操作加日志表。每次扣库存、退货、改价都往operation_log写一条记录操作人、时间、前后值。出问题时不用猜直接查日志。这个表不用建外键写入性能优先定期归档就行。我自己做这类系统最大的教训是不要等到功能全写完才去测并发。收银这种场景两个人同时结账是常态库存扣减的原子性必须一开始就做对后面再补会牵一发动全身。另一个习惯是每加一张表就同步更新文档别攒到最后一起写攒到最后一定写不全。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

SwingBench 2.6.1数据库压测实战:环境准备到参数调优

SwingBench 2.6.1数据库压测实战:环境准备到参数调优

简介:面向 Oracle 数据库负载生成与性能压测场景,swingbench 2.6 是可直接部署的完整发行包,适合 DBA、架构师及性能测试人员,可模拟真实业务压力,验证分区、压缩等特性,也可用于评估新硬件或存储系统的极限…

2026/10/9 18:08:43 阅读更多 →
Django进销存系统实战:从源码解析到跑通入库出库完整闭环

Django进销存系统实战:从源码解析到跑通入库出库完整闭环

简介:面向Python/Django学习者的一份完整项目源码,基于Django框架实现商品销售进销存管理,涵盖商品信息维护、采购入库、销售出库、库存预警等典型业务环节,适合作为期末大作业、课程设计或毕业设计的参考。压缩包共2000个文件&am…

2026/10/10 18:11:36 阅读更多 →
数据中心机房设计方案:从可用性等级到供配电制冷计算与落地避坑指南

数据中心机房设计方案:从可用性等级到供配电制冷计算与落地避坑指南

简介:这份《数据中心机房设计方案》文档面向机房建设从业者、弱电系统设计人员及备考相关认证的技术人员,提供一套按B级机房标准编写的完整设计模板,帮助解决机房规划中子系统繁多、规范依据分散、方案难以落地的问题。资源包共1个doc文件&am…

2026/10/10 20:48:29 阅读更多 →

最新新闻

Rust Web框架实测:Salvo与axum对比,24小时快速开发CRUD接口

Rust Web框架实测:Salvo与axum对比,24小时快速开发CRUD接口

如果你最近在 Rust 里挑 Web 框架,应该会经历一段很具体的纠结期:axum 文档最全、生态最大,actix-web 性能名声在外,Rocket 的宏写法接近魔法。我原来一直偏向 axum,直到上周接了个小需求,要三天内把一个内…

2026/10/10 20:57:40 阅读更多 →
Secure Boot状态不一致:固件启用但Linux显示禁用的原理与诊断

Secure Boot状态不一致:固件启用但Linux显示禁用的原理与诊断

1. 现象本身不是Bug,而是两套独立状态系统的自然结果你刚进BIOS/UEFI设置界面,一眼就看到Secure Boot选项旁边清清楚楚标着「已启用」——绿色对勾、高亮文字、甚至还有个锁形图标。你松了口气,重启进Linux系统,随手敲下mokutil -…

2026/10/10 20:57:40 阅读更多 →
学习型索引:用轻量神经网络替代B-Tree的原理与实践

学习型索引:用轻量神经网络替代B-Tree的原理与实践

1. 项目概述:当索引本身开始“学习”数据分布你有没有遇到过这样的场景:数据库查一个范围查询,明明只想要100条记录,B-Tree却要从根节点一路遍历到叶子页,反复做磁盘随机IO,最后发现90%的页读进来只是用来跳…

2026/10/10 20:57:40 阅读更多 →
Python实现配电网经济性与可靠性双目标协同优化规划

Python实现配电网经济性与可靠性双目标协同优化规划

搞配电网规划的朋友,应该都体会过经济性和可靠性"打架"的感觉。传统工作流里,这两个维度往往是串行处理:先按年费用最小去定线路和容量,再用N-1准则或可靠性导则去校核,不够就加设备、加大截面,来…

2026/10/10 20:57:40 阅读更多 →
机器学习课程设计:Python垃圾分类系统源码解析与实战避坑指南

机器学习课程设计:Python垃圾分类系统源码解析与实战避坑指南

简介:这份Python垃圾分类系统课程设计源码包,面向机器学习课程设计学生及垃圾分类入门开发者,提供一套从模型训练到界面演示的完整个人大作业方案。项目基于TensorFlow 2.3,核心包括MobileNet模型训练脚本、窗口端垃圾分类测试程序…

2026/10/10 20:57:40 阅读更多 →
共聚焦显微镜与激光共聚焦有什么区别?选型与实操全解析

共聚焦显微镜与激光共聚焦有什么区别?选型与实操全解析

直接抛一个问题:你实验室里那台写着“共聚焦显微镜”的仪器,和你师弟论文里写的“激光共聚焦显微镜”,到底是不是同一个东西?如果只是名称长了三个字,为什么采购单上价格能差出一倍?很多刚接触显微成像的同…

2026/10/10 20:56:40 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

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

2026/10/10 11:14:25 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

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

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

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

2026/10/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/10 5:23:50 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →