工业互联网平台数字仿真:CAE云化架构与落地实践
简介《工业互联网平台数字仿真发展白皮书2021》由中国电子信息产业发展研究院编写面向制造业数字化转型从业者、工业软件与仿真领域研究人员及政策制定者系统梳理“平台数字仿真”的发展脉络与落地路径。资源为1个PDF文件压缩包约1.8MB共32页篇幅精炼便于通读与检索。白皮书分四部分展开发展现状对比国际寡头垄断与国内自主仿真困境趋势展望从技术供给、应用范围、产业生态三个角度研判云化、APP化、普惠化方向定义内涵明确其基于平台资源与能力构建仿真模型、开展平台化仿真服务架构体系则概括为“一二二三三”涵盖通用研发平台、系统与实物仿真两大体系、两类模型、三大功能及设备产线工厂三大领域。已有179人学习适合快速建立“平台数字仿真”整体认知框架把握换道超车机遇与制造业转型升级的参考依据。1. 工业互联网平台数字仿真从一份32页白皮书看CAE云化落地2021年那份《工业互联网平台数字仿真发展白皮书》只有32页却把一件事说透了仿真不再只是研究所里几台工作站跑ANSYS的事它正在变成工业互联网平台上的一种服务。如果你在工厂里做过CAE一定经历过这样的场景——前处理画网格花两天求解等一宿结果发现边界条件设错了重来。而工业互联网平台想做的是把这套流程拆开、搬到云上、按需调度算力让仿真像用水用电一样按量取用。这份白皮书适合三类人看正在选型CAE上云方案的工程师、想把仿真能力封装成工业APP的开发者、以及需要评估数字仿真投入产出比的技术管理者。它不讲某个具体软件的操作而是讲整个数字仿真能力怎么在平台架构里重新组织。下面我按自己趟过的路把这份白皮书背后的技术逻辑和落地路径拆开讲。2. 数字仿真上工业互联网平台架构怎么搭、CAE怎么云化2.1 从单机CAE到平台化仿真的三层架构传统CAE的工作流是线性的几何清理→网格划分→求解设置→提交计算→后处理。这套流程跑在单机上最大的问题是资源孤岛——前处理工程师的机器可能只用了20%性能而求解器排队等三天。工业互联网平台要解决的就是资源池化和流程解耦。白皮书里给出的参考架构分三层。最底层是基础设施层提供CPU/GPU异构算力、分布式存储和高速网络。中间层是平台服务层这是核心包含仿真任务调度引擎、许可证管理服务、数据管理服务和作业监控模块。最上层是应用层面向具体场景的工业APP比如结构强度快速评估、注塑工艺参数优化。我一般会把调度引擎单独拎出来说因为它是整个平台能不能跑起来的关键。调度引擎要解决三个问题第一怎么把一个大求解任务拆成可并行的小任务第二怎么在多个求解器许可证之间做排队和抢占第三任务失败后怎么自动重试而不丢中间结果。常见做法是用Kubernetes做容器编排把每个求解器封装成独立镜像通过挂载共享存储来传递输入输出文件。注意不是所有CAE软件都支持容器化。有些商业求解器对硬件指纹和许可证绑定很严格容器化之前先确认许可证是否支持浮动授权。2.2 把CAE求解器封装成平台服务的具体步骤假设你手头有一个结构静力学求解器想把它搬到平台上。下面是我实际走过的一套流程以Linux环境为例。第一步确认求解器的无头运行模式。大部分商业CAE软件都支持命令行批处理模式比如ANSYS的ansys -b -i input.dat -o output.outAbaqus的abaqus jobjobname inputinput.inp。先在一台干净的Linux机器上跑通不依赖图形界面。第二步制作Docker镜像。基础镜像选CentOS 7或Ubuntu 20.04把求解器安装包、依赖库、许可证客户端都装进去。关键是把许可证配置做成环境变量不要硬编码在镜像里。# Dockerfile 片段封装一个假想的求解器 FROM ubuntu:20.04 # 安装基础依赖 RUN apt-get update apt-get install -y libgomp1 libmpich-dev # 拷贝求解器安装目录 COPY ./solver /opt/solver # 设置许可证服务器地址为环境变量 ENV LICENSE_SERVER ENV SOLVER_HOME/opt/solver # 入口脚本负责拼接命令行参数 COPY entrypoint.sh /entrypoint.sh RUN chmod x /entrypoint.sh ENTRYPOINT [/entrypoint.sh]这段Dockerfile的逻辑是基础镜像只装运行库求解器本体通过COPY放入许可证地址通过环境变量注入入口脚本负责把平台传来的参数转成求解器能识别的命令行。参数说明LICENSE_SERVER在平台调度时动态注入SOLVER_HOME用于定位求解器二进制文件。第三步定义任务描述文件。平台调度需要知道这个任务需要多少核、多少内存、预计跑多久。我一般用YAML来描述# job.yaml 仿真任务描述 job: name: static_analysis_001 image: solver/ansys:2021r1 command: [/opt/solver/run, -i, /data/input.dat] resources: cpu: 8 memory: 32Gi gpu: 0 volumes: - /shared/input:/data - /shared/output:/results license: feature: mech_1 count: 4这个YAML里resources字段告诉调度器需要8核32Gvolumes把共享存储挂载到容器内license字段声明需要4个mech_1许可证。平台调度器根据这些信息做资源匹配和许可证排队。第四步结果回传与后处理。求解完成后输出文件在/shared/output目录下。平台可以自动触发后处理脚本提取最大应力、位移云图等关键指标写回数据库。这一步用Python脚本就能做# 提取结果文件中的最大应力值 import re def extract_max_stress(result_file): 从求解器输出文件中提取最大应力 with open(result_file, r) as f: content f.read() # 假设输出格式为 MAX STRESS 123.45 MPa match re.search(rMAX STRESS\s*\s*([\d.]), content) if match: return float(match.group(1)) return None if __name__ __main__: stress extract_max_stress(/results/output.out) print(f最大应力: {stress} MPa)这段脚本用正则匹配输出文件里的关键结果逻辑很简单但很实用。参数说明result_file是求解器输出文件路径正则表达式要根据实际求解器的输出格式调整。2.3 工业APP封装把仿真流程变成可复用的模块白皮书里反复提到工业APP我的理解是把一串仿真操作步骤固化成一个带界面的应用让不懂CAE的人也能用。比如“注塑件翘曲分析APP”用户只需要上传STL模型、选材料、填工艺参数后台自动完成网格划分、求解、结果提取。封装工业APP的关键是参数模板化。把求解器输入文件里的变量抽出来做成前端表单字段。比如Abaqus的INP文件里材料弹性模量、泊松密度、载荷大小都是可以参数化的。用Jinja2模板引擎就能做from jinja2 import Template inp_template Template( *Material, name{{ material_name }} *Elastic {{ elastic_modulus }}, {{ poisson_ratio }} *Density {{ density }} ) # 渲染模板生成实际INP文件 rendered inp_template.render( material_nameSteel, elastic_modulus210000, poisson_ratio0.3, density7.85e-9 ) with open(job.inp, w) as f: f.write(rendered)这段代码用Jinja2把INP文件模板化前端传来的参数直接填充。参数说明elastic_modulus单位是MPadensity要注意单位制一致性Abaqus里常用吨-毫米-秒制。提示工业APP的版本管理很重要。同一个APP不同版本可能对应不同的求解器版本和材料库建议用Git做模板文件的版本控制。3. 数字仿真平台的算力调度与数据管理参数怎么设3.1 求解器许可证调度别让许可证成为瓶颈CAE上云最容易被忽视的坑是许可证。商业求解器按核数收费一个32核的求解任务可能占用32个许可证。如果平台上有10个用户同时提交任务许可证池瞬间见底。我一般会在调度层做三件事。第一许可证预检任务提交时先查询许可证服务器剩余数量不够就直接拒绝不要让任务跑起来再失败。第二许可证排队用Redis做一个简单的队列按提交时间排序先到先得。第三许可证回收任务结束后立即释放不要等容器完全退出。import redis import time r redis.Redis(hostlicense-server, port6379) def acquire_license(feature, count, timeout3600): 申请许可证带超时 key flicense:{feature} start time.time() while time.time() - start timeout: available int(r.get(key) or 0) if available count: # 原子性扣减 pipe r.pipeline() pipe.decrby(key, count) pipe.execute() return True time.sleep(5) return False def release_license(feature, count): 释放许可证 r.incrby(flicense:{feature}, count)这段代码用Redis的原子操作做许可证计数。acquire_license函数在许可证不足时轮询等待release_license在任务结束后归还。参数说明timeout是最大等待时间建议设为预计求解时间的1.5倍。3.2 仿真数据管理结果文件别乱放仿真产生的数据量很大。一个瞬态分析可能产生几十GB的结果文件如果每个用户都往自己的目录里扔存储很快爆掉。白皮书里提到用分布式存储但具体怎么组织目录结构我踩过坑。我的做法是按项目-任务-时间戳三级目录/shared/simdata/ ├── project_A/ │ ├── task_001_20210601/ │ │ ├── input/ │ │ ├── output/ │ │ └── post/ │ └── task_002_20210602/ └── project_B/每个任务目录下分input、output、post三个子目录。input存原始模型和INP文件output存求解器原始结果post存提取后的云图和报告。这样做的好处是清理时按时间戳删整个任务目录不会误删备份时按项目粒度做策略。数据生命周期管理也要设参数。我一般设三个阈值热数据保留30天存在SSD上温数据保留180天转到HDD冷数据保留3年归档到对象存储。超过3年的数据直接删除除非用户手动标记为“永久保留”。3.3 算力资源配额怎么防止一个人占满集群没有配额管理的仿真平台一定会被少数几个大任务拖垮。我见过一个用户提交了一个200核的CFD任务把整个集群占了一周其他人都没法用。配额管理分两层。用户级配额每个用户最多同时运行3个任务总核数不超过64核。项目级配额每个项目每月总机时不超过1000核时。这些配额存在数据库里调度器每次调度前检查。-- 用户配额表 CREATE TABLE user_quota ( user_id VARCHAR(64) PRIMARY KEY, max_concurrent_jobs INT DEFAULT 3, max_total_cores INT DEFAULT 64, monthly_core_hours INT DEFAULT 1000, used_core_hours INT DEFAULT 0 ); -- 调度前检查配额 SELECT (SELECT COUNT(*) FROM running_jobs WHERE user_id user001) max_concurrent_jobs AS concurrent_ok, (SELECT SUM(cores) FROM running_jobs WHERE user_id user001) 8 max_total_cores AS cores_ok, used_core_hours 8 * 24 monthly_core_hours AS hours_ok FROM user_quota WHERE user_id user001;这个SQL在任务提交前做三项检查并发任务数、总核数、月机时。参数说明8是本次任务申请的核数24是预计运行小时数实际使用时从任务描述文件里读取。注意配额检查要在调度器里做不要在前端做。前端可以被绕过调度器是最后一道防线。4. 数字仿真平台避坑指南五条血泪经验4.1 求解器容器化后许可证报错现象容器里跑求解器提示“License server unreachable”或“Invalid host”。原因商业求解器的许可证客户端通常绑定MAC地址或主机名。容器每次启动MAC地址都变许可证服务器认为这是未授权主机。解决在Docker启动时固定MAC地址用--mac-address参数指定一个固定值。或者更彻底的做法是把许可证客户端配置成通过环境变量读取服务器地址不依赖主机名。有些求解器还支持“许可证借用”模式提前从服务器借一个许可证到本地文件容器里用文件授权。4.2 共享存储挂载后求解器读写权限错误现象求解器能启动但读输入文件时报“Permission denied”或者写结果文件时失败。原因容器内运行求解器的用户UID和宿主机上共享存储的UID不一致。比如容器里是rootUID 0宿主机上共享目录属于UID 1000。解决在Dockerfile里创建一个和宿主机UID一致的普通用户用USER指令切换。或者在启动容器时用--user参数指定UID。我一般会在entrypoint脚本里先chown一下工作目录但这不是长久之计最好从镜像层面解决。4.3 大任务被调度到内存不足的节点现象任务跑了一半被OOM Killer杀掉日志里只有“Killed”没有其他信息。原因调度器只检查了节点总内存没检查可用内存。或者求解器的内存预估不准实际用量远超申请量。解决调度器要实时采集节点可用内存不要用总内存做判断。另外在任务描述文件里加一个memory_buffer参数默认是申请量的1.5倍。求解器本身也可以设置内存上限比如ANSYS的-m参数超了会报错而不是被系统杀掉。4.4 结果文件太大导致后处理超时现象求解完成但后处理脚本跑了两个小时还没出结果最后超时失败。原因瞬态分析的结果文件可能几十GBPython脚本逐行读取太慢。解决后处理不要读全量结果只读需要的时间步和节点。用求解器自带的后处理工具做批量提取比如ANSYS的/POST26或Abaqus的abaqus python脚本。如果一定要用Python用numpy的内存映射模式np.memmap不要一次性加载。4.5 工业APP参数单位不统一导致结果错误现象用户输入弹性模量210000以为是MPa实际模板里按Pa处理结果应力大了1000倍。原因不同求解器的单位制不同。Abaqus常用吨-毫米-秒制ANSYS常用千克-米-秒制用户不一定清楚。解决在工业APP前端明确标注单位并且在模板渲染时做单位换算。我一般会在后端加一个单位校验层如果用户输入的数值超出合理范围比如弹性模量小于1000或大于1000000就弹出警告让用户确认。5. 数字仿真平台的验证方法与一个实用技巧5.1 怎么验证平台仿真结果的可靠性平台化仿真最怕的是“算出来了但结果是错的”。验证方法分三步。第一步基准算例对比。选一个标准算例比如悬臂梁端部受集中力理论解是PL³/(3EI)。在平台上跑一遍和理论值对比误差应在5%以内。这一步验证的是求解器本身没被容器化搞坏。第二步跨节点一致性验证。同一个算例分别在两个不同配置的节点上跑结果应该完全一致。如果不一样说明浮点运算或并行策略有问题。我一般会跑三次取平均值和标准差。第三步回归测试。每次平台升级调度器、存储、镜像自动跑一遍基准算例集确保结果没漂移。这个用Jenkins或GitLab CI就能做。# 回归测试脚本片段 #!/bin/bash # 提交基准算例并检查结果 RESULT$(curl -s -X POST http://platform/api/jobs \ -H Content-Type: application/json \ -d benchmark_job.json | jq -r .job_id) # 等待任务完成 while true; do STATUS$(curl -s http://platform/api/jobs/$RESULT | jq -r .status) if [ $STATUS completed ]; then break elif [ $STATUS failed ]; then echo 回归测试失败任务执行错误 exit 1 fi sleep 10 done # 提取结果并对比 MAX_STRESS$(curl -s http://platform/api/jobs/$RESULT/result | jq -r .max_stress) EXPECTED123.45 THRESHOLD0.05 if (( $(echo scale4; ($MAX_STRESS - $EXPECTED) / $EXPECTED $THRESHOLD | bc -l) )); then echo 回归测试失败结果偏差超过5% exit 1 fi echo 回归测试通过这个脚本提交基准算例轮询任务状态完成后提取最大应力和预期值对比。参数说明THRESHOLD是允许偏差结构分析一般设5%流体分析可以放宽到10%。5.2 一个实用技巧用任务标签做成本归集仿真平台跑起来之后老板一定会问“这个月仿真花了多少钱”。如果平时没做成本归集月底只能拍脑袋。我的做法是在任务描述文件里加一个cost_center标签调度器每次调度时记录核时消耗月底按标签汇总。# 带成本标签的任务描述 job: name: crash_test_001 cost_center: project_A resources: cpu: 16 memory: 64Gi然后在数据库里建一张机时消耗表CREATE TABLE cost_log ( id SERIAL PRIMARY KEY, job_id VARCHAR(64), cost_center VARCHAR(64), cores INT, start_time TIMESTAMP, end_time TIMESTAMP, core_hours FLOAT ); -- 月底汇总 SELECT cost_center, SUM(core_hours) AS total_core_hours FROM cost_log WHERE start_time 2021-06-01 AND end_time 2021-07-01 GROUP BY cost_center;这个表在任务开始时插入记录结束时更新end_time和core_hours。core_hours的计算方式是cores * (end_time - start_time)的小时数。月底按cost_center汇总就能知道每个项目花了多少机时。我自己的习惯是每次平台上线新功能之前先跑一遍基准算例集确认结果没漂移再发布。这个习惯帮我避免了好几次因为调度器改动导致的计算结果异常。数字仿真上云这件事技术上的坑大多有解真正难的是让用惯了单机的人相信平台算出来的结果是对的。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

