Claude Code源码包实战:终端AI编程代理的架构解析与避坑指南
简介这份源码资料包面向希望借助AI提升编码效率的开发者与编程学习者围绕Anthropic推出的Claude Code展开系统梳理其代码理解、生成、调试优化、多语言支持与长上下文窗口等能力并覆盖访问方式、典型应用场景、使用技巧、与ChatGPT Code Interpreter的对比及常见问题解答帮助读者快速建立对该AI编程助手的整体认知。资源包共3个文件以html页面、inscode配置与gitignore忽略规则为主压缩后约6KB体量轻便便于直接查阅与本地集成参考。目前已有655人学习下载说明其在AI编程工具方向具备一定关注度。读者可从中获取Claude Code的功能定位、实战集成思路与排错参考并借助源码结构理解项目组织方式适合作为入门了解与日常开发辅助的参考材料。1. 从终端到代码库为什么我把 Claude Code 当主力开发工具第一次听说 Claude Code 是在一个内部技术分享会上某开发者演示了如何在终端里用自然语言直接让 AI 读写整个项目目录、跑测试、改配置全程不离开命令行。当时我的第一反应是“这不就是个套壳 CLI 吗”直到自己把源码包拉下来跑通第一个任务才发现它和那些只会在聊天框里贴代码的 AI 编程助手完全不是一回事。Claude Code 的核心定位是终端原生的 AI 编程代理它直接运行在你的 shell 里能读取项目文件树、执行 bash 命令、编辑源码、跑 lint 和测试把大语言模型的推理能力嵌进真实的开发工作流。适合谁适合那些每天泡在终端里、项目结构复杂、不想在 IDE 插件和网页聊天之间反复横跳的工程师。源码包给了你完整的可审计能力你能看到它怎么组织上下文、怎么调工具、怎么处理权限而不是对着一个黑匣子许愿。2. 源码包拆解目录结构与核心模块的工程逻辑2.1 从入口文件看整体架构拿到源码包后别急着跑npm install先花十分钟把目录结构过一遍。常见的组织方式大致是src/下分cli/、core/、tools/、context/、providers/几个大块。cli/负责参数解析和交互循环core/是代理调度和会话管理tools/放的是文件读写、bash 执行、搜索这些原子能力context/管上下文窗口的裁剪和注入providers/对接模型 API。这个分层不是随便拍的它对应了一个关键设计决策把“模型决策”和“工具执行”彻底解耦。模型只负责输出结构化的工具调用请求真正碰文件系统和 shell 的是tools/层中间隔着一层权限校验和沙箱逻辑。# 典型的源码包目录结构以实际解压为准 claude-code-src/ ├── package.json ├── tsconfig.json ├── src/ │ ├── cli/ │ │ ├── index.ts # CLI 入口参数解析 │ │ └── repl.ts # 交互式会话循环 │ ├── core/ │ │ ├── agent.ts # 代理主循环调度模型与工具 │ │ ├── session.ts # 会话状态管理 │ │ └── permissions.ts # 权限校验与确认逻辑 │ ├── tools/ │ │ ├── file-read.ts │ │ ├── file-write.ts │ │ ├── bash.ts │ │ └── search.ts │ ├── context/ │ │ ├── builder.ts # 上下文组装 │ │ └── truncator.ts # 超长上下文裁剪策略 │ └── providers/ │ └── anthropic.ts # 模型 API 适配层 └── tests/这个结构里最值得关注的是core/agent.ts和core/permissions.ts。前者是主循环接收用户输入 → 组装上下文 → 调模型 → 解析工具调用 → 执行工具 → 把结果回灌 → 继续循环直到模型输出最终回答。后者决定了哪些操作需要人工确认、哪些可以自动放行。很多新手翻车就翻在权限配置上后面避坑章节会细说。2.2 上下文构建为什么它比聊天框更懂你的项目聊天框里的 AI 编程助手最大的问题是“看不见项目”。你贴一段代码它改一段但它不知道这段代码在哪个文件、被谁引用、项目用什么构建工具。Claude Code 的context/builder.ts解决的就是这个问题。它会在会话启动时扫描项目根目录识别package.json、tsconfig.json、.gitignore、README.md这些关键文件构建一个“项目画像”。然后根据当前任务动态决定把哪些文件内容塞进上下文窗口。// context/builder.ts 的核心逻辑示意基于常见实现模式 interface ProjectProfile { rootPath: string; language: string; framework?: string; entryPoints: string[]; ignorePatterns: string[]; } async function buildContext( profile: ProjectProfile, userQuery: string, maxTokens: number ): PromiseContextPayload { // 1. 加载项目画像中的关键配置文件 const configFiles await loadConfigFiles(profile.rootPath); // 2. 根据用户查询做关键词匹配找出相关源文件 const relevantFiles await searchRelevantFiles( profile.rootPath, userQuery, profile.ignorePatterns ); // 3. 按优先级排序配置文件 直接相关文件 间接引用文件 const ranked rankByRelevance(configFiles, relevantFiles, userQuery); // 4. 在 token 预算内裁剪超出部分做摘要而非直接丢弃 return truncateToBudget(ranked, maxTokens); }这段逻辑的关键参数是maxTokens它直接对应模型的上下文窗口大小。源码包里通常会把它做成可配置项默认值偏保守。如果你用的是支持长上下文的模型可以适当调大但别拉满——留出空间给工具执行结果回灌否则多轮任务跑到一半就会因为上下文溢出而中断。ignorePatterns默认会读.gitignore但node_modules、dist、.git这些目录一般会硬编码排除避免把整个依赖树扫进来。2.3 工具执行层文件读写与 bash 的权限边界tools/目录下的每个工具都是一个独立模块导出统一的接口接收参数、返回结果、抛出可捕获的错误。以file-write.ts为例它不会直接fs.writeFile就完事而是先做几件事检查目标路径是否在项目根目录内防止写到系统目录、检查文件是否已存在决定是覆盖还是追加、生成 diff 预览供用户确认。bash.ts更谨慎默认只允许执行白名单内的命令或者要求用户逐条确认。// tools/bash.ts 的权限校验示意 const SAFE_COMMANDS [ls, cat, grep, find, git status, npm test]; async function executeBash( command: string, options: { autoApprove: boolean; cwd: string } ): PromiseBashResult { const baseCmd command.trim().split(/\s/)[0]; // 非白名单命令必须人工确认 if (!SAFE_COMMANDS.includes(baseCmd) !options.autoApprove) { const approved await promptUser(即将执行: ${command}\n是否允许? (y/n)); if (!approved) { throw new Error(用户拒绝执行); } } // 限制工作目录防止越界 if (!isWithinProject(options.cwd, process.cwd())) { throw new Error(执行目录超出项目范围); } return execPromise(command, { cwd: options.cwd, timeout: 30000 }); }这里有个容易忽略的参数timeout。默认 30 秒对大多数命令够用但如果你让它跑全量测试或者构建很可能超时。源码包里一般会把这个值做成环境变量或配置文件项建议根据项目实际情况调到 120 秒以上。另外autoApprove模式在 CI 环境里很有用但本地开发时慎开——我见过有人开了自动批准结果 AI 把.env文件覆盖了血泪教训。3. 从零跑通第一个任务环境准备与最小闭环3.1 依赖安装与模型接入配置源码包跑起来的第一步是确认运行时环境。通常需要 Node.js 18 和 npm 或 pnpm。解压后进入目录先看package.json里的engines字段别硬上低版本否则 TypeScript 编译阶段就会报一堆语法错误。# 进入源码目录 cd claude-code-src # 确认 Node 版本 node -v # 建议 v18.17.0 或更高 # 安装依赖用 pnpm 通常更快没有就用 npm pnpm install # 复制环境变量模板 cp .env.example .env.env文件里最关键的是模型 API 的接入配置。源码包的providers/anthropic.ts一般会读ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL两个变量。前者填你的密钥后者如果你用的是兼容接口改成对应的地址。注意别把.env提交到 git源码包的.gitignore通常已经排除了但自己再确认一遍。# .env 配置示例 ANTHROPIC_API_KEYsk-xxxxxxxxxxxxxxxx ANTHROPIC_BASE_URLhttps://api.anthropic.com # 模型名称根据你实际可用的型号填 CLAUDE_MODELclaude-sonnet-4-20250514 # 上下文窗口 token 上限 MAX_CONTEXT_TOKENS180000 # bash 命令超时毫秒 BASH_TIMEOUT_MS120000MAX_CONTEXT_TOKENS这个值别照抄根据你实际用的模型来。设大了会导致请求被拒设小了频繁触发裁剪任务做到一半丢上下文。我一般会设成模型标称窗口的 80% 左右留出余量给工具返回结果。3.2 编译、启动与第一个自然语言任务依赖装完后看package.json的scripts字段通常有build、dev、start几个入口。开发模式用dev它会监听文件变化自动重启生产模式先build再start。# 编译 TypeScript pnpm build # 启动交互式会话 pnpm start # 或者直接跑开发模式 pnpm dev启动后你会看到一个 REPL 风格的提示符。第一个任务别上来就让它重构整个项目找个小的、可验证的目标。比如让它读某个文件并解释逻辑# 在 Claude Code 交互界面中输入 读取 src/core/agent.ts用中文解释主循环的执行流程并指出可能出错的边界情况它会先调用file-read工具读取文件然后把内容连同你的问题一起发给模型模型返回解释。整个过程你能看到工具调用的日志输出包括读了哪个文件、花了多少 token、模型返回了什么。如果这一步跑通了说明最小闭环已经打通。3.3 验证工具调用链是否完整光让它读文件还不够得验证写文件和执行命令的链路。找一个测试文件让它做一个小修改 在 tests/ 目录下创建一个 hello.test.ts写一个最简单的断言测试然后运行它正常流程是模型决定调用file-write创建文件 → 你确认写入 → 模型决定调用bash执行npm test或pnpm test→ 你确认执行 → 返回测试结果。如果中间任何一步卡住看日志里工具调用的参数和返回值。常见问题是bash工具的工作目录不对导致找不到package.json这时候检查cwd参数是否指向了项目根目录。提示第一次跑通后把整个会话的日志导出来存一份。后面遇到类似问题时对比正常日志和异常日志的差异比翻源码快得多。4. 避坑与排查源码包落地时最容易翻车的五个点4.1 上下文溢出导致任务中断现象多轮对话跑到一半突然报 token 超限错误或者模型开始“失忆”忘记前面说过的约束条件。原因context/truncator.ts的裁剪策略偏激进或者MAX_CONTEXT_TOKENS设得太大实际请求超过了模型窗口。另一种情况是工具返回结果太长比如bash执行了一个输出巨多的命令把上下文撑爆了。解决先把MAX_CONTEXT_TOKENS降到模型窗口的 70% 左右。然后在truncator.ts里确认裁剪优先级——配置文件和相关源文件应该优先保留工具执行的长输出应该被截断或摘要。如果经常跑输出量大的命令在bash.ts里加一个输出行数限制比如只保留最后 200 行。4.2 权限配置过松导致误操作现象AI 自动执行了rm -rf或者覆盖了重要配置文件没有弹确认框。原因autoApprove被设成了true或者SAFE_COMMANDS白名单里混进了危险命令。有些源码包的默认配置为了演示方便会把git相关命令全部放行但git checkout .这种命令会丢弃所有未提交修改。解决本地开发时autoApprove永远设false。检查SAFE_COMMANDS数组只保留只读命令ls、cat、grep、find、git status、git diff。写操作和可能修改状态的命令一律走人工确认。如果团队协作把这份白名单写进项目文档别让每个人自己改。4.3 模型返回的工具调用格式解析失败现象模型明明返回了工具调用请求但程序报“无法解析响应”或者“未知工具名称”。原因providers/anthropic.ts里对模型返回的 JSON 结构做了硬编码假设换了一个模型版本或者用了兼容接口返回格式有细微差异解析就挂了。常见的是工具名称大小写不一致或者参数嵌套层级不同。解决在解析层加一层容错。先尝试标准解析失败后做模糊匹配——工具名称转小写再比对参数字段做递归查找。同时把原始响应打到日志里方便定位。如果用的是兼容接口确认它是否完整实现了工具调用协议有些接口只支持文本补全不支持结构化工具调用。4.4 文件路径处理在跨平台时出错现象在 Windows 上跑文件读写报“路径不存在”或“非法字符”。原因源码里用了硬编码的/做路径拼接或者path.resolve的基准目录不对。Windows 的路径分隔符是\而且盘符和 UNC 路径的处理逻辑不同。解决全局搜索代码里的字符串路径拼接替换成path.join或path.resolve。检查tools/file-read.ts和file-write.ts里是否有startsWith(/)这种判断改成用path.isAbsolute。如果项目要跨平台在 CI 里加一个 Windows runner 跑基础测试。4.5 会话状态丢失导致重复劳动现象关掉终端再打开之前的对话上下文全没了得重新描述任务。原因core/session.ts默认只存在内存里进程退出就清空。有些源码包没有实现持久化或者持久化路径写死在了/tmp下重启就丢。解决看session.ts里有没有save和load方法。如果有确认存储路径是否可配置把它指到一个项目内的.claude-session/目录并加进.gitignore。如果没有持久化最简单的方案是把每轮对话的 messages 数组序列化成 JSON 写到本地文件启动时读回来。注意别把 API key 或者敏感文件内容写进去。5. 进阶技巧用自定义工具扩展代理能力边界源码包最大的价值不是开箱即用的功能而是它给了你一个可扩展的代理框架。tools/目录下的每个模块都遵循统一接口你完全可以照着file-read.ts的写法加一个自己的工具。我拿一个实际场景举例项目里有一套内部 API 文档每次让 AI 改接口相关代码时它不知道最新的字段定义经常改错。与其每次手动贴文档不如写一个api-lookup工具让它能按关键词查内部文档。// tools/api-lookup.ts 自定义工具示例 import { ToolDefinition, ToolResult } from ../core/types; import { readFileSync } from fs; import { join } from path; export const apiLookupTool: ToolDefinition { name: api_lookup, description: 根据关键词查询内部 API 文档返回匹配的接口定义, parameters: { type: object, properties: { keyword: { type: string, description: 要查询的接口名称或字段关键词 }, maxResults: { type: number, description: 最多返回几条结果默认 3 } }, required: [keyword] }, async execute(params: { keyword: string; maxResults?: number }): PromiseToolResult { const docPath join(process.cwd(), docs, api-index.json); const index JSON.parse(readFileSync(docPath, utf-8)); const max params.maxResults ?? 3; const keyword params.keyword.toLowerCase(); // 简单关键词匹配实际可以换成向量检索 const matches index.entries .filter((entry: any) entry.name.toLowerCase().includes(keyword) || entry.description.toLowerCase().includes(keyword) ) .slice(0, max); if (matches.length 0) { return { success: false, output: 未找到与 ${params.keyword} 相关的接口 }; } const formatted matches.map((m: any) 接口: ${m.name}\n路径: ${m.path}\n字段: ${JSON.stringify(m.fields, null, 2)} ).join(\n---\n); return { success: true, output: formatted }; } };写完后在tools/index.ts里注册一下重启会话就能用了。这个工具的关键参数是maxResults默认 3 条避免一次返回太多把上下文撑爆。api-index.json的格式可以自己定我一般用一个简单的数组每条包含name、path、description、fields四个字段。如果文档量大把关键词匹配换成向量检索效果更好但那就得再引入一个 embedding 模型复杂度上来了。注册工具的时候注意权限声明。自定义工具如果涉及网络请求或者文件写入在ToolDefinition里加一个requiresApproval: true字段让权限层知道这个工具需要人工确认。我见过有人写了个自动发 HTTP 请求的工具没加审批标记结果 AI 在调试时反复请求内部服务把测试环境打挂了。从那以后我每次加自定义工具都强制走一遍“只读测试 → 人工确认写操作 → 日志审计”的流程确认没问题再放开。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

