news 2026/9/17 5:42:18

用大模型将聊天记录自动写入CRM:JSON结构化提取全链路实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用大模型将聊天记录自动写入CRM:JSON结构化提取全链路实践

我们团队半年前接了一个挺头疼的需求:销售每天在企业微信、电话、面谈里产生大量沟通记录,但 CRM 里的跟进记录永远是滞后的,甚至很多高价值客户信息就烂在聊天记录里没人理。老板说,“你们能不能把聊天记录自动变成 CRM 的客户档案?”当时市面上有各种号称 AI 能提取信息的工具,真正落到自研 CRM 里批量写入的却很少。于是我们做了个小工程,核心思路一句话:用 LLM 把非结构化沟通记录转成 JSON,再通过一致性校验和幂等设计批量写进 CRM。整个过程踩了不少坑,今天把这个项目的完整实践过程梳理出来,希望能给正在做类似“AI 数据管道”的同学一点参考。

这个方案适合谁?如果你所在公司有自研或可 API 对接的 CRM,手头有大量微信/企微对话、通话转写文本、邮件等非结构化沟通数据,并且希望把这些数据变成可作为销售跟进依据的结构化字段——本文的完整链路、提示词设计、批处理容错和成本优化方案,都可以直接抄作业。

1. 项目背景与整体方案设计

1.1 业务痛点:一切从“会话存档没人看”开始

我们公司接了企微的会话存档接口,每天大概产生 3 万条左右聊天消息,来自销售和客户的日常沟通。但有一个尴尬的事实:数据存了,没人看。企微自带的会话存档界面又难用,销售和销售主管根本不可能一条一条去翻聊天记录。结果就是,客户在对话里已经明确说了“下个月有点预算,你出个方案吧”,这种高意向信号没人捕捉,甚至客户流失了都没人知道。

传统的做法是让销售手动填 CRM,在跟进记录里写“电话沟通了,客户有意向”,稍微好一点的团队会要求销售在聊天结束以后补充客户意向等级和下一步计划。这套机制的问题也很直接:销售不愿意填,填了也不准,填了不及时。90% 的客户信息都散落在非结构化文本里。

所以我们内部定了一个目标:做一个处理器,把“原始沟通文本”自动变成一张结构化的“客户跟进卡片”,字段包括客户姓名、意向等级、核心需求描述、下一步动作、下次跟进时间,然后批量写进现有 CRM。如果这一步跑通了,销售主管每天早上看到的 CRM 就不是昨天销售自己填的“无效跟进”,而是从真实对话里提取出来的有效情报。

1.2 为什么这活 LLM 能干:关键可行性判断

其实最早我们想过纯规则方案,因为提取的字段看起来不算复杂。后来发现规则方案必死:同一句话在聊天场景里有无数种表达,“下周”“周内”“月底前”“等领导批了再说”,这些时间表达靠正则去匹配根本写不干净,更别提客户名称不完整、客户意图隐含、中英文夹杂、各种口语化表达的问题。

LLM 在做这件事上的核心优势在于它能“理解语义后填表”。你给它一段对话,它能判断客户是真有意向还是纯客套,能把“我大概月底能定”转成时间戳,能把“我们现在用的系统太卡了”识别为痛点描述。这些能力在大模型普及之前需要做一整套 NER(命名实体识别)+意图分类 + 关系抽取的流水线,费时费力不说,换一个业务场景又要重新做标注。

我们当时做了一个小验证:随机抽了 50 段真实聊天记录,人工写清楚提取规则,用大模型跑了一遍,人工评估准确率达到 90% 以上,其中意向等级这类主观字段的准确率稍低但也在可接受范围。这个验证决定了项目从“可能做”变成“立刻做”。

1.3 整体技术方案:一条从原始记录到 CRM 的数据管道