AUTOSAR RTE深度解析:从VFB到通信机制与任务映射

AUTOSAR RTE深度解析:从VFB到通信机制与任务映射

第一次在AUTOSAR项目里听到RTE这个缩写,我以为它只是个普通运行库。直到自己动手搭了一个涉及三个SWC的通信Demo,被一堆偶发数据错乱和任务超时折磨了两周,才真正意识到这一层的分量。不管你是刚接触AUTOSAR的学生,还是正在做ECU软…

2026/10/13 18:53:55 阅读更多 →
工业互联网平台数字仿真:CAE云化落地与工业APP封装实战

工业互联网平台数字仿真:CAE云化落地与工业APP封装实战

简介:《工业互联网平台数字仿真发展白皮书(2021)》由中国电子信息产业发展研究院编写,面向制造业数字化转型从业者、工业软件研发人员及产业政策研究者,系统梳理“平台数字仿真”的发展脉络与落地路径。资源为1个PDF文…

2026/10/13 18:53:55 阅读更多 →
Agent能扛多大的事?四维承重设计与压测实战

Agent能扛多大的事?四维承重设计与压测实战

你的Agent,能扛多大的事儿?这个问题我最近被问得最多,不是来自那种刚看完发布会的新手,而是来自已经折腾过几轮 prompt、堆过不少工具、把 demo 跑得飞起、但一碰真实业务就崩盘的中级玩家。大家手里都会有个能聊天、能查资料、能…