厦门纯钛镜框选购全攻略:本土信赖之选——末禾MOHOE眼镜

厦门纯钛镜框选购全攻略:本土信赖之选——末禾MOHOE眼镜

在厦门配镜,职场人群挑选日常通勤的纯钛镜框、家长为孩子选购近视防控镜架时,普遍面临 “高价溢价” 与 “低价踩坑” 的两难:商场连锁品牌的进口镜框、纯钛镜架动辄数百上千元,营销溢价远高于产品本身价值;街边小店与…

2026/10/14 22:40:09 阅读更多 →
深入理解System V共享内存:多进程IPC高效通信实践与并发控制

深入理解System V共享内存:多进程IPC高效通信实践与并发控制

1. 共享内存是什么,为什么绕不开它搞过一段时间 Linux 服务端开发或者写过一些多进程程序的朋友,几乎都会撞上"进程间通信"这堵墙。进程和进程之间默认是各过各的,你改你的变量,我改我的变量,谁也看不见谁。…

2026/10/14 22:40:09 阅读更多 →
TCP拥塞控制实战指南:从慢启动到BBR的全链路优化

TCP拥塞控制实战指南:从慢启动到BBR的全链路优化

1. 为什么“拥塞控制”不是教科书里的抽象概念,而是你写的每一行TCP代码都在默默执行的生存法则很多人学完《计算机网络》教材里“慢启动”“拥塞避免”那几页,合上书就以为掌握了——直到某天自己写的后端服务在流量高峰时响应时间从50ms飙到2秒&#x…