整个系统我们设计成四个环节,环环相扣:

  • 采集层:企微会话存档接口拉取原始消息,按会话(同一个客户+同一个销售的对话)聚合,加上 ASR 转写出来的电话录音文本作为补充数据源。
  • 提取层:调用 LLM,把聚合后的会话文本输入模型,模型按预设 JSON Schema 输出结构化字段。这里的关键是 JSON Schema 必须强约束,不能用自由文本。
  • 审核层:结构化结果进入一个“待写入区”,由规则引擎判断置信度。高置信度的直接进入 CRM 自动写入队列,低置信度或解析失败的去人工审核台,由运营或销售主管在页面上批量确认/修改。
  • 写入层:通过 CRM 的 OpenAPI 批量创建/更新客户记录、跟进记录,写入之前做幂等和去重校验。

为什么中间要有一个审核层?因为沟通记录是要写进正式客户系统的数据,一旦写错,比如把客户 A 的需求写到客户 B 名下,后面所有销售动作都会带偏。全自动不是不行,但团队要有试错和兜底机制,前一个月我们一直是高置信度自动写入 + 人工抽检,稳定之后才逐步放开。

1.4 模型与框架选型:效果、成本与自控的平衡

模型选型是第一个需要拍板的决策。我们最初接的是 Claude 和 GPT 两条线,后来又加了国产模型做备用,实测下来主流闭源模型在处理中文口语对话、输出 JSON 稳定性上都有不错表现。关键在选择标准:

  • 上下文窗口:会话聚合后经常超过 8K token,窗口太小的模型会把对话截断,导致后半段信息消失。建议至少要 16K 以上的上下文。
  • 结构化输出能力:这个很重要。有些模型虽然文本生成能力强,但输出 JSON 时经常混入解释性文本。优先选支持 JSON mode / Structured Output 的模型和 API。
  • 成本与延迟:每段对话平均 2K token 输入 + 0.5K 输出,按当时闭源模型定价估算,单条会话成本在几分钱到一毛钱区间。日均处理 500 段会话,成本在可接受范围,但如果做全量历史数据回溯,累计起来就要认真做成本控制了。

框架层面,我们没有引入重型 LLM Agent 框架,因为这件事本质是“单轮结构化提取任务”,不需要多轮工具调用,也不依赖 Agent 记忆。直接用模型厂商的 Python SDK 或 OpenAI 兼容接口,自己封装一层调用逻辑即可。引入 LangChain 这类框架反而增加一层抽象,出问题排查麻烦。这是一个我当时特别想强调的选型原则:能简单就不要复杂。

2. 结构化提取的工程细节:Prompt、Schema 与数据清洗

2.1 让大模型学会“填表”:JSON Schema 强制约束

结构化提取的第一个难点,是让模型输出的格式稳定可控。我们最开始的做法是直接在 Prompt 里写“请用 JSON 格式输出这些字段”,结果模型时不时在 JSON 外面包一层 markdown 代码块,偶尔还会多出解释性文字。后来我们统一改成:

  • 使用支持 JSON mode 的接口参数,让 API 层强制输出合法 JSON。
  • 在 Prompt 中提供严格的 JSON Schema 定义,字段名、类型、枚举值逐一说明,并在末尾附上一个 few-shot 示例,展示“输入对话 → 输出 JSON”的完整对应关系。

这里说的 JSON Schema 不是只写一个字段清单,而是要尽量把边界条件也写清楚。比如“意向等级”只允许取“高/中/低/未知”四个枚举值,模型默认倾向标“高”,我们就得在 Schema 描述里加一句:只有在客户明确表达采购预算或时间节点时才能标“高”,否则按“中”或“未知”处理。

输出示例:

{ "customer_name": "王总", "phone": "138****1234", "intention_level": "中", "need_description": "现有 OA 系统卡顿,希望替换为低代码平台", "next_action": "发送产品介绍文档并预约下周二演示", "next_follow_up_date": "2025-06-10", "summary": "客户对当前系统不满,有替换意向,需跟进演示" }

最终我们在系统里对 JSON 输出做两层校验:第一步是 JSON 语法解析,第二步是字段级校验(类型、枚举值、日期格式),任何一步失败都进入重试队列。重试时会把上一次解析出的错误信息拼回 Prompt,让模型自己修正。这个“错误修复循环”帮我们把 JSON 解析失败率从一开始的 7% 压到了 0.5% 以内。

2.2 字段设计:业务字段不是越多越好