2026/10/13 18:52:55 阅读更多 →

最新新闻

Nano Banana 2.1降价背后:API账单未减半的三大原因

Nano Banana 2.1降价背后:API账单未减半的三大原因

Nano Banana 2.1降价了,价格直接腰斩。按常理想,原来一个月花100元的API调用费,现在应该50元就够了。可我这几个月盯着账单数据,发现事情远没有这么简单——有些月份总花费只降了10%出头,甚至有一个周五的峰值账单比降…

2026/10/13 19:39:21 阅读更多 →
Git四部曲:add、commit、remote、push的本质与实操

Git四部曲:add、commit、remote、push的本质与实操

1. 项目概述:为什么“四部曲”这个说法在Git实操中如此根深蒂固你刚学Git时,是不是也听过这句话:“上传文件就四步——add、commit、remote、push”?我第一次带某高校开源社团做代码托管训练时,发现92%的新人把这四步当…

2026/10/13 19:39:20 阅读更多 →
数学建模B题穿越沙漠:Matlab动态规划源码拆解与调优

数学建模B题穿越沙漠:Matlab动态规划源码拆解与调优

简介:面向数学建模2020年B题的Matlab源码包,适合正在备战建模竞赛、需要参考完整赛题编程实现的学生和培训团队。资源围绕四关递进式求解展开,重点解决第二关双地图双村庄下的矿山与补给选择、第三四关天气不确定时的路线规划,并对…