2026/10/14 22:39:08 阅读更多 →

最新新闻

秋招网络岗VLAN面试全攻略:从原理到配置与排障

秋招网络岗VLAN面试全攻略:从原理到配置与排障

1. 秋招网络岗为什么绕不开VLAN这个知识点每年秋招,网络工程师、运维开发、云计算相关岗位的笔试面试里,VLAN出现的频率高得离谱。我翻过近几年的面经,也跟几个做过校招面试官的朋友聊过,发现一个规律:VLAN本身的概念不…

2026/10/14 23:28:03 阅读更多 →
Storm、Spark Streaming、Kafka Streams、Flink:流处理框架选型深度对比与实战指南

Storm、Spark Streaming、Kafka Streams、Flink:流处理框架选型深度对比与实战指南

流式处理这个领域,我差不多是从 Storm 还是绝对主流的时候就开始跟了,中间经历过 Kafka Streams 刚发布时大家观望的阶段,也踩过 Spark Streaming 把批次调小结果资源反而更紧张的坑,再到后来 Flink 逐渐成为很多团队的首选。这几…

2026/10/14 23:28:03 阅读更多 →
带载流子密度的双温模型:MATLAB有限元实现飞秒激光仿真

带载流子密度的双温模型:MATLAB有限元实现飞秒激光仿真

