简介一份包含安卓与苹果双端的影视应用源码程序面向移动应用开发者、产品运营及对视频聚合类应用感兴趣的学习者。源码基于跨平台开发思路既提供了安卓与苹果的统一代码库又覆盖在线视频播放、界面交互、用户登录、后台管理等完整链路降低多端开发成本。内置分销体系、卡密生成与分享机制并支持会员等级定价与权益分享有助于理解从用户裂变、佣金结算到虚拟商品交付的商业闭环。压缩包大小四十二点五兆内含数据库脚本文件、后台功能配置及部署使用教程可快速完成环境搭建与二次开发同时可学习用户关系管理、订单跟踪、支付接口集成、内容数据统计等关键模块的实现思路。已有1173人学习下载是研究商业化影视应用架构、会员营销策略及后端服务构建的实战参考资料。1. 影视APP双端源码程序在解决什么问题想搭一个影视点播平台的人买到的影视APP双端源码程序到手之后才发现它不是单个App安装包而是一整套系统用户播放端、管理后台、服务端接口和数据库脚本。这个标题里的双端在不同卖家嘴里含义不一样多数情况下指的是用户端 管理端这套完整可运营的组合也有人拿它指Android和iOS两个移动端。不管哪种它的价值都在于让你从零省掉前后端开发工作量把精力放到运营上。适合三类人做本地影视站点的创业者、接外包做视频类App的开发者、想基于现有源码做会员和支付二次开发的团队。2. 拆解双端架构用户端、管理端与视频服务怎么分工2.1 双端到底是哪两端先厘清行业默认花大几千买的影视APP源码拿到手最先要做的是看清目录结构。常见做法是解压后会看到server、admin、android、ios和sql这几个目录分别对应后端接口、管理后台、Android工程、iOS工程、数据库脚本。如果只有android和ios两个目录没有web后台和数据库脚本那它只是一对播放器壳不具备上架运营的能力。project/ ├── server/ # 后端接口常见是 PHP(ThinkPHP) 或 Java ├── admin/ # 管理后台 WebVue Element UI 居多 ├── android/ # Android 用户端工程 ├── ios/ # iOS 用户端工程 └── sql/ # 数据库初始化脚本看到这个结构基本可以判断这套源码走的是用户端 管理端双端路线。影视源码市场很大一部分后端都沿用了苹果CMSApple CMS的生态习惯字段命名、接口风格一脉相承哪怕换了壳也能快速上手。判断双端含义还有一个简单办法把sql目录里的脚本导入数据库如果后台能独立登录并添加影片说明管理端是完整的那一端。双端这个词单独看在电路领域有双端输入单端输出的说法在软件领域还有App端加微信小程序端的组合。如果你拿到的源码是uni-app工程那么双端很可能指Android和iOS一次编写、两端打包甚至能把微信小程序也算进来。判断标准还是看工程目录有原生android和ios两个独立目录的是双原生端只有一个uni-app目录的是跨平台双端。两种路线各有取舍双原生端播放能力强、权限控制细uni-app开发效率高、后期能扩展到小程序和鸿蒙但播放器定制深度有限。2.2 视频从哪来采集、JSON接口与转码的边界影视App的核心矛盾不是界面好不好看而是播放地址稳定不稳定。运营人员在后台手动添加影片是最稳的方式但工作量很大另一种方式是采集后台配置资源站地址定时任务把远端影片数据拉回本地数据库。这个采集过程在源码里通常是一个独立的PHP脚本或命令行任务跑一次就把一批影片的分类、封面、播放地址写入MySQL。# 每天凌晨3点拉取一次资源站数据 0 3 * * * php /www/wwwroot/video/server/collect/index.php /dev/null 21采集任务跑完要看日志重点确认有没有重复入库、字段缺失和播放地址为空。资源站接口一旦变更采集脚本就会静默失败每周手工抽查一次数据库里新增影片的质量很有必要。App端和后端之间走的是JSON接口接口字段一般长这样{ code: 0, msg: ok, data: { vod_id: 123, vod_name: 示例影片, type_name: 动作片, vod_pic: https://cdn.example.com/poster.jpg, vod_play_url: https://cdn.example.com/movie.m3u8 } }这些字段里的vod_id、vod_name、vod_pic就是苹果CMS体系里的老命名。看到它们你基本能判断后端是PHP MySQL那一脉。转码这块要单独说如果播放地址直接指向资源站你不需要自己转码但会面临地址失效的问题如果是自己上传视频就需要在后台对接FFmpeg。市面上多数影视APP源码默认只做地址管理不做转码所以部署前要先确定视频来源走哪条路不然等上线了再补转码服务代价会翻倍。2.3 播放器选型原生播放器、ijkplayer 还是 ExoPlayer用户端播放器决定用户能不能看得爽也是后续翻车最多的地方。Android端常见的播放组件有三个系统MediaPlayer、Google ExoPlayer、Bilibili开源的ijkplayeriOS端基本是AVPlayer或搭配KTVHTTPCache做边下边播。选择不同对视频格式的兼容性差异很大。播放器擅长协议维护状态常见坑Android MediaPlayermp4、ts随系统HLS兼容差弱网易卡ExoPlayerHLS、DASH、rtspGoogle持续维护扩展学习成本高ijkplayer几乎所有常见格式社区维护so库需按需编译iOS AVPlayerHLS最佳Apple维护非标准m3u8可能黑屏多数影视源码Android端默认集成ijkplayer因为点播环境里HLS、FLV、RTSP都能播。ijkplayer的so库体积大有些精简包把不需要的协议裁掉了换一个视频源就播不了这是后面要重点排查的地方。iOS端别轻易换播放器AVPlayer对HLS的支持是系统级的配合KTVHTTPCache做缓存体验足够撑起常规点播。如果拿到的源码Android端用的是ExoPlayer保留它Google持续维护API也清爽只是自定义扩展时要多读点文档。边下边播不是影视源码的标配很多售卖版只有播放没有缓存这一点购买前就要问清。iOS端的做法是AVPlayer搭配KTVHTTPCache把网络流缓存到本地拖动进度条时再从本地读取Android端ExoPlayer自带缓存模块ijkplayer则要自己接一层文件缓存。没有缓存的情况下用户拖动进度条会反复请求网络运营商流量敏感的用户很容易弃用。3. 把源码跑起来的完整步骤从环境准备到双端联调3.1 环境准备PHP、Nginx 与 MySQL 的最小组合影视APP源码后端如果是PHP部署环境用LNMP就够了。Linux上用命令装一套# CentOS 7/8 示例安装 nginx、mysql、php 及常用扩展 yum install -y nginx mariadb-server php-fpm php-mysql php-json php-mbstring php-gd systemctl start nginx systemctl start mariadb systemctl start php-fpm systemctl enable nginx mariadb php-fpm这里的php-mysql需要注意PHP 7.x以上版本叫php-mysqlnd装错扩展名会直接导致数据库连接失败。用php -m查看已装的模块确认mysqli或pdo_mysql存在再继续。不习惯命令行的直接用宝塔面板可视化安装LNMP十分钟能拉起来适合不想折腾服务器环境的人。环境装完先访问一下phpinfo页确认PHP版本和扩展加载情况。PHP 7.4和8.0对很多老源码的兼容性差别很大如果你的源码是两年前开发的直接上PHP 8.1可能报一堆deprecated错误稳妥做法是选源码文档里标注的PHP版本一般7.2到7.4之间。装完扩展记得重启php-fpm很多扩展加载不生效都是重启漏了。3.2 导入数据库与修改配置文件数据库脚本一般在sql目录下导入之前先建一个独立库避免和服务器上其他项目混在一起mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS video_db DEFAULT CHARSET utf8mb4; mysql -uroot -p video_db sql/video_db.sql导入完成后打开server目录下的配置文件常见是.env、config.php或database.php把数据库连接信息改成你自己的// config.php 示例 return [ db_host 127.0.0.1, db_name video_db, db_user video_app, db_pass your_password, db_charset utf8mb4, ];这段配置的核心是把数据库账号密码从默认的root改成专用账号生产环境不要用root跑业务接口。改完配置后访问服务器IP/api/index.php看到类似{code:0,msg:ok}的返回说明后端接口已经活了。这一步是整个部署里最容易卡住的地方很多人在配置上漏了字符集utf8mb4导致中文影片名全部变成问号。导入SQL时如果报错先看脚本头部有没有CREATE DATABASE语句有的话要把前几行删掉再导入避免库名冲突。还要检查表前缀苹果CMS系源码默认表前缀是mac_或pre_配置文件里的表前缀必须和SQL里一致否则后台登录直接报表不存在。这一条我踩过一次第一次部署时以为表前缀随便填结果后台列表页全红。3.3 管理后台首次配置添加分类、影片与播放地址后台登录后第一步不是急着加片而是先建分类。常见做法是后台分类管理里添加电影、电视剧、综艺等顶级分类每个分类可以再建子分类。然后到影片管理添加一部测试影片填标题、分类、封面图、播放地址。播放地址可以是直链mp4也可以是一个m3u8文件地址后台会原样存进数据库App端不做转码直接播。添加完成后到前台列表接口验证一下数据是否出来浏览器打开api接口地址看返回的JSON里有没有刚才添加的影片。这一步能筛掉一大批问题——比如数据库字符集不对、分类ID关联不上、播放地址被后台过滤规则拦掉。后台管理端只要能正常增删改查用户端的联调就只剩下地址对接这一件事。管理后台首次登录后尽快修改管理员密码并关闭默认的admin账号。很多源码出厂自带admin/123456上线后会被扫描工具直接撞库。后台的权限分配也要看一眼如果源码带角色管理给运营人员单独开账号不要所有人共用管理员避免误操作把整个分类删了。3.4 用户端联调修改接口地址与打包注意事项用户端工程里的接口地址一般集中在一个配置类里Android常见的是这个样子// ApiConfig.java public class ApiConfig { // 用户端所有请求都会拼这个地址 public static final String BASE_URL https://api.yourdomain.com/; public static final String APP_KEY your_app_key; }改BASE_URL时要注意Android 9.0之后默认禁止明文HTTP流量如果后端还没配HTTPS就必须在AndroidManifest.xml里打开usesCleartextTraffic否则打包出来接口全部失败application android:usesCleartextTraffictrue ... iOS这边对应的是Info.plist里的App Transport Security。HTTP域名需要在NSAppTransportSecurity里加NSAllowsArbitraryLoads或NSExceptionDomains否则iOS 9以上直接拦截请求。uni-app同理在manifest.json的h5和app节点分别配接口域名。热词里常见的npm: 无法将npm项识别为...就是这个环节的高频事故——跑uni-app或Vue后台要先装Node.js并配好PATH装完记得开新终端再执行npm run dev。用户端联调阶段把接口地址、AppKey、包名签名这三样对齐后面就顺畅了。Android工程打开后先同步Gradle依赖等首次构建通过再改代码不要上来就改配置否则编译报错时你分不清是环境问题还是代码问题。iOS端如果是Swift工程注意Pod依赖是否齐全缺了KTVHTTPCache这类库播放器直接编不过。4. 上线前必须调好的参数播放、鉴权与性能4.1 播放器参数超时、缓冲与硬解开关播放器默认参数大多偏保守直接上线会遇到弱网下转圈太久、切换清晰度卡顿的问题。Android端用ExoPlayer的话重点调缓冲参数// ExoPlayer 缓冲参数示例 DefaultLoadControl loadControl new DefaultLoadControl.Builder() .setBufferDurations(15 * 1000, 50 * 1000, 2 * 1000, 5 * 1000) .build();setBufferDurations四个值依次是最小缓冲、最大缓冲、缓冲重试起始、缓冲重试结束单位毫秒。点播场景最小缓冲调到15秒能明显减少播放中的卡顿。ijkplayer则是调IjkMediaPlayer的超时和硬解开关ijkPlayer.setOption(IJKMediaPlayer.OPT_CATEGORY_PLAYER, mediacodec, 1); ijkPlayer.setOption(IJKMediaPlayer.OPT_CATEGORY_PLAYER, opensles, 0);硬解开关是黑匣子重灾区开启mediacodec后部分H.265片源会黑屏遇到这种情况先把mediacodec改成0强制软解验证。iOS端AVPlayer的缓冲是系统控制的要调的是AVPlayerItem的preferredForwardBufferDuration建议设成30秒左右兼顾内存和滑动播放的顺滑度。选集记忆和自动播放下一集是提升体验的两个点。Android端在onCompletion里拿到下一集地址后提前初始化播放器iOS端可以在AVPlayerItem的didPlayToEndTime通知里处理。源码如果没有这个逻辑二次开发时优先补上对长剧用户很重要。播放器还有一层容易被忽略的参数是音频焦点处理切到后台再回来声音不恢复的问题多半是没处理AudioManager的焦点回调。4.2 接口鉴权与防盗链参数影视App最怕播放地址被盗链。常见做法是用户端每次请求带上时间戳和签名服务端验证签名后再返回数据。签名生成的逻辑一般在服务端统一处理// PHP 端签名生成示例 $sign md5($uri . $timestamp . $secret_key);客户端请求时带上timestamp和sign服务端用相同的key算一遍不一致就返回401。参数配置方面有几个默认值上线前一定要改参数默认值建议值说明token过期时间2小时1天点播场景过长token反而增加被盗风险签名算法md5(urikey)md5(uritimestampkey)加时间戳防止重放播放地址有效期无30分钟视频直链短时有效防止被批量抓取Referer白名单关闭开启只允许App和后台域名访问签名的key不要写死在客户端代码里至少做到混淆和加固否则反编译之后接口等于裸奔。播放地址有效期不要设太长HLS切片地址即使泄露30分钟后也失效能把盗链损失压到最小。防盗链开启后要注意后台预览也会被拦管理端的请求需要单独加白名单否则运营人员自己都看不到播放效果。4.3 CDN与图片处理参数封面图和视频播放地址都建议走CDN。图片方面后台填的封面图往往是大图App列表直接加载原图会拖慢首屏。处理办法是在图片地址后加CDN的处理参数https://cdn.example.com/poster.jpg?imageView2/2/w/300这类参数是七牛、阿里云OSS一类CDN的标准写法w300表示列表缩略图详情页再按原图或w800加载。图片体积尽量压到200KB以内首屏加载会快很多。视频切片的话如果后端自己转码HLS的ts分片时长建议控制在4到8秒太长拖动进度条等待明显太短会增加请求数。分片大小不是源码里能直接改的要看转码脚本的-hls_time参数很多源码自带的转码脚本默认是10秒改成6秒体验更稳。CDN域名和接口域名要分开不要用同一个域名。接口走的是动态请求CDN缓存会误伤接口数据播放和图片走静态加速两个域名分开后接口出问题时不会殃及播放链路。回源HOST也要在CDN控制台配好否则源站会拒绝非白名单域名的请求片子全挂。4.4 缓存与并发参数接口层加Redis缓存能显著降低数据库压力。列表接口缓存设置如下# 列表接口缓存10分钟详情接口缓存30分钟 redis-cli EXPIRE video_list_home 600 redis-cli EXPIRE video_detail_123 1800源码里如果已经集成了Redis在配置里打开缓存开关即可没集成的优先给首页轮播和分类列表这两个高频接口加缓存性价比最高。PHP-FPM的并发参数也要顺手调pm.max_children按服务器内存1/4除以单个php进程占用估算2核4G的机器建议设成20左右。MySQL侧开启慢查询日志上线后观察哪些SQL超过1秒针对性的加索引这比盲目堆配置更有效# MySQL 开启慢查询日志定位执行超过1秒的SQL set global slow_query_log ON; set global long_query_time 1;并发上来之后视频详情页的点击量最大播放地址查询接口要确保命中索引否则高峰期数据库CPU会直接飙满。如果预算允许详情页接口直接上Redis缓存缓存穿透时加一个空值缓存避免恶意刷接口把数据库打死。5. 影视APP双端源码的常见问题与排查安装失败、黑屏与接口4015.1 安装后秒退签名、混淆与so库缺失现象APK装到手机上点开图标就闪退抓日志看到UnsatisfiedLinkError或ClassNotFoundException。 原因最常见的是so库没打全build.gradle里的abiFilters只保留了一个架构其次是混淆规则没keep住实体类Gson反序列化时反射失败。 排查路径先用adb logcat抓崩溃堆栈确认是native层还是Java层异常然后解压APK看lib目录下有哪些架构的so文件最后对比混淆配置文件里有没有keep实体类的规则。 解决检查build.gradle确保abiFilters同时包含arm64-v8a和armeabi-v7a混淆配置文件里加一行-keep class com.yourpackage.entity.** { *; }重新打包验证。如果是签名问题确认后台登记的签名SHA1和打包用的keystore一致测试机和正式包分开签名。这条坑在接手别人二次开发的源码时特别常见前一个开发者改了包名忘了同步签名配置后面接手的人一打包就闪退。5.2 视频黑屏但能听到声音协议不兼容与硬解开关现象播放HLS流时画面黑屏声音正常日志里能看到解码错误。 原因视频编码是H.265播放器硬解不支持声画分离或者m3u8里有非标准标签AVPlayer和ExoPlayer解析不完整。 排查路径先换一个已知正常的mp4直链测试确认是片源问题还是播放器问题再用软解模式播放同一个HLS流判断硬解兼容性。 解决先用软解验证——ijkplayer把mediacodec设为0ExoPlayer关闭MediaCodecSelector的H265支持如果软解正常说明是硬解兼容问题优先让后端把这些片源转码成H.264。iOS端的非标准m3u8换成AVPlayer的默认解析还不行的话就得在服务端清洗m3u8把多余标签去掉再返回给App。还有一个经常被忽略的情况播放地址本身是加密的m3u8需要额外传请求头才能拉切片。这类地址在浏览器里直接打开是403App里也不播要在播放器初始化时带上自定义Header。5.3 管理端能登录但App列表空白baseUrl与跨域现象后台能正常加片但App首页一直转圈或白屏调试看网络请求发到了localhost。 原因用户端的BASE_URL还是开发环境地址或Web后台服务端没配CORSApp跨域请求被浏览器或WebView拦掉。 排查路径在App里打开网络抓包工具看请求的实际URL再用浏览器直接访问一次接口地址确认服务端返回是否正常最后看响应头里有没有Access-Control-Allow-Origin。 解决把BASE_URL改成线上HTTPS域名同时在后端入口加跨域响应头header(Access-Control-Allow-Origin: *); header(Access-Control-Allow-Methods: GET, POST, OPTIONS);注意生产环境把*换成具体域名不然别人也能跨域调你的接口。这个坑很基础但确实经常出现在部署完忘了改配置的项目里。还有一种情况是后台填的播放地址是内网IPApp在公网环境拉不到内网资源列表能显示但播放全失败排查时留意数据库里存的地址到底是什么。5.4 打包后接口全部401签名算法与时间戳校验现象本地调试一切正常一打成release包就全部报签名错误。 原因后台校验了Android包签名指纹本地调试用的debug签名和release签名不一致或者源码在打包阶段把时间戳校验也带进了release逻辑。 排查路径先看后台日志里记录的签名指纹是否和release包一致再用测试包直接请求接口对比本地调试时请求报文里的sign和时间戳格式。 解决先把后台的签名校验地址确认一遍填入正式keystore的SHA1时间戳校验的逻辑在服务端和客户端各有一份建议只保留服务端校验客户端只负责传当前时间。时间戳校验还有一个隐性问题客户端手机时间不准提前或滞后几分钟都会导致签名过期。源码里如果对时间窗口卡得紧比如正负5分钟用户体验会很差建议放宽到正负15分钟。我之前遇到过用户手机时间快了10分钟全部接口401后台无脑改宽限才解决。5.5 npm 命令无法识别环境变量没配现象Windows终端执行npm run dev直接报npm: 无法将npm项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 原因Node.js没装或者装的时候没勾选Add to PATH当前终端会话里的PATH没有node和npm目录。 排查路径先跑node -v如果也提示无法识别基本确定Node.js没装或没进PATH如果node -v正常而npm报错多半是PATH里只有node没有npm的全局目录。 解决重新安装Node.js LTS版本安装向导里勾选Add to PATH装完后新开一个终端先跑node -v和npm -v确认输出正常再执行npm install。旧终端不会自动刷新PATH开新窗口这一步别省。这个报错在热词里被大量搜索说明是Windows下跑前端工程的入门高频问题和影视源码本身无关但uni-app和Vue后台跑不起来的时候十有八九卡在它身上。6. 二次开发切入点与上线验证从跑通到能商用6.1 上线前的验证清单检查项验证方式通过标准接口鉴权抓包改签名篡改后返回401播放兼容真机播放HLS/mp4/flvAndroid与iOS均不黑屏弱网体验模拟3G网络播放缓冲不超过5秒后台备份导出sql文件恢复后数据完整签名一致性对比后台登记SHA1与keystore一致6.2 值得做的四个二次开发方向有价值的方向基本围绕变现展开。第一个是会员与支付接入微信支付或支付宝VIP集数按会员等级下发这是影视源码最常被问到的需求。第二个是播放页体验改造倍速、弹幕、选集记忆三个功能对留存影响最直接改动量也不大。第三个是短视频模块用现有播放器封装一个竖屏feed能显著提高用户时长。第四个是微信小程序端用uni-app从现有接口抽一套小程序壳标题栏通过uni.setNavigationBarTitle动态设置和App保持同一套数据源。6.3 运维习惯备份、升级与后悔药我的习惯是任何改动前先备份数据库和配置文件改动后立刻在测试机验证一遍再上生产。源码程序最怕的就是升级插件时覆盖了自定义的二开代码所以我会在server目录里维护一份补丁记录标明改了哪些文件、为什么改。这样即使升级翻车也能快速回滚。影视源码这个方向只要后端接口稳定、播放地址可靠、鉴权不被绕过运营起来比想象中省心。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
基于 ANTLR4 的电话号码语法 telephone:规则解析、示例验证与构建测试实践 编程语言编译器开发工具 【免费下载链接】grammars-v4 Grammars written for ANTLR v4; expectation that the grammars are free of actions. 项目地址: https://gitcode.com/gh_mirrors/gr/grammars-v4 点击查看 免费下载 本篇文章以 grammars-v4 仓库中的 telep… · 2026/9/25 3:27:20
RocketMQ大消息处理实战:4MB限制排查与优化方案 1. 4MB限制不是传说:客户端和Broker各卡一道,先搞清楚“谁说了算”上周有个同事跑来找我,说线上给下游推送客户画像消息,突然开始报错,后台一看发送端直接抛了MQClientException: message body size over maxMessageSi… · 2026/9/25 3:56:33
OpenShorts AI布局自动决策的秘密:为什么发12帧比发整个视频更聪明(含成本测算) OpenShorts AI布局自动决策的秘密:为什么发12帧比发整个视频更聪明(含成本测算) 【免费下载链接】openshorts Open source AI clip generator: turns long videos into viral 9:16 shorts with AI moment detection, face tracking, subtitle… · 2026/9/25 3:56:27
ipatool:一条命令完成 App Store IPA 下载,旧版本直接拿 ipatool:一条命令完成 App Store IPA 下载,旧版本直接拿 【免费下载链接】ipatool Command-line tool that allows you to search for iOS, iPadOS, tvOS, visionOS, and macOS apps on the App Store, and download .ipa or macOS .pkg app packages. … · 2026/9/25 3:56:27
二分查找全解析:核心思想、边界处理与PTA函数题实现 二分查找这个算法,很多人觉得自己早就掌握了:不就是“对一个有序数组,每次取中间值比较一下,缩小一半范围”嘛。可实际上,我在带学生和帮朋友排查面试题的几年里,发现二分查找反而是翻车率最高的题目之一。… · 2026/9/25 3:56:26
含碳捕集微网多时间尺度低碳经济调度:改进粒子群算法及Matlab实现 做微网调度研究的人这两年普遍有个感受:经济性和低碳性已经不能分开算了。我最早接触这个方向时,模型里就是燃料费加运维费,碳排放最多折算成碳税在目标函数里加一笔。后来意识到一个问题:把碳捕集装置(CCS)… · 2026/9/25 3:56:20
PilotDeck插件开发完全指南:用plugin.json注册工具、Hook与自定义记忆存储 PilotDeck插件开发完全指南:用plugin.json注册工具、Hook与自定义记忆存储 【免费下载链接】PilotDeck Task-oriented AI Agent productivity platform 项目地址: https://gitcode.com/OpenBMB/PilotDeck
PilotDeck 是一个任务导向的 AI Agent 生产力平台&am… · 2026/9/25 3:56:20
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37