尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
SpringBoot+Vue3+MyBatis爱心商城系统开发全流程复盘
每年到毕业季或者项目实战阶段总能看到一批做商城系统的同学在选型上纠结半天。今天要聊的这个“Java SpringBootVue3MyBatis 爱心商城系统”算是把主流技术栈和公益场景结合得比较典型的一个前后端分离项目。它不是一个简单的“增删改查demo”而是从用户端购物、订单流转到后台商品管理、爱心捐赠记录甚至公益积分的发放与使用都有完整闭环的系统。这篇要讲的就是我从零开发这个爱心商城系统的全过程复盘。我会把技术选型的原因、数据库怎么设计才不返工、前后端联调时最容易踩的坑、以及部署上线遇到的那些问题全部摊开来说。无论你是准备拿它当毕业设计还是想把这个项目写进简历或者是想学一下前后端分离项目的完整落地流程这篇内容应该都能帮你省掉不少试错成本。1. 项目整体设计动手写代码之前先想清楚这几件事1.1 爱心商城的核心业务到底长什么样很多人拿到“商城系统”四个字就直接建表写接口了结果做到一半发现逻辑对不上又回头改表结构非常痛苦。爱心商城和普通商城最大的区别在于它不只卖商品还承担公益属性。我当时梳理出来的核心角色有三种普通用户、平台管理员、以及后台运营人员。用户端的核心链路是注册登录 - 浏览商品 - 加入购物车 - 提交订单 - 支付模拟- 收货 - 评价。但除此之外爱心商城还多了一条公益链路用户下单之后系统按订单金额的一定比例生成“爱心积分”积分可以兑换公益商品或者在个人中心里查看自己累计的爱心值。这个设计直接决定了数据库表结构和后端接口的设计。管理员端的核心功能是商品分类管理、商品上下架、订单审核、物流发货、用户管理、爱心积分规则配置、公益捐赠数据统计。这些看起来不复杂但每个模块背后对应着前端至少一个页面、后端至少一组REST接口工作量并不小。所以我在设计阶段就把功能清单列成了表格优先级也标清楚避免做到后面越加越多、项目失控。1.2 技术选型为什么是SpringBootVue3MyBatis这一套这个组合在目前的国内开发环境下确实是最“稳”的选项之一。我解释一下每个部分的理由。后端用SpringBoot看中的是它的自动配置和生态成熟度。一个爱心商城系统的后端涉及用户、商品、订单、支付回调、权限拦截等多个模块SpringBoot的starter机制能省掉大量配置工作哪怕是新手也能快速把项目跑起来。而且SpringBoot自带的嵌入式Tomcat让部署变得非常简单打一个jar包就能跑不需要单独装Tomcat。持久层选MyBatis而不是Spring Data JPA核心原因是SQL可控。商城系统的订单查询、商品统计往往需要写比较复杂的分页查询和聚合SQLMyBatis把SQL写进XML里调试的时候直接拿出来在数据库客户端里跑一遍定位问题非常方便。相比之下JPA虽然写着省事但复杂查询一旦性能出了问题排查成本很高。前端用Vue3搭配Vite和Element Plus看中的是组合灵活性。Vue3的Composition API让组件逻辑复用更干净Vite的冷启动速度比Webpack快非常多开发体验好。Element Plus则基本覆盖了商城后台管理页面需要的表格、表单、弹窗、上传等组件不用自己手写UI细节。整个前端工程用npm管理依赖结构清晰后面接Tailwind或者换UI库都不伤筋动骨。1.3 前后端分离的工程结构怎么规划前后端分离的关键不只是“前端一个项目、后端一个项目”而是接口约定要清晰。我一开始就定义了统一的前后端约定接口前缀统一为/api比如用户模块就是/api/user/register、/api/user/login。响应结构统一为{ code: 200, message: success, data: {...} }前端拦截器统一处理后端的code非200情况。用户身份信息通过请求头里的token传递后端写了一个拦截器统一解析。后端工程我按照Maven标准结构分成了这样几层controller接口层、service业务层、mapper数据访问层、entity实体类、dto数据传输对象、vo视图对象、config配置类、common公共工具和统一结果封装。这个分层结构看起来很常规但它在后面排查问题时非常有用——所有HTTP参数校验都在controller层做业务规则判断在service层做SQL写死在mapper的XML里每一层职责单一出了问题直接按层定位。前端工程我用的Vite默认模板目录分成了src/api请求封装、src/router路由、src/store状态管理、src/views页面、src/components组件、src/utils工具函数。后面开发了大概二十多个页面组件这个结构基本没动过说明一开始的规划是合理的。2. 数据库设计一个商城系统的骨架决定成败2.1 核心表结构拆解爱心商城的数据库我用的MySQL 8.0字符集utf8mb4。核心表大概有10张左右用户表、用户地址表、商品分类表、商品表、商品图片表、购物车表、订单表、订单明细表、爱心积分表、积分流水表、捐赠记录表。下面把几张关键表的设计思路展开说一下。用户表t_user其实没什么特别主键id、用户名、密码、手机号、邮箱、头像、注册时间、状态。唯一要注意的是密码一定不能明文存我用的BCrypt加密即使数据库泄露用户密码也不会直接暴露。商品表t_goods是商城信息的核心载体。字段包括商品名称、商品副标题、商品主图、原价、现价、库存、销量、上下架状态、商品详情富文本、分类id、创建时间、更新时间。设计的时候有个细节很容易忽略商品表里一定要把“价格”和“库存”的类型定好价格用decimal(10,2)库存用int别图省事都用varchar存等后面写订单金额计算的时候会非常痛苦。订单表t_order是整个系统设计难度最大的一张表。我设计的核心字段有订单号、用户id、订单总金额、实付金额、优惠金额、订单状态、收货人姓名、收货人电话、收货地址、创建时间、支付时间、发货时间、完成时间。订单号我当时用了时间戳加6位随机数的组合保证唯一性。有人喜欢用数据库自增id直接当订单号在职场上这基本不会被接受因为订单号会暴露平台单量而且不利于业务扩展。订单明细表t_order_item记录了每个订单里包含哪些商品字段包括订单id、商品id、商品名称快照、商品图片快照、商品单价快照、购买数量、小计金额。这里强调“快照”两个字是因为商品信息随时可能改价格、改名称但订单历史必须保持下单那一刻的原貌。这个思想是商城系统设计的通用做法爱心商城也不例外。2.2 购物车和库存的两个关键设计决策购物车表t_cart我一开始的字段是用户id、商品id、数量。但实际开发中发现必须先查一遍商品当前状态再决定能不能加入购物车。如果商品已经是下架状态或者库存为0前端虽然做了判断但后端接口仍然要二次校验——这是很多人容易漏掉的点。库存的处理更是我踩过坑的地方。商品的库存字段在t_goods表里下单减库存的逻辑必须放在一个数据库事务里先查库存再判断库存是否充足然后扣减库存同时创建订单。这个流程没法在controller层靠多个独立接口完成必须在service层用一个Transactional方法包起来。如果把它拆成“查库存接口”和“下单接口”两部分并发场景下会出现严重的超卖问题。虽然爱心商城本身并发不会很高但从一开始就按正确的方式写后面做秒杀类扩展也有基础。我在测试的时候用两个浏览器同时下单同一件库存只剩1件的商品事务和行锁保证了只有一个请求能成功。2.3 爱心积分和捐赠记录的数据流转设计这是爱心商城区别于普通电商的亮点模块。积分表t_integral记录用户当前积分余额积分流水表t_integral_record记录每一笔积分变动变动类型增加/减少、变动值、积分来源购物返还/兑换扣减、关联订单号、创建时间。设计逻辑是用户确认收货后系统按订单实付金额的10%生成积分写入积分流水同时更新用户积分余额。积分兑换商品时则先判断积分余额是否充足充足则扣减积分并生成一个积分商品订单。整个积分流转的关键点在于积分流水必须有“来源标识”这样一旦某个环节数据对不上可以顺着流水号把整条链路查清楚。当时我在开发这个模块时还加了一个小设计每个用户有一个gift_count字段用来展示累计爱心值配合定时任务把用户的有效订单金额累加起来生成个人爱心榜单。捐赠记录表t_donation我放在了积分模块一起管理每次用户用积分兑换公益商品比如捐赠给山区儿童的文具包就会产生一条捐赠记录记录里包含捐赠人用户id、公益商品id、积分消耗值、收货组织信息。这条数据既能作为用户爱心行为的证明也是后台统计公益数据的基础。3. 后端实现SpringBoot与MyBatis的落地细节3.1 统一响应、全局异常与管理端的基础框架后端一上来我先写了一个统一的接口响应类ResultT结构就是前面约定的{code, message, data}。同时写了一个全局异常处理器用RestControllerAdvice捕获业务异常和参数校验异常让错误信息以统一的JSON格式返回给前端。这个基础框架虽然代码量不大但它决定了后面几十个接口的编写效率值得在项目第一天就搭好。业务异常我用了一个BusinessException在service层判断不符合业务规则时抛出。比如库存不足、积分不够、订单不属于当前用户这些都是业务异常前端拿到code为5001、5002这类约定好的业务错误码就能弹出对应的提示。这样做的好处是后端接口的返回值永远有一个稳定的数据结构前端axios拦截器只需要处理一种响应格式。管理端的基础框架也用到了SpringSecurity或者拦截器。我选择的是自己写一个拦截器加JWT的方案没有引入完整的SpringSecurity原因是爱心商城系统的权限模型很清晰——用户和管理员两种角色用拦截器加自定义注解完全够用引入SpringSecurity反而增加了配置复杂度。拦截器里对/api/admin/**开头的路径统一校验管理员的token对/api/user/**校验普通用户token白名单是登录、注册和商品查询接口。3.2 登录鉴权JWT的使用与注意点生成JWT我用的jjwt库登录成功后生成一个token返回给前端token的有效时间设置成了2小时。JWT生成时我在claims里放入了用户id、用户名、角色这三个核心信息这样后端在后续请求中解析token就能直接拿到用户身份不用每次toke请求都去查一遍数据库。校验逻辑要重点提醒拦截器在解析token时如果token过期、签名不对或者角色不匹配都必须抛出明确的异常。我当时遇到过一个问题前端在token过期后仍然发请求后端返回的报错信息不够明确导致前端不知道自己该跳转登录页了。后来我统一了codetoken缺失返回401token过期返回402前端axios响应拦截器统一判断这两个code跳转登录页并清理本地存储。这个配合理顺之后整个系统的登录体验才算是完整了。密码加密推荐用BCrypt。用户注册时把明文密码交给BCryptPasswordEncoder加密再存库。BCrypt的每一次加密都会生成不同的盐值所以同一密码两次加密结果不一样但校验时用matches方法依然能正确判断。这是SpringSecurity自带的加密工具单拿出来用也完全没问题。3.3 商品与订单的核心业务实现商品查询接口是商城用户端调用最频繁的接口我做了分页和条件筛选。接口参数有当前页页码、每页条数、分类id、商品名称关键词、排序方式。排序方式支持默认综合排序、销量排序、价格升序、价格降序四种。这条查询SQL写在MyBatis的XML里用动态SQL拼接条件加上LIMIT做分页。当时为了偷懒没引入PageHelper直接在参数里传offset和limit实际用下来反而更轻量SQL可控性更好。订单提交的核心流程我梳理成了下面几步根据前端传来的购物车记录id列表查询出对应的购物车数据。循环校验每个商品商品是否上架、库存是否满足购买数量。计算订单总金额这一步在前端也做了计算但后端必须重新算不能信前端传的价格。生成订单号和订单明细扣减库存清空购物车对应的记录。事务提交返回订单id。这个流程最大的坑在于订单和库存的一致性。当时我用Transactional默认的传播行为处理事务内先执行UPDATE t_goods SET stock stock - #{num} WHERE id #{id} AND stock #{num}MySQL的行级锁保证了并发时只有一个事务能更新成功受影响行数是0就说明库存不足抛出异常回滚。这个写法比“先查再减”更安全建议直接抄。3.4 后台管理与数据统计接口管理端的接口我大概写了十几个核心的是商品管理、订单管理和积分规则管理。商品管理接口包括分页查询商品列表、新增商品、编辑商品、更新上下架状态、删除商品实际是逻辑删除把状态改成删除标记、上传商品图片。上传图片我用的本地磁盘存储方案配置了一个上传目录的路径把MultipartFile写入服务器磁盘再把图片的访问URL存入数据库。开发环境下可以用本地上传生产环境建议换成对象存储服务把图片访问域名配成CDN本地磁盘方案只是过渡方案。订单管理接口包括分页查询所有订单、按订单状态筛选订单、订单发货填写物流单号修改订单状态为已发货、订单关闭。后台统计接口包括总共多少商品、总共多少用户、今日新增订单数、本月订单总额、爱心积分发放总数。这些统计SQL用SUM和COUNT聚合只需要一张接口汇总到一个仪表盘页面里展示。我当时还加了一个简单的ECharts折线图展示最近7天的订单量趋势后端接口就把最近7天的日期和订单数查出来返回给前端。4. 前端实现Vue3商城页面的实战记录4.1 路由设计与状态管理前端我用Vue3 Vite Element Plus Pinia的组合。路由用Vue Router的history模式分成两个布局用户端布局和管理员布局。用户端的地方有首页、商品列表、商品详情、购物车、结算、个人中心、订单列表管理端的地址是后台首页、商品管理、订单管理、用户管理、积分管理。这样每个布局对应一套路由组件公共的布局被抽成了组件避免把菜单栏和头部导航在每个页面重复复制。状态管理用的Pinia主要负责三块内容用户信息、购物车数量、全局加载状态。用户登录成功后把用户信息和token存入Pinia同时持久化到localStorage刷新页面后在路由前置守卫里读取本地存储恢复用户状态。购物车数量这个值比较特殊用户加购后要立即更新导航栏徽标用Pinia管理然后同步调用getCartCount接口获取后端真实的购物车总数避免前端本地状态和后端不同步。4.2 用户端页面的核心实现首页的设计我采用了布局从上到下轮播图、分类导航、推荐商品列表。分类导航点击后跳转到商品列表页带上分类id参数。商品列表页支持分类筛选和关键词搜索搜索框在顶部导航栏搜索词通过路由query传递。列表用卡片网格展示每个卡片包含商品主图、名称、价格、销量点击跳转商品详情。商品详情页的信息量相对大顶部左侧商品图轮播右侧是价格、库存、销量和数量选择器下面是商品详情的富文本内容。加入购物车按钮和立即购买按钮做了区分加入购物车只调加购接口立即购买则带参数直接跳结算页。这里要提醒一个细节——商品详情的富文本是后端返回的HTML字符串在Vue3里渲染时不能简单用v-html没做任何清洗就直接插进去因为如果运营后台允许上传富文本存的是完整的HTMLXSS风险要靠过滤或者限制上传内容来控制。我的方案是后端入库前用Jsoup做了白名单过滤只保留常见的排版标签。购物车页面就是典型的表格布局每条购物车记录前端含checkbox多选、商品信息、数量增减、小计金额。全选、取消全选、删除选中商品这些逻辑在前端做完后统一调用后端接口同步数据。结算页则分为收货地址、商品清单、金额明细商品总额、运费、实付款、提交订单按钮几个区块。运费我设置了满99包邮不满99收10元运费这个规则在后端计算订单总价时同步实现。4.3 管理端页面用Element Plus快速构建后台管理端我完全用的Element Plus组件库搭的整体风格是左侧菜单右侧内容区的经典后台布局。商品管理页面用的是el-table展示商品列表行内直接渲染上下架状态的el-switch点击状态开关触发状态修改接口。编辑商品用了el-dialog弹窗嵌套一个较大的表单表单里商品详情的富文本编辑器用的wangEditor支持图片插入插入的图片会先上传到后端再以URL形式放入富文本内容。订单管理页面同样用表格展示订单列表状态列用el-tag的type属性区分不同颜色待付款、待发货、待收货、已完成、已取消。发货操作弹出一个对话框填写物流公司、物流单号提交后调发货接口。用户管理页面包含用户列表、搜索、查看用户详情。积分管理页面我做了两部分积分规则配置用户端订单金额百分比、积分流水查询。管理端的接口调用和用户端共用了同一套axios封装。axios实例设置了baseURL为/api开发环境通过Vite的proxy代理到后端服务地址。请求拦截器统一从localStorage取token放到请求头响应拦截器统一处理code非200的情况。这里有一个实际开发时容易踩的坑axios响应拦截器里如果对业务异常弹了ElMessage.error调用页面里又再弹一次就会出现重复提示。我的习惯是拦截器只负责跳转登录和处理401/402业务错误码都在页面调用处统一提示。4.4 前后端联调的关键配置前后端联调最让人头疼的就是跨域。我的方案是开发环境下前端Vite配置proxy把/api的请求代理到后端http://localhost:8080这样浏览器看到的请求是同源的不涉及跨域生产环境前后端通过Nginx托管Nginx配置同域名的不同路径转发后端接口路径全部走/api开头。这两种方式都可以避免在前端代码里写死后端地址也避免在后端配置复杂的CORS跨域规则。后端我也不建议默认开启CORS解决一切。CORS开启后确实方便但在生产环境如果前后端域名不一致会出现安全问题。而且如果后端的CORS策略和代理同时存在某些情况下会被浏览器双重重定向排查起来很头疼。前后端分离项目最稳的做法是开发用代理部署用Nginx反向代理后端专注业务接口。联调阶段我强烈建议用接口文档沉淀一遍。我当时用Swagger自动生成接口文档后端在每个controller上加了Swagger注解启动后访问/doc.html能直接查看接口的入参和响应示例。前端开发照着Swagger的说明调接口能减少大量“字段名对不上”“数据类型不一致”的沟通成本。5. 部署上线与常见问题排查实录5.1 本地运行与打包部署流程先说一下本地把项目跑起来的标准步骤。后端导入Maven工程等待依赖下载完成修改application.yml里的数据库连接信息为本地MySQL启动项目。如果数据库里没有表结构我提供了init.sql用Navicat或者命令行执行一遍就能生成全部表和初始数据。左下角的Redis如果项目里用到了登录token缓存场景需要先启动Redis服务不过我这个爱心商城把token校验做在JWT无状态方案里所以不依赖Redis部署更简单。前端安装Node.js 14以上版本在工程目录执行npm install安装依赖执行npm run dev启动开发服务。浏览器访问http://localhost:5173就能看到首页。这里提醒一下Vite默认端口是5173和后端的8080要区分开有同学把两个端口搞混了还在找bug。生产环境部署我是这样做的前端执行npm run build产物是在dist目录把这个目录上传到服务器的/usr/share/nginx/html下由Nginx托管。后端执行mvn clean package -DskipTests打出jar包上传到服务器执行nohup java -jar xxx.jar log.out 21 启动。Nginx的server配置里location /指向前端dist目录location /api转发到本地8080后端服务这样整个系统就处于同一个域名下对外只暴露80端口。5.2 常见问题速查表下面把我在开发过程中真实遇到过的、并且在各种技术群里经常看到的问题整理成了一张表碰到类似情况可以直接对着排查。现象可能原因解决办法前端请求 /api 接口报404Nginx代理路径没配对或者proxy配置contextPath不对检查Nginx location /api 的proxy_pass是否带上了后缀slash记得保留路径商品图片上传后访问不了静态资源映射未配置后端配置addResourceHandlers把本地磁盘上传目录映射到 /upload/** 访问路径订单提交时报库存不足但明明有货前端传的购买数量单位和后端不一致统一用件数前端下单前重新调一次商品详情接口获取最新库存CORS报错Access-Control-Allow-Origin前端地址和后端地址端口不同且没有走代理开发环境用Vite proxy别直接跨域访问8080管理端接口一直提示无权限token解析角色失败角色名不一致检查JWT生成和校验时使用的角色字段名是否完全一致大小写也要看订单金额出现小数精度问题价格字段用了float/double全部改成decimal类型Java中用BigDecimal富文本内容在页面显示乱码或带样式异常HTML未做过滤或渲染方式不对后端入库白名单过滤前端v-html前确认内容已清洗5.3 几个我反复踩坑后总结的避坑心得第一个心得和“逻辑删除”有关。商品表我不建议用“物理删除”用户一旦下单了商品订单明细里已经存了商品快照但如果后台运营手滑删了商品的数据积分商品页面和历史记录都会受影响。当时我遇到一个线上问题运营删掉了一个商品结果用户历史订单里商品图片全裂了因为订单明细里只存了图片URL图片文件被同步删了。从那以后我的标准做法是所有核心业务表都加is_deleted字段商品删除走逻辑删除图片文件清理走定时任务延迟处理。第二个心得关于定时任务。爱心积分如果在下单时发放用户未付款就取消订单会造成积分错乱。我最后把积分发放放在了“确认收货”这个动作之后用户在订单列表里点“确认收货”后端才判断该订单是否已发过积分没发过才发放。这样可以避免退款取消订单引起的积分回滚问题。这个逻辑想明白之后整条积分链路的对账就清晰了。第三个心得是管理后台的密码安全问题。系统里我内置了一个管理员初始账号但很多同学写完就忘了提醒使用的人改初始密码。我加了登录后强制修改初始密码的逻辑虽然多写了一个判断但这个细节在企业项目里属于基本要求。类似的还有所有列表查询接口必须分页不能一把梭查全表所有金额运算用BigDecimal禁止double。结语这个爱心商城系统从最开始的需求梳理到前后端联调完成大概花了一周多的业余时间。做这类前后端分离项目最大的收获不是会了某个框架的新特性而是把“一个完整业务从零到上线”的整个链路走通了——数据库设计时要考虑订单快照和积分流水后端写接口时要考虑统一响应和事务边界前端跳页面时要考虑路由守卫和token持久化部署上线还要考虑Nginx转发和静态资源映射。每一次“当时觉得多此一举”的设计都在后面某个报错场景里救了场。最后分享一个很实在的建议如果你也打算做这个方向的商城项目别上来就写代码。花一个晚上把用户角色、核心流程、表结构画出来画的时候多问自己几个“如果……怎么办”比如如果商品下架了用户购物车里的数据怎么处理如果订单支付超时怎么关单。这些问题想清楚了写代码的速度会快很多返工也会少很多。这个爱心商城目前仍然是我推荐给想练手前后端分离项目的朋友的首选案例技术栈主流、业务闭环完整、面试还有得聊。
RELATED

相关推荐

微信小程序招聘后端:SSM平滑迁移SpringBoot实战指南

微信小程序招聘后端:SSM平滑迁移SpringBoot实战指南

简介:这是一套基于微信小程序的求职招聘系统完整开发资源,面向Java后端与小程序前端初学者及课程设计者,解决校园场景下学生兼职对接、商户岗位发布与管理员协同管理的实际需求。资源包含小程序端(求职者/商家)与Web后…

📅 2026/10/23 3:11:35
CASS11报‘请不要在虚拟机中运行’的5种真实解决方案

CASS11报‘请不要在虚拟机中运行’的5种真实解决方案

简介:本资源是一份针对CASS11软件安装与运行中‘请不要在虚拟机中运行此程序’报错的专项排错指南,面向测绘、地理信息系统(GIS)及工程制图领域的专业技术人员与高校实践者,解决CADCASS11环境部署时因虚拟化检测引发的…

📅 2026/10/23 3:11:35
Unity WebGL中文输入解决方案:透明DOM覆盖层与IME输入法跟随

Unity WebGL中文输入解决方案:透明DOM覆盖层与IME输入法跟随

简介:这是一份针对Unity WebGL中文输入需求的示例工程,面向希望在网页端实现原生中文输入与输入法跟随的Unity开发者,尤其适合在文本交互、聊天、搜索等场景中需要中文录入的WebGL项目。工程演示了通过JavaScript与Unity交互层监听键盘事件、…

📅 2026/10/23 3:11:35
MORE NEWS

更多资讯

📰

从照亮到编码:光度立体、相移与格雷码的逻辑与工程实现

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

📰

ADC精度实战指南:从采样原理到PCB布局的工程真相

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

📰

Linux下LevelDB安装、链接与调优:从LSM原理到C++实践

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

📰

快排O(n log n)的真相:划分、递归深度与期望值三支柱解析

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

📰

2026移动开发选型指南:Android、iOS、跨平台与安卓上架全流程

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

📰

ADSL宽带接入:频段划分、DMT调制与线路排障实战

/* 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

本月热门

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

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

📞 💬