一开始产品经理给的字段清单有 20 多个,什么客户预算区间、采购角色、竞品信息、客户情绪……LLM 都能给你填出来,但填出来不意味着能用。字段越多,模型出错概率越大,运营审核成本越高,写进 CRM 后真正被销售使用的字段却很少。

我们最后砍到 8 个核心字段:客户姓名、联系方式、意向等级、需求描述、下一步动作、下次跟进日期、会话摘要、备注。这 8 个字段是销售主管最需要的。其中“意向等级”和“下次跟进日期”这两个字段是后续自动生成销售待办的数据基础,必须有,其余能砍则砍。

字段设计有一个原则:能靠系统加工的就不要让模型去理解。比如客户所属行业,我们本来想让 LLM 判断,后来发现 CRM 里本身有客户行业的入口,销售建客户时会填,这个字段就不需要提取。手机号的提取也别完全依赖 LLM,可以用正则从原文里先捞一遍,把正则命中的号码交给模型做匹配确认,正规率明显提高。

2.3 对话文本的预处理:先剪枝,再投喂

直接拿原始消息去调 LLM 的做法我们试过,效果差。原因是企微会话存档里有大量噪音:图片消息转出的 OCR 文本片段、视频号卡片、小程序链接、群聊里的无关发言、以及销售和客户互相发的“收到”“好的”这种寒暄消息。这些内容白白占用 token,还会干扰模型判断重点。

所以我们在投喂之前做了一次文本剪枝:

  • 过滤系统消息、撤回消息、红包消息。
  • 去掉会话中的图片链接、文件消息体,只保留文本。
  • 去掉单个文本消息超过 300 字的长篇大论,这类一般是销售复制粘贴的合同条款或产品手册,不是有效沟通信息。
  • 对连续寒暄消息(如“早”“在吗”“嗯嗯”)做合并压缩。

剪枝之后再做聚合。企微的会话存档是一天一个文件,同一段对话可能跨越两天。我们用“客户 customer_id + 销售 user_id”作为会话聚合键,把一个自然周内的消息合并成一段完整对话。合并时按时间排序,如果中间间隔超过 2 小时就切成两个话轮,避免把不同主题的沟通混在一起。

2.4 异常与兜底:处理“非销售对话”和“解析失败”

这个点很实际。我们跑了一周后发现,大约有 20% 的会话根本不是有效的销售沟通,比如客户发了一句“在吗”销售没回,或者两个人互发“节日快乐”,这种对话根本没有提取价值。如果强行提取,模型会给你编造意向等级和需求描述,非常危险。

处理方式是加一个预筛步骤:在正式提取前,先让模型判断这段对话是否包含业务价值。输出一个布尔字段 has_business_value,如果为 false,直接跳过提取,不生成 CRM 记录。这个预筛步骤的 Prompt 非常简单,只让模型输出 true/false,成本极低,但能规避大量无效写入。

另外还碰到一个场景:客户明确表示“这事你别管了”或销售已经跟单结束,这种负向信号也要识别出来。我们在 Schema 里加了一个 status 字段,允许值为 active(跟进中)/ lost(战败或已终结)/ pending(待确认),并让模型对 status 为 lost 的会话强制输出战败原因。

3. 从 JSON 到 CRM:批量写入的完整链路

3.1 中间层设计:待审核区与自动写入区

LLM 提取出来的结果不能直接 write-through 到 CRM 主库,我们设计了两个中间区域:staging 表和审核队列。

Staging 表保存全量提取结果,核心字段包括:会话 ID、来源渠道、原始消息摘要、LLM 返回的完整 JSON、解析后的结构化字段、模型名和版本号、Token 消耗量、处理状态。这张表的核心价值是留痕——任何时候发现写进 CRM 的数据有问题,都能从 staging 表回溯到原始请求和模型响应。

状态为“自动通过”的记录,由一个定时任务每 5 分钟扫描一次,批量调用 CRM 接口写入。状态为“待人工审核”的记录,进入一个极简的审核页面,页面展示对话摘要(原始消息脱敏后)+ 模型提取结果,运营人员只需要确认或修改几个关键字段,确认后一键入库。

这里要注意一个节奏问题:批量写入的粒度和频次不要设计得太激进。我们一开始做成实时写入,结果 LLM 服务偶尔抖动导致下游 CRM 出现重复请求,排查起来很麻烦。后来改成每 5 分钟一个批次,批内做去重和校验,出问题的概率小很多,排查也方便。

3.2 并发控制与限流:别把模型供应商打爆

LLM 提取服务和模型 API 之间也要做并发控制。我们用的是信号量限制同时进行的请求数量,并给每个请求设置超时时间。一个常见的坑是:把企微会话存档按会话聚合后,有的会话消息数量特别大(超过 100 条消息),输入 Token 数会超过模型单次调用上限。这种会话我们实行“滑动窗口切段”:每次只送最近 20 条消息 + 上一个窗口的结构化摘要,既控制 Token 数,又能保留对话上下文。

限流参数的确定不能拍脑袋。我们根据模型供应商的 RPM(每分钟请求数)和 TPM(每分钟 Token 数)上限,倒推本地队列的处理速率。举个例子:如果模型 API 限制 RPM=60,我们本地就把并发数设为 30,每秒处理 0.5 个请求,留出 50% 的余量给其他业务服务。这样在高峰期也能避免 429 限流错误。

写 CRM 接口也一样,现成 CRM 的 OpenAPI 通常有频次限制。一开始我们一次性并发写入 200 条,直接把 CRM 的 API 打挂了。后来改成每批 50 条、批间隔 1 秒,从监控上看效果稳定,不再触顶限流。

3.3 写入 CRM 的幂等与容错:重复会话不重复建单

批量写入最大的坑是重复。同一个会话可能被处理两次(比如消息延迟到达重组了会话),LLM 结果也生成了两条记录,写进 CRM 就会产生重复的客户跟进记录。我们的解决办法是设计一个幂等键:用“source_type + external_session_id + process_date” 作为唯一业务键。

CRM 的用户表如果已经存在该客户(通过手机号的单向哈希匹配),则走更新逻辑而不是新建客户;跟进记录表则通过 business_key 做唯一约束,重复写入时直接跳过。这个逻辑写进写入服务的开头,批量处理前先查一次库里是否已有对应键,有则更新字段,无则新建。上线三个月,重复记录率基本为零。

另一个容错点是 CRM 接口返回错误时的处理。如果响应是 4xx 错误(如参数校验失败),说明是我们这边的问题,直接记录错误日志,把消息转入人工处理队列。如果是 5xx 错误或超时,说明 CRM 服务暂时不可用,消息进入延迟重试队列,采用指数退避策略:1 分钟、5 分钟、30 分钟后重试,最多重试 5 次。超过重试次数进死信队列,由人工介入。

3.4 监控与审计:每条数据都查得到“祖先”

系统上线后,最容易被忽略的就是监控。我们后来补了一套完整的指标和日志体系,这里给个清单,建议直接参考:

  • 各环节处理量:采集量、预筛通过量、提取成功量、写入成功量、人工触发量。
  • 处理耗时分布:LLM 调用耗时 P50/P95/P99,写入 CRM 耗时 P95。
  • 结构化提取质量指标:JSON 解析失败率、字段校验失败率、人工审核通过率(审核人员没有修改直接确认的比例)。
  • 成本指标:每日 Token 消耗量、每千次提取的模型成本、按场景分组的 Token 消耗占比。

审计日志这里花了点功夫,最终我们实现的效果是:从 CRM 里任意一条自动生成的跟进记录,点击详情能一路查到它的原始会话 ID、LLM 请求的 Prompt(含原文)、模型返回的 JSON、命中的人工审核操作记录。这个“数据血缘”能力在出问题追责时作用巨大。有一次客户投诉销售人员泄露了信息,我们事后审计发现,那条数据其实来自销售人员在其他渠道填写的,不是系统自动写入的——审计链路帮团队洗清了误会。

4. 常见问题与排查技巧实录

4.1 JSON 解析失败和字段跑偏

这个问题主要出现在模型版本升级后。原本正常的提取任务,升级模型版本后突然出现大量 JSON 外层多一个 markdown 代码块的输出。我们的排查思路:先看是单次失败还是批量失败,单次失败大概率是输入文本中有特殊字符(比如乱码、异常符号),批量失败大概率是模型配置或参数变了。后来我们在调用层统一加了正则清理逻辑,只抽取 JSON 大括号范围内的内容再做 json.loads,解析成功率从 94% 提升到 99.5%。

