恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

swagger-php 文档编写规范:写作约定、文档工具链与源码级准确性保障

  • 首页
  • 资讯中心
  • /
  • swagger-php 文档编写规范:写作约定、文档工具链与源码级准确性保障

相关资讯

GDAL 命令行帮助体系解析:`--help` 与 `--help-general` 的用法、输出差异与源码实现 2026/10/13 6:16:01
嵌入式工程师薪资困局:四维定价模型与职业跃迁指南 2026/10/13 6:16:01
GDAL 1.11.5 mingw32 在 Qt 工程中的集成与避坑指南 2026/10/13 6:16:01

最新资讯

AI做PPT终于不丑了!开源gpt-image2-ppt-skills让你自动生成PPT
毛坯房装修的正确流程是什么?
宝塔面板管理
【Bug已解决】PyTorch - RuntimeError: [enforce fail at inline_container.cc:209] . file not found: arc 解决方案
【Bug已解决】How to move PyTorch model to GPU on Apple M1 chips? 解决方案
宁波执业律师张娟:离婚后孩子判给谁——抚养权判断规则与争取要点梳理

今日推荐

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析
CAN总线错误处理机制深度解析:从位错误到Bus Off的硬件级调试

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

swagger-php 文档编写规范:写作约定、文档工具链与源码级准确性保障