2026/10/13 19:39:20 阅读更多 →
dlib 19.20.0 VS2019 预编译包:免编译配置与集成避坑指南

dlib 19.20.0 VS2019 预编译包:免编译配置与集成避坑指南

简介:这是一份针对Windows 64位平台的dlib 19.20.0预编译资源包,采用VS2019(msvc1928)编译的release版本,面向需要在C项目中快速集成dlib的开发者,适用于图像处理、机器学习和计算机视觉等场景。包内共1032…

2026/10/13 19:39:20 阅读更多 →
两堵墙之间:数据不出域与云端协同的六次门禁迁移

两堵墙之间:数据不出域与云端协同的六次门禁迁移

如果你也站在“数据不出域”和“模型效果跟不上”这两堵墙之间犹豫过,那这个标题应该能让你会心一笑。我估计不少同行都有过类似的阶段:本地推理服务器与云端协同,听起来像一句无比正确的废话,真落地起来才知道,单是“…

2026/10/13 19:39:20 阅读更多 →
Cursor额度重置教程:设备指纹清理实现合规续杯

Cursor额度重置教程:设备指纹清理实现合规续杯

简介:本资源是面向软件开发者的 Cursor 编辑器 11 月续杯实战源码包,聚焦解决免费用户模型调用受限、账号续期繁琐等实际痛点,适用于中初级开发者快速提升 AI 编程效率。压缩包共 3 个文件,含 .inscode(Cursor 插件配置…

2026/10/13 19:38:20 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →