JSP企业电子投票系统源码部署与避坑指南
简介这是一套基于JSP技术栈开发的企业电子投票系统完整源码面向学习Java Web开发的学生与初级开发者可用于课程设计、毕业设计或JSP实战练习。系统分为普通用户与管理员两大模块普通用户可登录退出、对已开放主题投票并查看已公布结果管理员则能撤销或恢复主题、永久删除主题、公布或隐藏投票结果、编辑与发布新主题以及新增删除用户功能覆盖投票业务全流程。压缩包共64个文件约1003KB以37个jsp页面为核心辅以css样式、js脚本、xml配置、图片素材并附带sql数据库脚本、MDF与LDF数据库文件及一份系统论文文档便于快速部署与理解表结构。前台访问路径为/vote后台入口为/vote/admin/login.jsp配合Tomcat与JDK即可运行。目前已有391人学习下载适合需要完整JSP项目案例、数据库设计与论文参考的读者借鉴。1. 一个 JSP 投票系统为什么值得你花半小时拆开看如果你手头正好有一套 JSP 企业电子投票系统的源码包别急着双击解压然后丢进 Tomcat 就完事。我见过太多人拿到这类资源第一反应是“能不能跑起来”结果卡在 JDK 版本、数据库连接、Servlet 映射上折腾一下午连登录页都没见着。这套东西本质上是一个典型的 Java Web 三层架构小系统JSP 负责视图渲染Servlet 处理投票逻辑和会话控制JDBC 直连数据库做选票的增删改查。它解决的是“小范围、内网、轻量级”的投票需求——比如某公司内部评选优秀员工、某高校实验室做课题方向摸底不需要微服务不需要前后端分离一个 Tomcat 加一个 MySQL 就能撑住。适合谁适合正在学 JSPServlet 的学生、需要快速交付内部投票工具的开发者以及想拿一个完整 CRUD 项目练手的人。但前提是你得知道它怎么跑、参数怎么调、坑在哪。2. 环境搭建与数据库初始化从 JDK 到 Tomcat 的完整链路2.1 版本选型为什么 JDK 8 Tomcat 8.5 是这套源码的舒适区这套 JSP 投票系统源码里大概率用的是javax.servlet包而不是jakarta.servlet。这意味着如果你直接上 Tomcat 10 或 11启动就会报ClassNotFoundException因为 Tomcat 10 之后把 Servlet API 的包名从javax.*改成了jakarta.*。这不是玄学是实打实的包路径断裂。我一般会建议用 JDK 8 配合 Tomcat 8.5 或 9.0这两个版本对javax.servlet的支持最稳而且 JDK 8 的tools.jar在编译 JSP 时不会出幺蛾子。如果你只有 JDK 11 或 17也能跑但要在 Tomcat 的conf/web.xml里确认 JSP Servlet 的初始化参数没有硬编码旧版编译器路径。常见做法是先java -version看版本再echo %JAVA_HOME%Windows或echo $JAVA_HOMELinux/macOS确认环境变量指向的是 JDK 而不是 JRE。少了这一步后面 Tomcat 启动时可能连catalina.bat都执行不下去。2.2 数据库建表与连接池配置把db.properties改对源码包里通常有一个src/db.properties或WEB-INF/classes/db.properties里面写着数据库 URL、用户名、密码。很多人直接复制粘贴结果忘了改数据库名或者端口。我一般会先手动在 MySQL 里建一个空库字符集用utf8mb4排序规则utf8mb4_general_ci然后执行源码自带的.sql文件。如果源码没带 SQL 脚本就得根据实体类反推表结构。下面是一个典型的投票系统表结构初始化脚本我按常见字段补全了-- 创建数据库字符集必须支持中文选项 CREATE DATABASE vote_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE vote_system; -- 用户表存储管理员和普通投票者 CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, role VARCHAR(20) DEFAULT voter -- voter 或 admin ); -- 投票主题表 CREATE TABLE vote_topics ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(200) NOT NULL, description TEXT, start_time DATETIME, end_time DATETIME, status INT DEFAULT 1 -- 1 进行中0 已结束 ); -- 选项表 CREATE TABLE vote_options ( id INT PRIMARY KEY AUTO_INCREMENT, topic_id INT, option_text VARCHAR(200), vote_count INT DEFAULT 0, FOREIGN KEY (topic_id) REFERENCES vote_topics(id) ); -- 投票记录表防止同一用户重复投票 CREATE TABLE vote_records ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT, topic_id INT, option_id INT, vote_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY unique_vote (user_id, topic_id) );这段 SQL 的逻辑说明users表用role字段区分权限vote_records表上的UNIQUE KEY是防刷票的核心——同一个用户对同一个主题只能插一条记录。参数上vote_count我习惯用冗余字段而不是每次COUNT(*)因为投票结果页要频繁展示实时聚合在数据量上千时会有明显延迟。改完 SQL 后回到db.properties把jdbc.url改成jdbc:mysql://localhost:3306/vote_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai。注意serverTimezone必须加否则 MySQL 8 驱动会报时区错误这是血泪经验。2.3 部署到 Tomcat三种方式与目录结构确认把项目放进 Tomcat 有三种常见做法一是直接把整个项目文件夹复制到webapps/下二是打成 WAR 包丢进去三是在 IDE 里配 Tomcat 服务器。我一般推荐第二种因为 WAR 包部署最干净不会因为 IDE 的临时文件导致类加载冲突。操作步骤在项目根目录执行jar -cvf vote.war .注意最后有个点然后把vote.war复制到%TOMCAT_HOME%/webapps/启动 Tomcat它会自动解压。启动后看logs/catalina.out如果看到Server startup in xxx ms且没有SEVERE级别的日志基本就成了。访问地址通常是http://localhost:8080/vote/具体看web.xml里welcome-file-list配的首页是index.jsp还是login.jsp。如果 404先检查webapps/vote/下有没有WEB-INF/web.xml再检查server.xml里的appBase有没有被改过。3. 核心模块拆解投票逻辑、会话控制与防刷票实现3.1 投票 Servlet 的请求处理链路投票动作通常由一个VoteServlet处理doPost方法里先拿HttpSession里的userId再从请求参数里取topicId和optionId。核心逻辑是先查vote_records看该用户是否已投过没投过就开事务往vote_records插一条同时UPDATE vote_options SET vote_count vote_count 1 WHERE id ?。这两步必须在一个事务里否则并发下会出现“记录插了但票数没加”或者反过来。下面是一个简化后的代码片段// 投票核心逻辑注意事务边界 Connection conn null; PreparedStatement psCheck null; PreparedStatement psInsert null; PreparedStatement psUpdate null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 关闭自动提交手动控制事务 // 1. 检查是否已投票 String checkSql SELECT id FROM vote_records WHERE user_id? AND topic_id?; psCheck conn.prepareStatement(checkSql); psCheck.setInt(1, userId); psCheck.setInt(2, topicId); ResultSet rs psCheck.executeQuery(); if (rs.next()) { conn.rollback(); response.getWriter().write(already_voted); return; } // 2. 插入投票记录 String insertSql INSERT INTO vote_records(user_id, topic_id, option_id) VALUES(?,?,?); psInsert conn.prepareStatement(insertSql); psInsert.setInt(1, userId); psInsert.setInt(2, topicId); psInsert.setInt(3, optionId); psInsert.executeUpdate(); // 3. 更新选项票数 String updateSql UPDATE vote_options SET vote_count vote_count 1 WHERE id?; psUpdate conn.prepareStatement(updateSql); psUpdate.setInt(1, optionId); psUpdate.executeUpdate(); conn.commit(); // 三步都成功才提交 } catch (Exception e) { if (conn ! null) conn.rollback(); e.printStackTrace(); } finally { DBUtil.close(conn, psCheck, null); DBUtil.close(null, psInsert, null); DBUtil.close(null, psUpdate, null); }逻辑说明setAutoCommit(false)是事务的起点commit()之前任何一步抛异常都会走rollback()。参数上userId从 session 取而不是从表单隐藏域取这是防止伪造投票的关键——隐藏域可以被篡改session 不行。DBUtil是常见的 JDBC 工具类负责从连接池拿连接和关闭资源。如果你发现投票后票数没变先看catalina.out里有没有SQLException再确认 MySQL 的存储引擎是不是 InnoDBMyISAM 不支持事务回滚会失效。3.2 Session 与权限过滤器的配合登录成功后通常会把user对象塞进session.setAttribute(user, user)。然后用一个AuthFilter拦截/admin/*路径检查 session 里有没有user且role是不是admin。过滤器的doFilter方法里如果校验不通过就response.sendRedirect(login.jsp)。这里有个容易翻车的点过滤器里用request.getRequestURI()拿到的路径包含项目名比如/vote/admin/list.jsp如果你直接startsWith(/admin)会匹配失败。正确做法是String path request.getRequestURI().substring(request.getContextPath().length());再去判断。这个细节在源码里如果没处理好就会出现“明明登录了却一直被踢回登录页”的玄学现象。3.3 结果展示页的分页与排序投票结果页一般用 JSP 脚本片段或者 JSTL 遍历ListOption。如果选项超过 20 个建议加分页否则页面加载会拖慢。常见做法是在 Servlet 里用LIMIT ?, ?做物理分页pageSize设 10 或 15offset (pageNum - 1) * pageSize。排序按vote_count DESC这样票数最高的选项排最前。注意 MySQL 的LIMIT在数据量很大时深分页会慢但投票系统通常选项不会过百所以不用上WHERE id ?那种优化。JSP 页面里用c:forEach遍历时记得在web.xml或页面顶部声明 JSTL 标签库否则c:forEach会被当成普通文本输出页面直接乱掉。4. 避坑与排查那些让你怀疑人生的报错4.1 中文乱码从请求参数到数据库的全链路排查现象投票选项里写中文提交后数据库里显示???或者页面回显乱码。原因通常有三层第一层是 JSP 页面顶部没写% page contentTypetext/html;charsetUTF-8 languagejava %第二层是 Servlet 里没设request.setCharacterEncoding(UTF-8)注意这行必须在getParameter之前调用第三层是数据库连接 URL 里没加characterEncodingutf8。解决顺序先改 JSP 的pageEncoding再在 Servlet 的doPost第一行加编码设置最后检查db.properties的 URL。如果用的是 Tomcat 8 以上GET请求的中文乱码还要去server.xml的Connector标签里加URIEncodingUTF-8。4.2 数据库连接池耗尽wait_timeout与连接泄漏现象系统跑一段时间后投票请求全部卡死日志里出现Communications link failure或Too many connections。原因多半是 JDBC 连接没关或者 MySQL 的wait_timeout默认 8 小时连接池里的空闲连接被服务端断开了但客户端不知道。解决一是在DBUtil.close里确保ResultSet、PreparedStatement、Connection都按顺序关闭二是在连接 URL 里加autoReconnecttrue但这不是银弹更好的做法是配一个连接池比如 Druid 或 HikariCP并设置validationQuery为SELECT 1。如果源码里用的是裸 JDBC至少把wait_timeout调大或者加一个定时心跳。4.3 重复投票绕过前端校验靠不住现象明明在 JSP 里用 JavaScript 禁用了已投过的按钮但换个浏览器或者直接构造 POST 请求还是能投进去。原因前端校验只是用户体验真正的防线在vote_records表的唯一索引和 Servlet 里的事务检查。解决确保数据库唯一索引存在并且 Servlet 里先查后插的逻辑在事务内执行。如果并发极高还要考虑用INSERT ... ON DUPLICATE KEY UPDATE或者加行锁。我一般会在vote_records上再加一个UNIQUE KEY (user_id, topic_id)这样即使 Servlet 逻辑有漏洞数据库层也能兜底。4.4 Tomcat 启动报ClassNotFoundException: com.mysql.jdbc.Driver现象Tomcat 启动时日志里刷一堆ClassNotFoundException指向 MySQL 驱动。原因MySQL 驱动 jar 包没放进WEB-INF/lib目录或者放的是新版的com.mysql.cj.jdbc.Driver但代码里写的是旧版类名。解决先确认WEB-INF/lib/下有mysql-connector-java-x.x.x.jar然后看db.properties里的driver配置。MySQL 5.x 用com.mysql.jdbc.DriverMySQL 8.x 用com.mysql.cj.jdbc.Driver。如果版本对不上要么换 jar 包要么改配置。注意驱动 jar 不能只放在 Tomcat 的lib/下因为项目类加载器可能优先从WEB-INF/lib找放错了位置照样报错。4.5 JSP 编译报Unable to compile class for JSP现象访问某个 JSP 页面时抛出 500日志里说Unable to compile class for JSP后面跟着一堆cannot find symbol。原因JSP 里用了某个类但没import或者% page import... %写错了包名。解决看日志里具体是哪个符号找不到然后检查 JSP 顶部的 import 列表。另一个常见原因是 JDK 版本和 Tomcat 的 JSP 编译器不匹配比如用 JDK 17 跑 Tomcat 8.5需要在conf/web.xml里把compilerSourceVM和compilerTargetVM改成1.8。这个坑我踩过不止一次改完重启立刻见效。5. 进阶技巧把投票结果导出成 Excel 与并发压测5.1 用 Apache POI 导出投票结果投票结束后管理员通常需要一份 Excel 报表。源码里如果没带导出功能可以自己加一个ExportServlet用 Apache POI 的XSSFWorkbook生成.xlsx。核心步骤从数据库查vote_options按vote_count降序创建Sheet第一行写表头然后循环写数据行最后workbook.write(response.getOutputStream())。注意响应头要设Content-Disposition: attachment; filenameresult.xlsx并且response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)。POI 的 jar 包需要poi、poi-ooxml、poi-ooxml-schemas和xmlbeans四个少一个都会报NoClassDefFoundError。下面是一个最小可用片段// 导出投票结果到 Excel XSSFWorkbook workbook new XSSFWorkbook(); Sheet sheet workbook.createSheet(投票结果); Row header sheet.createRow(0); header.createCell(0).setCellValue(选项); header.createCell(1).setCellValue(票数); ListOption options optionDao.findAllOrderByCountDesc(); int rowNum 1; for (Option opt : options) { Row row sheet.createRow(rowNum); row.createCell(0).setCellValue(opt.getOptionText()); row.createCell(1).setCellValue(opt.getVoteCount()); } response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setHeader(Content-Disposition, attachment; filenamevote_result.xlsx); workbook.write(response.getOutputStream()); workbook.close();参数说明optionDao.findAllOrderByCountDesc()是自定义的 DAO 方法SQL 是SELECT * FROM vote_options WHERE topic_id? ORDER BY vote_count DESC。rowNum从 1 开始是因为第 0 行被表头占了。如果选项名有中文确保response的字符编码在getOutputStream()之前设好否则 Excel 里会乱码。5.2 用 JMeter 做一轮并发投票压测想知道这套系统能扛多少人同时投票可以用 JMeter 建一个线程组线程数设 100Ramp-Up 设 10 秒循环 1 次。然后加一个 HTTP 请求路径指向/vote/voteServlet方法 POST参数带上topicId和optionId。关键是要加一个HTTP Cookie 管理器因为投票依赖 session没有 cookie 的话每次请求都是新会话防刷票逻辑直接失效。跑完后看聚合报告里的Throughput和99% Line。如果错误率超过 1%先看数据库连接池够不够再看 Tomcat 的maxThreads是不是默认的 200。我一般会把maxThreads调到 500acceptCount调到 100然后 MySQL 的max_connections至少设 200。压测完记得把数据清掉否则vote_records表里全是脏数据。5.3 一个让我长记性的习惯从那以后我每次拿到这种 JSP 源码包都强制走一遍“版本核对 → 数据库建表 → 连接串检查 → 日志盯启动 → 单点投票验证 → 并发压测”的流程少一步都可能在后头翻车。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

声纹识别技术全解析:原理、模型选型与工程落地避坑指南

声纹识别技术全解析:原理、模型选型与工程落地避坑指南

声纹识别这技术,说简单点就是让机器听声辨人。身边很多人第一次听说,以为和语音识别是一回事,其实两者差别非常大:语音识别是听“你在说什么”,声纹识别是听“你是谁”。就像你接电话,对方一喊“喂”&#…

2026/10/17 12:21:47 阅读更多 →
DFS、爬山法、束搜索:工业级搜索策略选型与避坑指南

DFS、爬山法、束搜索:工业级搜索策略选型与避坑指南

1. 这不是算法课件,而是一套可落地的问题求解思维工具箱“lecture 4:Search:Depth-First, Hill Climbing, Beam”——光看这个标题,很多人第一反应是:哦,又是某门人工智能导论课的第四讲PPT。但在我带过十几期算法实践…

2026/10/17 12:21:47 阅读更多 →
微信小程序加载外部3D模型:Three.js适配与GLTFLoader实战

微信小程序加载外部3D模型:Three.js适配与GLTFLoader实战

简介:这份资源面向希望在微信小程序中实现3D可视化效果的开发者,尤其是具备一定JavaScript基础、想借助three.js突破小程序渲染限制的前端与小程序工程师。它围绕「加载外部3D模型」这一核心问题,提供可运行的工程示例,帮助读者理…