发布时间:2026/10/13 6:16:01
swagger-php 文档编写规范:写作约定、文档工具链与源码级准确性保障 后端API设计文档代码生成【免费下载链接】swagger-phpA php swagger annotation and parsing library项目地址https://gitcode.com/gh_mirrors/sw/swagger-php点击查看免费下载本文是 swagger-php 项目维护者与贡献者编写文档、Pull Request 描述与提交信息时遵循的完整规范涵盖「事实只说一次」「细节只放一处」「复用而非复制」等核心写作原则以及文档结构、拼写、语气与逐项审查清单。文中同时结合 docs/dev/docs-toolchain.md 与tools/目录下的真实生成器源码、tests/DocsAccuracyTest.php 等测试佐证说明这些规范如何在 swagger-php 中落地为可自动校验的工程机制。读完本文你将掌握一套可以直接复用到任何开源 PHP 项目文档流程中的编写与校验方法。这些规则在哪里适用本规范的大多数内容讨论的是精确与克制这两点不会因为写作载体不同而改变。它们同时适用于docs/目录下的手写页面src/中的 docblock 注释Pull Request 描述与提交信息commit message。docblock 会被拼接到生成的参考页面中例如docs/reference/annotations.md由src/Annotations/的 docblock 生成所以一个不精确的 docblock 会以正式发布文档的形式对外呈现。换句话说注释质量直接影响发布质量。以下三个部分只针对文档页面不适用于 PR 描述和提交信息结构Structure拼写Spelling审查清单中与生成页面相关的条目。Pull Request 描述与提交信息的互补约束PR 描述描述的是这次变更只有在变更无法被理解时才补充上下文。工作是如何被发现的、还调查过什么、可能引出什么后续工作都不属于 diff 的一部分。CONTRIBUTING.md 中给出了模板和标题格式type(Scope): subject例如feat(Spec): add encoding shortcut。提交信息正文则相反它记录的是这个 diff 做了什么而不是它为什么存在。解释动机的句子属于 PR 描述。常规验证已通过测试也不是关于 diff 的事实——变更经过测试是默认假设在正文里写它等于什么都没说。事实只说一次不要重复页面自身结构已经确立的内容。例如 spec 管线的 beta 状态已经由以下多个载体共同承担docs/guide/modes.md 中的Status行章节标题中的(beta)::: warning Beta提示块版本时间线页面标题中的 图标。此时再写一句这是唯一没有标记 beta 的模式就毫无增量而且会随着上述那些真实载体独立腐烂。判断标准只有一个读者是否能从这句话中学到原本看不到的信息。仅仅读起来通顺是不够的。这条原则适用于成熟度、版本要求、该用哪个命名空间、某个模式做什么等所有内容。营销填充与复述填充是同一种缺陷。把稳定的、生产就绪的模式换成唯一没有标记 beta 的模式并不算改进。第三种形式是解释事实为什么重要的从句例如 which is what makes X possible、which matters because…、which is the point。这种从句本身不携带任何事实。直接陈述事实然后停止即可。如果一个事实的重要性无法从事实本身看出来那说明这个事实本身就是错的。细节只属于一个地方导览orientation可以出现在多个页面因为不同的人会从不同入口到达同一主题常常需要重复介绍。但具体细节detail绝不能被重复展开。同一份细节写两遍两份副本就会各自漂移而且没有任何机制能指出哪一份已经过时。有效的分工方式是按深度切分而不是按主题切分面向用户的页面说明某个东西做什么、为什么重要然后链接到更深处面向贡献者的页面承载机制、规则和精确清单两者互不重复对方的另一半。docs/reference/architecture.md与docs/dev/pipeline.md就是现成的范例。参考页面用一段话描述 Assembler 后链接到内部文档内部文档则独占 slot map、解析算法和根属性清单。在这次拆分之前两个页面用不同措辞各自描述了 slot map、augmenter 排序和类层次结构。当你要第二次写某个东西时那就是应该改成链接的信号。复用内容不要复制内容当同一段文字需要在多个输出中出现时应该把它提取出来再引入。复制是腐烂的根源。swagger-php 已经在使用两种机制docs/snippets/preamble_*.mdmarkdown 片段由参考文档生成器拼接到对应页面中。从源码看DocGenerator::snippetContent() 读取docs/snippets/preamble_{type}.md找不到文件时返回null找到时把内容追加到Renderer::preamble()生成的页面框架之后见 Renderer::preamble()。编辑片段即可更新生成页面。仓库中现存六个片段preamble_annotations.md、preamble_attributes.md、preamble_spec-attributes.md、preamble_processors.md、preamble_augmenters.md、preamble_extension-points.md均位于 docs/snippets/。 /snippets/path.php把真实且经过测试执行的源文件转写到页面中因此被记录的示例永远不会与真实运行的代码脱节。例如Renderer::exampleSection()就通过这种转写把docs/examples/specs/{name}/attributes|annotations|spec/{file}三份实现分别注入codeblock的三个模板槽at/an/spec中见 Renderer.php。第三种机制!--include: ./path.md--由 Vitepress 支持但本仓库尚未使用。它适合在手写页面之间共享散文。优先提取片段而不是粘贴。凡是内容可以派生出来的地方优先生成而不是复制——docs/dev/docs-toolchain.md 说明了哪些内容已经由生成器产出。写主题本身不要写关于文档的注脚一个页面描述的是它的主题。除非文档本身就是主题如本页或工具链笔记页面不需要解释文档是如何产生的、为什么某个交叉引用是可信的。任何页面——无论哪种类型——都不需要宣布自己的读者群或为自己的存在辩护。标题和把读者带到这里来的链接已经完成了这个工作。原文档给出了三个真实的反面案例均出自同一页面The Augmenters reference —generated from the pipeline itself, so it cannot fall out of step with the codesee Spec pipeline internals,which is written for people changing the pipeline rather than using itThis page stays at the level of what happens and in what order这三句话各自都属实但没有任何一句回答了读者唯一的问题这个东西是怎么工作的。某个参考页是否是生成的只对维护它的人有意义读者只需要跟着链接走。最常见的标志是挂在链接后面解释链接的从句。让链接文字自己完成工作see [Spec pipeline internals]就已经完整了逗号之后的任何内容都是页面在谈论自己。只枚举封闭集合一个需要别人记得去更新的列表注定会出错。只有当集合是封闭的——即它在代码中某处被定义且只随那段代码变化而变化——才值得枚举。生成页面就是封闭集合tools/docgen.php 中的$outputMap明确列出了七组输出目标reference/annotations.md、reference/attributes.md、reference/spec-attributes.md、reference/processors.md、reference/augmenters.md、reference/extension-points.md、guide/examples.md因此一张列出这些页面的表格可以一直成立直到有人编辑生成器。docs/下其他所有内容则是开放集合——任何人添加一个页面它就变大所以它应当被描述而不是被列举。同样的检验也适用于挂在列表上的计数。集合会变数字就会变所以当六个页面这种计数所概括的枚举被删掉时这个计数也要一并删掉。不要手写可以被捕获的内容命令输出、默认配置、API 清单都应该从真实的东西复制而不是凭想象编写。原文档记录过一个教训某次手写的openapi -h代码块长期携带了错误的格式、错误的--mode描述、一个并不存在的--version默认值以及四个缺失的选项——只因为一直没有人真正运行过它。正确做法是捕获真实输出./bin/openapi -h # capture this ./bin/openapi --mode spec -D src这一规范已经被固化为自动化测试。DocsAccuracyTest::testCliHelpOutputMatchesDocs()见 tests/DocsAccuracyTest.php从docs/guide/generating-openapi-documents.md中提取-h帮助块实际执行bin/openapi -h并断言两者中命令行自定义选项部分完全一致。Symfony Console 自动追加的内置选项从-h, --help开始会被ownHelpOptions()剥离因为它们的措辞随 Symfony 版本变化文档中仍展示完整输出。这条测试确保手写的帮助文本一旦漂移CI 会立即失败。不要引用行号Class::method()能扛住重构Foo.php:110不能。ADR-001 中曾有三处行号引用其中两处已经腐烂。这一原则与仓库内部的引用规范相互印证DocsAccuracyTest::testResultMethodListingMatchesDocs()tests/DocsAccuracyTest.php用正则从docs/reference/builder.md提取所有$result-xxx(方法引用再与Builder\Result类的全部公有实例方法逐一比对——它验证的正是方法名这一层引用而非行号。不要声称你未验证过的东西如果某个页面要对比 spec 模式与 classic 模式那就把两者都运行一遍。像classic 模式可能会输出数组形式这种模糊措辞是基于推理而非实测的信号读者无法据此行动。要么验证后直说要么只记录你确知的行为。这条规则在DocsAccuracyTest中有直接的机器化版本testCompilerTableMatchesDocs()tests/DocsAccuracyTest.php对文档中的每个 Compiler 条目都实际实例化对应的类、验证它实现CompilerInterface、并断言getVersion()以文档标注的版本号开头。不要与所在页面自相矛盾两个来自同一页面的例子属性被描述为不可变immutable而紧接着的 augmenter 章节却在描述向它们写入数据所有模式产生相同输出紧跟着却是一张模式差异表。如果某个声明需要读者无视下一段才能成立那就删掉这个声明。语气Voice短句、平实、一个句子一个意思。一句话携带三个限定条件时拆成两三句。不用破折号em dash。改用逗号、括号、冒号或另起一句不用分号连接从句。拆分句子不用缩写形式写 does not、it is克制。功能由它做什么来描述而不是它有多好解释描述代码如 swagger-phpwill automatically register theOAalias、can be used to。指示性语句以 you 称呼读者不用 not X but Y 句式也不要在结尾写 In short 式的总结。拼写Spelling代码库的拼写是混合的normalise与serialization并存behavio(u)r两种拼写在src/和docs/中都出现。没有单一约定可循。规则是匹配你正在编辑的文件已有的拼写其他的一律不动。批量修正造成的改动远多于它修复的问题。结构Structuredocs/snippets/下的代码片段由测试套件执行。具体见 docs/dev/testing.mdDocSnippetsTest会运行每个docs/snippets/*_an.php并对照对应的-3.1.0.yaml期望输出跨适用的模式与实现缺失的实现会被跳过而非判失败但缺失或过期的-3.1.0.yaml是硬失败。新增一个 snippet 意味着要同时提供foo_an.phpannotations、foo_at.phpattributes、foo_spec.phpspec attributes与foo-3.1.0.yaml四件套。仓库中现存的完整示例是 minimal_api_an.phpOA注解风格、minimal_api_at.php属性风格、minimal_api_spec.phpOpenApi\Spec风格及其 minimal_api-3.1.0.yaml 期望输出。codeblock组件把注解annotation、属性attribute和 spec 变体渲染为标签页。三种实现必须保持同步。这也解释了为什么Renderer::exampleSection()要为每个示例文件同时生成at/an/spec三个模板槽。内部链接使用站点绝对路径/reference/architecture而不是相对文件路径这样页面在不同渲染深度下依然有效。在本文仓库文档语境中这类链接的仓库相对等价物如 docs/reference/architecture.md、docs/dev/pipeline.md 均指向实际存在的文件。描述classic与spec模式行为差异的散文放在::: info Mode difference容器中这样当两条管线趋同后这些差异可以再次被集中列出。以模式为主题的页面会把这种区分体现在自身结构里而不需要逐段标记。审查文档变更Reviewing documentation changes这是一套可以跑在文档 diff——无论自己的还是别人的——以及 PR 描述、提交信息上的检查清单。原文档特别说明下面每一项都至少在这个代码库中抓住过真实缺陷。检查失败时修复源头而不是修复症状错误的生成页面意味着错误的 docblock 或生成器而不是需要手工编辑的页面。可以直接运行的检查生成页面未被改动。composer docs:gen在 docs/dev/docs-toolchain.md 列出的页面上不应留下任何 diff。该脚本在 composer.json 中定义为php tools/docgen.phptools/docgen.php还支持按名称只跑部分生成器如php tools/docgen.php aug proc。文中提到的每个composer script都真实存在于composer.json。本仓库定义的文档相关脚本包括docs:check运行DocsAccuracyTest、docs:gen、docs:dev进入docs/运行vitepress dev、docs:build先docs:gen再构建静态站点。每个代码引用都能解析。对照源码检查类名、Class::method()、文件路径、CLI 标志与配置键。这能抓住最有害的一类错误自信的散文描述了一个已被改名或从未存在过的 API。命令输出是捕获的不是编写的。任何--help文本、默认配置导出或 API 清单都应来自真实运行。这一点已由DocsAccuracyTest::testCliHelpOutputMatchesDocs()自动化。没有行号引用。Foo.php:123会静默腐烂应引用Class::method()。链接可解析。相对链接指向存在的文件。站点构建会对失效的内部链接报错因此composer docs:build覆盖了其余情况。章节锚点已验证或直接删掉。#heading-slug链接只有在标题为纯单词时才安全标点与连字符会使生成的 slug 有歧义。如果无法确认就链接到页面本身。没有易变值。计数六个页面、约 27 个测试文件、端口号、版本号等任何不编辑文档就会漂移的内容。要么从源头推导要么定性描述要么在工具自己声明时直接引用工具的声明。开发服务器自己打印 URL 时应记录为打印其 URL而不是记录一个端口号。版本与依赖要求与composer.json 一致。没有营销或套话填充production-ready、seamless、powerful、clean、simply、robust、comprehensive、leverage、crucial、genuinely。diff 中没有重复的套话。同一措辞出现两次其中一次就是填充。没有破折号也没有连接从句的分号。两者都能在 diff 搜索中出现。需要阅读才能完成的检查没有枚举开放集合。列表只留给代码中定义、且仅随代码变化而变化的集合。任何会随有人添加文件而增长的东西用描述代替列举。细节只出现一次。两个页面可以介绍同一主题但只有一页承载具体细节。当你第二次写某个东西时改成链接。声明是验证过的不是推理出来的。may、should、is expected to 这类含糊词通常标志着没人测试过的声明。先运行再直说或者删掉。页面没有自相矛盾。一个需要读者在两段之后无视它的声明比没有声明更糟。层级匹配读者。面向用户的页面说做什么并链向深处面向贡献者的页面承载机制。任何一方都不该持有另一方的另一半。没有关于文档本身的评论除非文档就是页面主题。包括页面如何生成、链接为何可信。警惕挂在链接后面解释链接的从句。没有页面宣布自己的读者群或目的。This page is for…、these notes exist because…。这条同样适用于贡献者页面。没有解释前句重要性的从句如 which is what makes X possible 或 which matters because…。陈述事实然后停止。没有复述页面结构已显示的内容。状态表、标题或提示块已经告诉了读者再写一句重复它只会腐烂。拼写跟随所在文件。两种拼写都不值得批量修正。共享内容被复用而非复制。见前文复用内容一节。一个句子一个意思。带三个限定条件的句子要拆分。解释描述代码。指示性语句以 you 称呼读者。规范背后的工具链docs:gen本身就是漂移检查本规范的绝大部分约束最终都落在一套可运行的生成与校验机制上理解它才能理解为什么这些规范能长期生效。生成页面不要手工编辑以下是 docs/dev/docs-toolchain.md 列出的生成页面及其来源它们都由composer docs:gen写入页面由什么生成docs/reference/annotations.mdsrc/Annotations/docblock docs/snippets/preamble_annotations.mddocs/reference/attributes.mdsrc/Attributes/docblock docs/snippets/preamble_attributes.mddocs/reference/spec-attributes.mdsrc/Spec/docblock docs/snippets/preamble_spec-attributes.mddocs/reference/processors.mdsrc/Processors/docblock docs/snippets/preamble_processors.mdProcessorGenerator中的散文docs/reference/augmenters.mdsrc/Augmenter/docblock docs/snippets/preamble_augmenters.mdAugmenterGenerator中的散文docs/guide/examples.md示例源码 各示例的docs/examples/specs/*/Readme.md要修改这些页面就修改它们的源头然后重新运行composer docs:gen。直接编辑页面是白费功夫下一次docs:gen会覆盖你的改动composer docs:build先跑docs:gen再构建同样会覆盖。注意部分散文活在内置于生成器的字符串字面量里而不在任何 markdown 文件中。例如ProcessorGenerator::renderConfigSection()见 tools/src/Docs/Reference/ProcessorGenerator.php与AugmenterGenerator::renderConfigSection()见 tools/src/Docs/Reference/AugmenterGenerator.php中 Configuration 章节的-c与-D说明文字就是代码内的 heredoc 字符串。而DocGenerator::renderConfiguration()tools/src/Docs/DocGenerator.php负责统一渲染这些章节的公共框架两个生成器只传入名词、模式标志与示例列表。所有生成器都经由tools/src/Docs/Sections/渲染Renderer只构建页面框架prelude、标题、示例块参数渲染为定义列表。描述是带自有段落断行的散文类型经过 HTML 转义两者都需要以 markdown 解析器不会再次读取的方式到达页面ConfigSettingsSection的实现见 tools/src/Docs/Sections/ConfigSettingsSection.php。docs/下其余一切均为手写包括顶层docs/examples/Readme.md——因为只有各示例自己的 Readme 才喂给生成页面。docs:gen的正确用法生成器是确定性的且提交的输出应当与源头一致因此composer docs:gen git status --porcelain docs/任何输出都意味着已提交页面发生了漂移重新生成的版本才是正确版本。值得在打开 PR 之前运行。在干净的树上运行或者把git status限定在生成页面范围内——docs/reference/也含手写页面全目录检查会把你自己对参考页的编辑也报成漂移。命令速查命令说明composer docs:gen重新生成上表列出的页面composer docs:build先运行docs:gen再构建静态站点composer docs:dev本地预览长时间运行。启动时打印其 URL 且不返回什么才算被文档记录的配置项docs/reference/augmenters.md与docs/reference/processors.md列出-c name.optionvalue可接受的选项。一个配置项够格的条件是它是非对象类型的构造函数参数构造函数参数按约定就是公开配置契约对象类型参数工厂、解析器、生成器是协作者collaborators而非配置项无法用 CLI 值表达。这套逻辑在 DocGenerator::configurableParameters() 中实现了一次并且镜像了Utils\Pipeline::getConfig()在运行时的报告。从源码注释看该方法的判定规则是若任何构造函数参数携带#[Config]属性则这些参数即为可配置项显式选择加入与Pipeline::getConfig()完全一致否则回退到非对象类型构造函数参数的启发式规则目前src/Processors/下所有尚未迁移到#[Config]的类走此回退。二者靠手工对齐而非构造上保证改了一个就要检查另一个。验证手段是./bin/openapi --mode spec -D src列出的配置项必须与参考页面记录的完全一致。值得知道的 CLI 行为-D/--defaults打印解析后的默认配置但仍然要求paths参数./bin/openapi --mode spec -D src而不是./bin/openapi --mode spec -D--version设置的是目标OpenAPI版本不是工具版本帮助输出是标准 Symfony Console 格式来自./bin/openapi -h未知的-c键在spec模式下通过Pipeline::configure()报告为警告在classic模式下则被静默忽略因为配置走的是Generator::setConfig()。classic 模式下-c键拼写错误会无声失败。已知粗糙点AugmenterGenerator::renderConfigSection()与ProcessorGenerator::renderConfigSection()本质上是同一个方法写了两次只差名词、模式标志与程序化示例。对其中一处的修复通常也要应用到另一处。文档是测试套件的一部分理解 docs/dev/testing.md 中的这一论断就能明白为什么本规范不是空谈两个测试直接验证文档与真实输出的一致性只要添加文档而不同时添加对应物两者都会失败。DocSnippetsTest运行每个docs/snippets/*_an.php并与匹配的-3.1.0.yaml对比跨适用的模式与实现。模式/实现配对是刻意的spec 模式只跑 spec snippetclassic 模式从不跑它们hybrid 模式跑全部三种ExamplesTest对docs/examples/specs/*做同样的事对照按版本区分的*-3.0.0.yaml/*-3.1.0.yaml/*-3.2.0.yaml期望文件。这正是改变管线输出会表现为一面墙的文档测试失败的原因——那是测试套件在正常工作期望的 YAML 文件就是管线输出规格本身也是发布文档展示的内容。实践建议把这套规范移植到你的项目swagger-php 的这套文档治理体系可以按以下优先级逐步移植到任何 PHP 项目先定规则把事实只说一次、细节只放一处、复用而非复制、不引用行号、不写未验证声明写进CONTRIBUTING.md并把 PR 描述与提交信息分开约束再建生成凡是由源码 docblock、配置或命令输出派生的文档一律走生成器参考本仓库的tools/docgen.phptools/src/Docs/结构手工页面只保留导览性内容最后上校验为每一条可机检的规则写一条测试——本仓库的DocsAccuracyTest帮助输出对比、编译器表格对比、Concerns 表对比、Result 方法清单对比就是可复制的范本composer docs:check一键运行。如此文档质量就从靠自觉变成了靠 CI 兜底这正是 docs/dev/writing-docs.md 这套规范在 swagger-php 中真实运转的方式。赞分享后端API设计文档代码生成【免费下载链接】swagger-phpA php swagger annotation and parsing library项目地址https://gitcode.com/gh_mirrors/sw/swagger-php点击查看免费下载相关推荐文档标题文档标题 概述 简要说明文档目的和范围 功能特性 功能点1详细描述 功能点2详细描述 安装指南 系统要求 Windows版本要求 硬件要求 安装步骤 1.桌面应用系统编程EmDash 文档写作规范拆解为 Astro CMS 编写准确、自然、可检索的技术文档EmDash 文档写作规范拆解为 Astro CMS 编写准确、自然、可检索的技术文档 本文基于 EmDash 仓库中 skills/writing emdaCMS后端前端插件系统Duktape 内部文档 reStructuredText 写作规范与排版约定Duktape 内部文档 reStructuredText 写作规范与排版约定 导读 Duktape 是一个以可移植性和紧凑体积为目标的嵌入式 JavaScri语言运行时嵌入式解释器上一篇Immich-Go安全上传策略API密钥权限与数据保护最佳实践下一篇learnxinyminutes-docs 之 C 语言完全指南从注释语法到指针与内存管理实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号