另外一个窍门:Prompt 里的字段说明和示例一定要和 JSON Schema 保持一致,一旦不一致,模型就会选择性跟随。我们曾经在系统提示词里写“输出字段 follow_up_date”,但示例里写成了“next_follow_up_date”,导致模型有时输出这个键、有时输出那个键,字段校验全挂了。排查半天才发现是低级错误,后来在 CI 流程里增加了一个自动化测试,用固定输入样本去跑模型,确保格式和字段名稳定后才允许部署。

4.2 提取结果不准:漏提、错提、幻造信息

“幻造”是 LLM 提取场景最危险的问题。模型会在需求描述里填写一些原文完全没有提到的信息。比如原始对话是“我们想了解下系统”,模型输出需求描述为“客户要求系统支持多人协同和移动端”,这明显是模型自己脑补的。

我们的对策有三层:

  • 第一层,在 Prompt 里强制要求:所有输出字段必须严格基于原文,原文没有提到的内容一律填 null 或“未知”,不允许推测。
  • 第二层,在 Schema 里为描述类字段增加 max_length 限制和“基于原文概括”的指令。
  • 第三层,抽检兜底。人工审核页面里,把原始对话文本高亮展示在模型输出旁边,运营人员一眼就能看出来模型是不是在编。如果某类场景幻造比例偏高,就把这类场景的 few-shot 示例替换成更强的反例。

漏提的问题通常发生在长对话里,客户在中间提到“这个方案挺好的”然后又开始聊别的,到结尾这个信息就被模型忘了。解决方式是滑动窗口切段的时候保留上一段摘要,并在下一段 Prompt 开头加一句“以下是上一段对话摘要,请综合参考但以最新消息为准”。这个问题也让漏提率从 11% 降到了 4% 左右。

4.3 重复写入与数据漂白

两个层面的重复:会话级重复和 CRM 客户级重复。

会话级重复上面已经说了解法,用幂等键。客户级重复更隐蔽:同一客户可能在不同渠道多次沟通,企微会话存档里他是“王总”,电话录音转录里他是“王明”,CRM 里客户名是“北京某某科技有限公司”。这个关联问题,我们没让 LLM 去做,太复杂了,改成了规则匹配:优先用手机号做关联,没有手机号的用“公司名模糊匹配 + 联系人来判定”。效果有限,但比完全没有强。

客户名提取不准是另一个高频问题。模型可能从对话里抓到一个别名“老王”“王哥”“姐”,这些称呼不适合直接作为客户姓名写入。我们在字段校验里加了一个禁止名单:包含“哥”“姐”“老”“先生”“女士”“老板”的姓名一律不通过,交由人工编辑。这个规则简单粗暴,但有效避免了 CRM 里出现一堆“张总”“李姐”的脏数据。

4.4 成本与延迟的平衡技巧

模型成本在跑量之后会非常可观,尤其是历史数据回溯阶段。我们做过几轮优化,效果显著:

  • 按会话长度动态选模型:短对话(少于 500 token)用便宜的小模型,长对话才走大模型,成本下降约 30%。
  • 缓存预筛结果:同一个会话如果第一次预筛判定为无业务价值,存一个 hash 标记,下一次不会再重复调用模型。
  • 批处理合并请求:支持 JSON mode 的模型可以一次输入多条会话、输出一个 JSON 数组。我们把 5 段短会话合并为一次调用,单次调用成本降低了将近一半。
  • 设置预算上限:供应商那边设了一个每月费用告警线,触线后自动把任务切换到一个更便宜的模型,保证系统不会因为账单失控而挂掉。

延迟方面,P95 单次提取耗时从最早的 3 秒优化到 1.2 秒。核心优化点是减少输入内 token 量,把无关的寒暄消息删干净,Prompt 里的示例也从 3 组减到 2 组。说实话,做批处理不太追求单条延迟,关键是吞吐量稳定,能把当天的会话在凌晨全部处理完就行。

5. 落地后的扩展:从“能写进 CRM”到“真有用”

5.1 用结构化结果为销售团队生成待办提醒

数据写进 CRM 只是第一步,真正让这套系统产生业务价值的是后续动作。我们把“next_action”和“next_follow_up_date”两个字段接入了 CRM 的待办模块。每天早上 9 点,系统自动给对应销售推送一条待办:“今天该跟进客户王总了,上次沟通摘要:客户对现有系统不满,下一步动作是发送方案并预约演示。”

这比销售自己定闹钟记跟进的体验好太多,主管也不用天天催。上线两个月后,销售对自动生成待办的接受度非常高,甚至开始主动要求系统把“客户说了要方案”这种有强烈信号的消息更早推送出来。这一步让我们从“数据搬运工”变成了“销售助理”。

5.2 按会话热度给客户打标签

把历史三个月的沟通记录批量处理后,我们按客户维度的会话数量、意向等级变化、需求集中度做统计分析,给每个客户打上了“高活跃”“需求明确”“久未跟进”等标签。这些标签直接显示在 CRM 客户列表里,销售的跟进排序就从“凭感觉”变成了“按系统提示”。

5.3 把人工审核的数据变成模型微调数据

这是我觉得最有长期价值的一件事。人工审核台每天都会产生大量人工修正后的高质量“输入-输出”对。我们把“修正前模型输出”和“修正后人工结果”收集起来,按周维度导出,作为模型的候选微调数据集。虽然我们还没有做真正意义上的模型微调,但这份数据资产已经非常值钱,未来如果要上垂域模型或做小模型蒸馏,这是最现成的训练语料。

这里也提醒一句:收集人工修正数据时一定要做隐私处理,客户姓名、手机号、企业名等敏感信息要做脱敏,尤其是从聊天记录中提取的数据,合规意识必须前置。我们是在项目初期就让法务和运维介入了数据存储和访问权限的设计,避免后期出问题。

另外提一个经验:聊天原始数据中有大量客户隐私,不要把它们直接存到模型提供商的日志系统里。我们所有发送给模型的 Prompt 都会先做脱敏替换,把手机号、姓名替换成占位符,模型返回后需要写库时再做一次反向映射。这样既保证提取效果,又守住隐私底线。这块坚持做,和客户沟通数据授权的时候就少很多麻烦。

写在最后的体会

这项目做下来最深的感触是:LLM 结构化提取的难点从来不在于调用模型,而在于上下游工程——数据清洗、格式约束、幂等去重、人工审核、成本控制、审计留痕,每一环都比模型调用本身更考验工程功底。如果上来就想全自动一把梭,大概率会被数据质量问题折磨到崩溃。稳妥的做法是:先用半自动跑通闭环,积累一批人工修正数据,把业务信任度建立起来之后,再逐步提高自动处理的比例。这套路子我们验证过,走得通,希望对正在做类似方向的同学有帮助。如果你也在做 LLM 提取 CRM 落地的项目,欢迎一起交流踩坑经验。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 5:41:40

Doris与ClickHouse选型指南:OLAP场景下的SQL兼容性与实时更新对比

1. 这不是选“哪个更好”,而是选“谁更对路”:一张表讲透 Doris 和 ClickHouse 的本质分野最近在给一家做实时BI平台的客户做技术选型,他们卡在 Doris 和 ClickHouse 之间反复横跳——前端报表要秒级响应,数据源每天新增2亿行&…

作者头像 李华
网站建设 2026/9/17 5:41:27

HR从业者学习心理咨询的职场价值 中国心理学会心理咨询师水平评价-心理咨询培训机构

HR从业者学习心理咨询的职场价值 中国心理学会心理咨询师水平评价-心理咨询培训机构 心理健康是全民健康的重要组成部分,心理咨询师则是守护公众心理健康的专业力量。随着中国心理学会心理咨询师水平评价等级考试的全面推行,行业准入门槛更加规范化、专业…

作者头像 李华
网站建设 2026/9/17 5:41:20

MuJoCo机械臂角速度实时监控与可视化方案

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

作者头像 李华
网站建设 2026/9/17 5:39:57

Java集成PaddleOCR表格识别:从图片到HTML与Excel导出

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

作者头像 李华