尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
基于JSP的社区用电服务管理系统毕业设计全解析
又到了毕业设计选题的季节这类题目年年都会出现基于JSP的社区用电服务管理系统。我自己当年做毕设时选的就是这类Java Web管理系统后来也帮不少学弟学妹看过相似题目。很多人一看“JSP”三个字母就开始犹豫觉得技术太老担心论文和答辩都没面子。但我的看法恰恰相反JSP加Servlet这套经典Java Web组合是做管理类毕设最稳的选择。这篇文章就围绕“社区用电服务管理系统”这个题目把需求分析、数据库设计、核心代码实现、常见坑点、打包部署整个流程原原本本铺开帮你把这个项目彻底吃透顺带也能回答一部分“基于jsp的毕设选题”该怎么下手的问题。1. 从选题到落地这个毕业设计到底在做什么1.1 需求背景为什么社区用电需要一套管理系统社区用电服务管理拆开看其实特别直白一个小区里住着几百上千户居民每户都有电表每个月要有专人查表、算电费、通知缴费用户遇到电表异常、线路故障要上报维修物业或管理方还要不定期发布停电通知和用电政策公告。这个闭环如果全靠Excel表格加微信群效率非常低而且特别容易出岔子——单子漏录了、电费算错了、报修没人跟进都是日常操作。毕设里的“社区用电服务管理系统”核心就是把上面这套手动流程搬上Web管理员在后台录入电表读数、生成账单、发布公告、处理报修居民用户登录之后查看自己的用电量、账单明细、缴费记录还能在线提交报修诉求。本质上这是一个典型的管理信息系统覆盖了数据采集、业务处理、服务响应三条主线麻雀虽小五脏俱全。对计算机专业的学生来说这个题目最难得的地方在于它既有明确的管理对象又有完整的数据流转过程不用像做商城项目那样硬编造一个“买买买”的需求出来。一个能跑通全流程的社区用电系统放在毕业设计里其实属于“小而完整”的典型样本规模不大但该有的技术点都有该踩的坑也一个不少。这也是我后来帮人改代码时反复看到的结论——愿意把这个题目好好做完的人毕业设计这一关基本都过得很轻松。1.2 我的选题理由与整体技术选型思路选题这一步我要说点实在话。很多同学看到“JSP”三个字母第一反应是“这都什么年代了JSP早过时了”。但毕业设计考察的从来不是技术新旧而是你能不能把系统完整地做出来、讲清楚。JSP Servlet JavaBean 这套组合恰好能把 Web 开发的完整主链路摊开在你面前浏览器发起请求、Servlet接收处理、JavaBean承载业务逻辑、JDBC读写MySQL、数据回填到JSP页面渲染输出。整个流程没有黑盒做完一遍你对 Java Web 的认知会是立体的而不是“调API调出来的”那种感觉。我当时的技术栈是JSP Servlet JavaBean MySQL 8.0 Tomcat 9页面端用Bootstrap做基础布局循环输出统一走JSTL和EL表达式。选这套组合有两个理由。第一JSP动态页面表现力足够特别适合这种页面数量较多的管理类系统用户信息展示页、账单列表页、报修表单页都是它的主战场。第二答辩时老师最爱问“页面和服务端怎么交互”“Session和Request什么区别”这类基础问题用JSP项目来答每个环节都有真实代码支撑不会慌。还有一个现实因素这种JSP项目前端要求极低基本用Bootstrap套一套模板就能把界面撑起来不需要学React、Vue那套构建流程。对Java基础还不牢固、又想保住毕业设计的同学来说这反而是最大的优势。项目周期大概安排三到四周第一周搞需求分析和数据库第二周写登录和用户模块第三周攻抄表、账单、缴费这条主链路最后一周补报修、公告、测试和文档节奏是非常明确的。2. 需求拆分与模块设计两类角色六条业务链2.1 角色权限设计管理员与居民用户系统整体分成两类角色管理员和普通居民用户。管理员的职责写在四个字上——“管”维护用户信息、管理电表档案、录入每月抄表数据、生成并发布电费账单、处理居民提交的报修单、发布公告通知。普通居民用户的核心是“用”注册登录、查看个人信息、查询历史和当前用电量、查看电费账单、在线模拟缴费、提交报修并跟踪进度。权限设计的落点在登录认证和角色拦截。我的做法是登录成功后把用户对象放进Session再写一个自定义Filter在每次请求时做登录检查根据请求路径判断当前用户的角色是否允许访问。比如所有以/admin开头的页面只接受 roleadmin 的用户普通用户直接访问就返回403或重定向回登录页。这部分逻辑的细节我会在后面第四章专门展开。这里有一个值得提前想清楚的问题管理员和居民到底算一张表还是两张表我的答案是一张表再加role字段。原因很简单登录逻辑可以统一写一次用户管理模块也只要维护一套增删改查省掉大量重复代码。有的同学喜欢把两张表拆开认为更符合“面向对象直觉”但结果是登录时要先判断走哪张表管理员也要维护居民账号反而绕了一圈。2.2 核心业务模块拆解按功能我给系统拆成了六个模块每一块对应一组页面和一组Servlet处理逻辑用户模块注册、登录、个人信息修改、密码修改。电表管理模块管理员维护电表档案包括电表编号、安装位置、所属用户。抄表与用电模块管理员按月录入电表读数系统自动计算当月用电量。账单与缴费模块根据用电量乘以单价生成账单用户查看账单并模拟缴费。报修服务模块用户提交报修管理员接单、处理、结单。公告模块管理员发布公告居民登录首页即可看到最新通知。这些模块单独看都不复杂但组合起来就是一条完整的业务链从电表档案到抄表读表到账单生成再到缴费和报修每个页面都有明确的数据来源每个Servlet都有明确的任务。做页面时也不会有“这块数据不知道从哪来、要显示到哪去”的迷茫感。模块拆分还有个隐藏好处答辩的时候你可以直接按“业务链模块”的方式介绍系统老师一听就知道你是真的设计过而不是把网上Demo改个标题就交上来。我建议你也按这个思路整理一份模块清单提前写在答辩PPT里。在页面规划上居民端建议围绕“个人信息”做聚合展示把手机号、地址、角色信息集中在一个页面管理员端则建议做一个首页统计面板展示待处理报修数、本月总用电量、未缴费账单数这几个核心数字。这些内容都属于锦上添花但能明显提升整体完成度。3. 数据库设计与表结构7张表怎么关联最合理3.1 数据库设计要点表、字段、冗余与精度先把结论放前面这个系统的表数量控制在7张左右就能把核心业务全部跑通。表一多容易把自己绕晕表太少又会造成逻辑耦合。我最终的库设计如下表名用途关键字段user用户表管理员居民id, username, password, role, name, phone, addressmeter电表档案表id, meter_no, user_id, address, install_date, statusreading抄表记录表id, meter_id, record_month, old_num, new_num, usage_kwhbill电费账单表id, user_id, bill_month, usage_kwh, unit_price, total_amount, statuspayment缴费记录表id, bill_id, user_id, pay_amount, pay_timerepair报修工单表id, user_id, device_type, fault_desc, status, create_time, handle_timeannouncement公告表id, title, content, create_time设计上有几个点值得特别注意。首先user表用role字段区分管理员和居民登录逻辑统一在一块减轻工作量。其次reading表保存每个月的“抄见数”当月用电量等于本月新读数减去上月旧读数这个差值在录入时就计算好冗余存入usage_kwh字段。这样生成账单时直接读取SQL简单也避免临时算错。第三bill表的status字段只有两个值0未缴费、1已缴费缴费完成后由payment表记录实际流水两表用bill_id关联。还有精度问题涉及钱和电量的字段一律用DECIMAL而不是FLOAT或DOUBLE。很多同学做项目时图省事把金额存成double结果算出来一堆0.30000000000000004这种怪数字答辩时被老师当场指出特别尴尬。数据库字段精度定好了Java端配合BigDecimal浮点误差问题就能从源头杜绝。3.2 关键表结构与关联关系下面贴两张核心表的建表SQL可以直接拿来改。第一张是用户表CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(64) NOT NULL, role VARCHAR(20) DEFAULT user, real_name VARCHAR(50), phone VARCHAR(20), address VARCHAR(200), create_time DATETIME DEFAULT CURRENT_TIMESTAMP );第二张是账单表也是业务核心CREATE TABLE bill ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, bill_month VARCHAR(7) NOT NULL, usage_kwh DECIMAL(10,2) DEFAULT 0.00, unit_price DECIMAL(6,4) DEFAULT 0.5200, total_amount DECIMAL(10,2) GENERATED ALWAYS AS (usage_kwh * unit_price) STORED, status TINYINT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES user(id) );这里有实用技巧total_amount用MySQL的生成列只要usage_kwh和unit_price写入总金额自动算好省一层Java代码出错的可能。如果不想用生成列也可以在Service层用BigDecimal手动计算再写入效果一样。各表关联关系简单过一遍user是主表meter.user_id指向user主键记录“这台电表归谁”reading.meter_id指向meter主键记录“这台电表每个月查了几度”bill.user_id直接指向user主键查询用户账单时不必多联一张电表表payment和repair表也都以user_id作为业务归属。announcement表相对独立不参与外键关联因为公告和业务没有直接绑定关系硬加外键反而增加维护负担。4. JSP核心功能实现EL、Filter拦截与电费计算4.1 JSP页面开发EL表达式和JSTL替代Java脚本很多初学者写JSP最顺手的就是% %脚本段但一个项目里如果到处都是脚本段页面会非常难维护老师也容易给“分层不清晰”的评价。我的建议是Servlet先把数据封装成对象放到request里页面只用EL表达式和JSTL标签渲染。比如普通用户查看本月账单核心代码可以长这样% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % c:forEach items${billList} varbill tr td${bill.billMonth}/td td${bill.usageKwh}/td td${bill.unitPrice}/td td${bill.totalAmount}/td td c:if test${bill.status 0}未缴费/c:if c:if test${bill.status 1}已缴费/c:if /td /tr /c:forEach要让这段代码正常工作项目里必须导入jstl-1.2.jar和standard.jar这两个依赖否则使用c标签时页面直接报错。除此之外每个JSP页面顶部都建议加上% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8%这句既是乱码预防也是页面规范。EL表达式还有个常被忽略的坑Servlet往request里放的属性名如果带大小写EL访问时要完全一致。比如放的是billList页面写${billList}没问题一旦某处手滑写成${billlist}大概率拿不到值页面显示一个空白。建议项目里统一属性命名规则别今天驼峰明天下划线给自己留着排查线索。4.2 登录认证与权限拦截Session和Filter的配合方式登录逻辑本身不复杂查库比对用户名密码通过后把用户对象放进Session。真正麻烦的是“每个请求都要校验登录状态不同角色只能访问不同页面”。如果每个Servlet里都手写判断代码会大量重复而且很容易漏判。正确做法是写一个Filter统一拦截请求核心逻辑如下public class LoginFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; HttpSession session request.getSession(false); Object loginUser session null ? null : session.getAttribute(loginUser); String uri request.getRequestURI(); String contextPath request.getContextPath(); String target uri.substring(contextPath.length()); // 放行白名单登录页、登录接口、注册接口、静态资源 if (target.startsWith(/login) || target.startsWith(/register) || target.startsWith(/static) || target.endsWith(.css) || target.endsWith(.js)) { chain.doFilter(req, resp); return; } if (loginUser null) { response.sendRedirect(contextPath /login.jsp); return; } // 角色判断进入admin路径必须管理员 if (target.startsWith(/admin) !admin.equals(((User) loginUser).getRole())) { response.sendError(HttpServletResponse.SC_FORBIDDEN); return; } chain.doFilter(req, resp); } }这段代码我直接搬到项目里就能用。提醒一个细节session判空这步千万别省否则用户第一次访问没有session时直接调用session.getAttribute()会抛NullPointerException。Filter写好后后续每个Servlet都不用再管“用户有没有登录”只管自己的业务重复代码量会大幅下降。在web.xml里注册Filter时url-pattern建议写/*让它覆盖所有请求。有些同学只写了/admin/*结果普通用户的页面漏洞百出各种“未登录也能打开详情页”的问题都是拦截范围没覆盖导致的。4.3 用电费用计算与展示从抄表到账单电费计算是整个系统业务味道最浓的地方。我的实现思路管理员在抄表页面选择月份录入某个电表的新读数程序自动查上一次抄表记录里的旧读数算出差值得到当月用电量然后把用电量、单价、总金额写入该用户的当月账单。计算精度是重点。用法usage_kwh用DECIMAL(10,2)unit_price用DECIMAL(6,4)Java端不要用double相乘再转回BigDecimal精度会丢。正确写法BigDecimal usage new BigDecimal(213.50); BigDecimal price new BigDecimal(0.5200); BigDecimal total usage.multiply(price).setScale(2, RoundingMode.HALF_UP);如果要支持阶梯电价写一个分段累加函数就行。比如200度以内0.52元/度超过200度的部分按0.80元/度算法类似个税累进先用if判断落在哪个梯度再拆段计算。逻辑不复杂但答辩时讲清楚能加分。页面展示上居民端有一个“我的账单”列表按月份倒序已缴费的显示灰色状态未缴费的旁边放一个“去缴费”按钮。缴费流程做成模拟支付即可用户点击缴费系统创建一条payment记录同时把对应bill的status置为1不接真实支付接口。数据库事务上这两步操作应该放在一个事务里要么都成功要么都失败避免出现“钱交了但账单还是未缴费”的不一致。5. 开发中的经典坑环境、乱码和JDBC连接5.1 环境配置从IDEA新建JSP项目到Tomcat网上搜“idea新建jsp项目”的人非常多说明这步就卡住了不少人。我推荐直接用IDEA创建Java Enterprise项目选Web Application模板不要自己在普通Java项目里硬凑web目录那样容易漏结构。项目创建后先确认有webapp/WEB-INF/web.xml这个标准结构再配置TomcatRun/Debug Configurations里选Tomcat Server—LocalDeployment里把项目的war exploded artifact加上即可。启动后浏览器404九成是访问路径问题。IDEA默认的部署名是工程名建议改成简短英文名不带中文和空格。比如部署名是jspElectricity访问路径就是http://localhost:8080/jspElectricity/。少了这层工程名直接404新人最容易在这个地方卡住。还有Tomcat和JDK的版本匹配。JSP项目如果本地JDK是8Tomcat用8.5或9比较稳如果装了Java17Tomcat9勉强能跑但Tomcat7这种老版本直接启动失败。装环境之前先看一眼自己JDK版本别下了个不兼容的Tomcat白折腾半小时。顺带一提网上有人搜“springboot2 集成jsp 目录”那属于另一个方向毕设里没必要绕这个弯直接用传统Tomcat项目结构更顺畅。5.2 中文乱码三个处理点缺一不可JSP中文乱码是经典问题表现形式百出页面显示问号、数据库存进去乱码、请求参数变成%3F。根据我的经验三个处理点缺一个都可能出乱码。第一所有JSP页面顶部统一加% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8%。第二写一个编码过滤器在请求进入Servlet之前调用request.setCharacterEncoding(UTF-8)注意这个必须在第一次调用getParameter()之前执行所以要放在Filter的doFilter最前面。第三数据库连接串要带编码参数String url jdbc:mysql://localhost:3306/electricity_system?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/Shanghai;还有一点容易被忽略MySQL建库时要指定默认字符集。建库SQL后面加DEFAULT CHARSETutf8mb4否则插入中文直接变问号。如果库已经建错了可以用ALTER DATABASE xxx CHARACTER SET utf8mb4;补救表也要同步转换。这些设定看着琐碎但一个环境不对后面所有页面都会带着乱码问题排查起来比写功能还费时间。5.3 JDBC数据访问连接管理与PreparedStatementJDBC写DAO的时候最容易踩的坑是重复连接数据库和忘记关资源。我建议写一个DBUtil工具类用静态代码块加载驱动封装getConnection()方法读取数据用try-with-resources自动关闭结果集、Statement和连接。这一步看起来不起眼但能避免大量“连接过多导致服务挂掉”的问题。另一个更关键的习惯所有SQL都走PreparedStatement严禁字符串拼接。登录查询如果写成SELECT * FROM user WHERE username username AND password password 用户输入一个 OR 11就把系统直接打穿。正确写法String sql SELECT * FROM user WHERE username? AND password?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, username); ps.setString(2, md5Password);密码存储也要提一句不要明文存密码建议MD5加盐后再存。答辩时老师问“你的系统安全性怎么保证”你能说出PreparedStatement防注入、密码加密存储这两点至少证明你有安全意识而不是只会写业务功能的搬砖工。6. 测试、打包与答辩把项目完整收尾6.1 功能测试要点全链路跑通和边界数据项目做完一定要站在用户视角走一遍全流程测试。我整理了一张测试主线表照着走基本能把主要bug排干净测试场景操作步骤预期结果注册访问注册页填写信息提交跳转登录页数据库新增用户登录输入正确密码跳转首页Session写入用户登录拦截未登录直接访问用户中心被重定向到登录页抄表管理员录入本月新读数用电量正确计算账单生成管理员推送某月账单用户端显示新账单金额正确缴费居民点击缴费账单状态变为已缴费生成payment记录报修居民提交报修管理员处理状态流转待处理到已处理到已结单权限校验普通用户直接访问/admin返回403或被拦截建议把这条主线跑两遍一遍正常数据一遍边界数据。边界数据比如用电量为0、单价为0、密码全空、超大数值最容易暴露页面展示层的异常。页面上的空指针异常绝大多数都是在这种“临界情况”下冒出来的。测试不只是盯着页面看还要学会看后端日志。IDEA控制台里的Exception堆栈对应到具体是哪个Servlet、哪一行代码能精准定位问题。很多同学调试时只会用System.out.println遇到空指针就懵了其实把堆栈日志从头看到尾技术点熟悉以后排查速度会快很多。6.2 打包部署WAR包的生成与上线“传统jsp项目打包war”是很多同学临近提交才搜的关键词因为平时IDEA开发都是WAR exploded直接跑根本不接触最终部署包。在IDEA里操作不复杂打开Project Structure选Artifacts新建Web Application Archive然后Build → Build Artifactout目录下就会生成一个.war文件。把这个war放进Tomcat的webapps目录启动Tomcat后会自动解压部署。部署时要注意两件事。第一war包名就是访问路径比如jspElectricity.war打成后访问地址是http://localhost:8080/jspElectricity/。第二部署前检查数据库连接串把地址、用户名、密码改成目标机器的MySQL配置并且提前建好库和表。很多同学打包完部署起来连不上数据库十有八九是连接串写死成开发环境地址换台电脑就废了。顺便回答一个经常被搜到的问题nginx支持jsp吗答案是否定的nginx本身只处理静态资源动态请求要反向代理到Tomcat去解析。不过毕业设计阶段一般不需要nginxTomcat单机直接跑起来就能演示不要给自己增加额外的部署复杂度。6.3 答辩时老师最常追问的五个问题项目做出来只是上半场答辩是下半场。我把我和身边同学被老师实际问过的问题整理出来提前准备答案会从容很多为什么选择JSP而不是前后端分离可以从毕业设计重在考察完整Java Web流程、JSP支持服务端渲染、分离架构增加部署复杂度这几个角度回答。数据库为什么这么设计讲清楚每条外键的设计理由比如bill表直接关联user是为了减少查询链路。角色权限怎么控制的直接描述Filter和Session的实现再把第四章的代码逻辑复述一遍。电费怎么算的把从抄表到账单的链路讲清楚顺便说自己用BigDecimal避免精度丢失。你遇到的最大难点是什么别说什么难点都没有讲一个你真实解决过的坑比如中文乱码、Tomcat部署都行真实感永远比完美值钱。答辩前一晚再把全流程操作一遍确保演示时不出岔子。从注册、登录到抄表、生成账单、缴费、报修整套流程在两分钟内能走通的话底气基本就足了。我自己当年答辩前也是这样反复演示真正站上讲台其实十几分钟就讲完了但因为每个页面都跑过无数遍老师问什么都接得住最后顺利通过。
RELATED

相关推荐

执行中途失败怎么办?sprix-sage-router进度感知重规划与失败恢复实战

执行中途失败怎么办?sprix-sage-router进度感知重规划与失败恢复实战

执行中途失败怎么办?sprix-sage-router进度感知重规划与失败恢复实战 【免费下载链接】sprix-sage-router Sprix AI at 屿智同行 — state-aware SELF/COLLABORATE/HANDOFF routing for A2A agent networks. 项目地址: https://gitcode.com/gh_mirrors/sp/sprix-s…

📅 2026/9/26 2:42:59
volatile 加了标志位还是停不下来:一次主循环不退出的排查,把 happens-before 讲明白

volatile 加了标志位还是停不下来:一次主循环不退出的排查,把 happens-before 讲明白

title: volatile 加了标志位还是停不下来:一次主循环不退出的排查,把 happens-before 讲明白 date: 2026-09-25 tags: [Java, JMM, volatile, happens-before, 并发]2024 年做订单状态机 worker,我们写了一个用 volatile boolean running tr…

📅 2026/9/26 2:42:59
bb 数据模型全解:Project、Thread、Environment、Host 四大核心概念彻底搞懂

bb 数据模型全解:Project、Thread、Environment、Host 四大核心概念彻底搞懂

bb 数据模型全解:Project、Thread、Environment、Host 四大核心概念彻底搞懂 【免费下载链接】bb The agent IDE that builds itself 项目地址: https://gitcode.com/gh_mirrors/bb14/bb bb 是一个"能自我构建的 AI 智能体 IDE"(the ag…