飞秒激光打金属或半导体薄膜,很多刚上手的人会被一张温度分布图问住:脉冲只有几百飞秒,怎么材料表面温度就上万K了?其实这里的温度并不是我们平时说的“材料温度”,而是电子子系统的温度。几百飞秒的激光脉冲&#xff…

2026/10/14 23:28:03 阅读更多 →
街景门牌号数据集解析:从标注处理到OCR/文本检测实战

街景门牌号数据集解析:从标注处理到OCR/文本检测实战

简介:这份街景门牌号数据集专为计算机视觉与图像识别任务设计,面向AI研究人员、算法工程师及参加相关竞赛的开发者,可用于训练和验证门牌号自动识别模型,支撑智能导航、自动驾驶、智慧城市等真实场景。包体共7个文件、约885MB&…

2026/10/14 23:28:03 阅读更多 →
AnyPS5实战:如何让任意设备获得PS5级游戏体验

AnyPS5实战:如何让任意设备获得PS5级游戏体验

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"PS5"这个关键词做文章的项目,而且"Any"这个前缀暗示了某…

2026/10/14 23:28:03 阅读更多 →
用C++实现最简PE加壳器:从解析文件到解密壳落地

用C++实现最简PE加壳器:从解析文件到解密壳落地

简介:这是一套面向C学习者和软件安全初学者的基础加壳实现源码包,围绕PE文件结构改造与程序入口点转移展开,完整演示了编写壳代码、注入保护逻辑、再封装可执行文件的过程。压缩包内共38个文件,体积仅1.47MB,涵盖10个头…

2026/10/14 23:26:59 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 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/13 22:01:27 阅读更多 →
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/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练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/14 7:53:34 阅读更多 →