2026/10/17 12:20:47 阅读更多 →

最新新闻

codex针对java+vue的Prompt提示词:用TaoToken统一Key跑通前后端联调

codex针对java+vue的Prompt提示词:用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/17 15:00:39 阅读更多 →
Oracle 11g 升级 19C 实战避坑:DBUA 报错、RMAN 恢复与时区版本全解析

Oracle 11g 升级 19C 实战避坑:DBUA 报错、RMAN 恢复与时区版本全解析

简介:这份Oracle 11g到19C数据库升级详尽指导手册,面向具备一定运维能力的数据库管理员(DBA)及运维工程师,聚焦利用DBUA工具将11g单机数据库安全迁移至19C的完整流程。内容涵盖前期备份与恢复、升级路线选择、环境说明…

2026/10/17 15:00:39 阅读更多 →
ZooKeeper节点类型详解:持久、临时、顺序节点的原理与实战避坑

ZooKeeper节点类型详解:持久、临时、顺序节点的原理与实战避坑

我这几年在分布式系统上踩的坑,有一大半都跟ZooKeeper的节点类型有关。不管是做分布式锁、服务注册发现,还是元数据存储,选错了节点类型,轻则功能异常,重则线上事故。今天就把这四种节点的特点、原理和使用场景彻底讲透…