📅 2026/9/26 2:42:59
MORE NEWS

更多资讯

📰

Cursor 2.0 多 agent 并行实战:用 TaoToken 统一 Key 打通自研模型调用链

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

📰

百万行PR也能顺滑滚动,GitHub靠的不是再加一层虚拟列表

超大代码评审卡顿,通常不是“行数太多”这么简单。GitHub公开的极限样本包含2200个文件、超过100万行改动和400多条行内评论。它真正难处理的是评论高度会随图片、折叠块和回复框变化。GitHub的核心判断很值得复用:确定高度与未知高度不该共用一套几何。…

📰

【新手搭建本地 AI】自动化程序 OpenClaw 详细步骤(含安装包与 TaoToken 配置)

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

📰

(小白必看)Win 安装 OpenClaw 太简单!全程可视化,新手轻松拿捏 TaoToken 配置

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

📰

必看资料:Python开发者的全面指南 Python学习包:从

作为一名开发者,最近在学习主流编程语言时,我发现Python真的太强大了!从简单的脚本到复杂的后端开发,Python几乎无所不能。它的语法简洁清晰,学习曲线友好,特别适合新手入门。更让我惊喜的是,Py…

📰

agentscope 以 STUDIO 方式调用 MCP 服务:TaoToken 统一 Key 配置与 STDIO 联调指南

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

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