2026/10/17 15:00:39 阅读更多 →
好写作AI:期刊论文选题到投稿全流程实操指南

好写作AI:期刊论文选题到投稿全流程实操指南

凌晨三点,对着屏幕上那块光标闪了一晚上的空白文档,手边的咖啡已经第三杯了。讲实话,这种场景在科研生活里太常见了:Introduction写不出逻辑链、文献综述堆了几十篇却不知道从哪句话开始、明明实验数据都齐了结果讨论部分憋不出来…

2026/10/17 15:00:39 阅读更多 →
Spring Boot内嵌Tomcat启动链路:原理、定制与避坑实战

Spring Boot内嵌Tomcat启动链路:原理、定制与避坑实战

简介:《Spring Boot启动过程(四)之内嵌Tomcat启动》是一份面向中高级Spring Boot开发者的PDF解析文档,帮助厘清启动阶段内嵌Web容器的创建、配置与初始化链路。文档以源码调用顺序为主线,先解释createEmbeddedServletC…

2026/10/17 15:00:39 阅读更多 →
分布式计算与并行计算区别详解:选型与实战指南

分布式计算与并行计算区别详解:选型与实战指南

我一直觉得,很多人一听到“分布式计算”和“并行计算”,第一反应是“这不差不多嘛,都是把任务拆开同时算”。实际上这两个概念在大数据处理里的定位差异非常大,用错场景轻则性能没提升,重则整套架构白搭。这篇文章我就…

2026/10/17 14:59:38 阅读更多 →

日新闻

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 阅读更多 →