<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Zany🥝</title>
  
  
  <link href="https://daixiaokang.com/atom.xml" rel="self"/>
  
  <link href="https://daixiaokang.com/"/>
  <updated>2026-10-22T16:00:00.000Z</updated>
  <id>https://daixiaokang.com/</id>
  
  <author>
    <name>Zany🥝</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>DeerFlow 2.0使用指南</title>
    <link href="https://daixiaokang.com/posts/29cc628.html"/>
    <id>https://daixiaokang.com/posts/29cc628.html</id>
    <published>2026-10-22T16:00:00.000Z</published>
    <updated>2026-10-22T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="1、DeerFlow-2-0-是什么">1、DeerFlow 2.0 是什么</h1><p><a href="https://github.com/bytedance/deer-flow">DeerFlow</a> 是字节跳动开源的智能体运行系统。它将模型、工具、子智能体、文件系统和记忆等能力组织起来，用于完成资料研究、内容整理、代码与文件处理等多步骤任务。</p><p>官方将 2.0 定位为 <strong>Super Agent Harness</strong>，可以理解为让智能体实际开展工作的运行环境。模型负责理解和决策，DeerFlow 提供执行任务所需的基础设施。</p><p><strong>DeerFlow 2.0 是一次完整重写，旧版代码保留在 <code>1.x</code> 分支。</strong> 查找教程时，需要先确认教程针对的分支，避免把旧版配置复制进当前项目。<a href="https://github.com/bytedance/deer-flow#readme">官方项目说明</a>。</p><p>本文按 <strong>2026-10-23 查阅的官方 <code>main</code> 分支文档</strong>整理。2.0 是本文讨论的产品架构，具体命令、配置项与界面仍应以下载的提交版本为准。本文仅记录使用方法，没有安装或启动 DeerFlow。</p><span id="more"></span><h1 id="2、先理解几个核心概念">2、先理解几个核心概念</h1><table><thead><tr><th>概念</th><th>主要职责</th><th>理解方式</th></tr></thead><tbody><tr><td>Model</td><td>理解任务、生成计划、决定工具调用</td><td>智能体使用的推理与生成能力</td></tr><tr><td>Lead Agent</td><td>接收任务、协调工具与子任务</td><td>主执行者</td></tr><tr><td>Subagent</td><td>接收被拆分的任务并返回结果</td><td>分工处理的执行者</td></tr><tr><td>Tool</td><td>执行具体动作</td><td>搜索、读取文件、运行代码等操作</td></tr><tr><td>Skill</td><td>描述某类任务的流程与方法</td><td>可以复用的工作说明</td></tr><tr><td>Sandbox</td><td>提供文件和代码执行环境</td><td>完成实际操作的工作空间</td></tr><tr><td>Memory</td><td>保存适合跨会话使用的信息</td><td>长期偏好与上下文</td></tr></tbody></table><p>一个典型任务可以按下面的过程理解：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">用户描述目标</span><br><span class="line">    → 主智能体理解任务</span><br><span class="line">    → 按需要规划、调用工具或委派子任务</span><br><span class="line">    → 在工作空间读取资料、处理文件</span><br><span class="line">    → 整理结果并交付文件或回答</span><br></pre></td></tr></table></figure><p>这是便于理解的流程，不代表每次请求都会经过所有步骤。简单问答不一定需要沙箱，复杂研究也不一定需要同时启动很多子智能体。<a href="https://github.com/bytedance/deer-flow/blob/main/backend/README.md">后端组件说明</a>。</p><h1 id="3、项目由哪些部分组成">3、项目由哪些部分组成</h1><p>官方项目包含 Web 界面、后端 Gateway、智能体运行时以及可选执行组件。</p><table><thead><tr><th>位置</th><th>主要内容</th></tr></thead><tbody><tr><td><code>frontend/</code></td><td>基于 Next.js 的 Web 界面</td></tr><tr><td><code>backend/</code></td><td>Gateway、智能体运行逻辑与相关模块</td></tr><tr><td><code>skills/</code></td><td>技能资源</td></tr><tr><td><code>docker/</code></td><td>容器编排、镜像及代理配置</td></tr><tr><td><code>config.example.yaml</code></td><td>主配置模板</td></tr><tr><td><code>extensions_config.example.json</code></td><td>扩展配置模板</td></tr><tr><td><code>Makefile</code></td><td>配置、安装、启动、停止与诊断入口</td></tr></tbody></table><p>当前官方架构通过 Nginx 提供统一入口：网页请求进入前端，<code>/api/*</code> 进入 Gateway，<code>/api/langgraph/*</code> 提供兼容的智能体交互接口。默认访问端口是 <strong>2026</strong>。<a href="https://github.com/bytedance/deer-flow/blob/main/backend/README.md#architecture">后端架构与路由</a>。</p><p>初次使用可以从统一入口访问，先确认完整链路能正常工作，再考虑单独调试内部服务。</p><h1 id="4、准备运行环境">4、准备运行环境</h1><h2 id="4-1、两种启动方式">4.1、两种启动方式</h2><table><thead><tr><th>方式</th><th>特点</th><th>需要准备</th></tr></thead><tbody><tr><td>Docker 开发环境</td><td>通过容器组织服务，适合先体验与调试</td><td>Docker、Compose、仓库脚本所需工具</td></tr><tr><td>本地开发环境</td><td>便于直接调试前后端代码</td><td>Node.js、pnpm、uv、nginx 等</td></tr></tbody></table><p>当前 Docker 开发配置要求 <strong>Docker Compose v2.24 或更新版本</strong>。本地开发文档列出的 Node.js 要求为 <strong>22+</strong>，Python 环境与依赖按仓库的项目配置和锁文件准备。</p><p>官方开发环境资源建议以 4 核、8 GB 内存作为起步参考，较重的任务可以从 8 核、16 GB 内存评估。这是运行应用与容器的参考，不包含自行部署本地大模型所需的额外资源。<a href="https://github.com/bytedance/deer-flow/blob/main/CONTRIBUTING.md">开发环境指南</a>。</p><p>Windows 下执行 <code>make</code> 前，需要确认 Make 可用；当前 Makefile 的 Windows 路径会通过 Git Bash 运行相关 Shell 脚本。Docker 方式还需要确认 Docker Desktop 已启动。<a href="https://github.com/bytedance/deer-flow/blob/main/Makefile">官方 Makefile</a>。</p><h2 id="4-2、获取代码并生成配置">4.2、获取代码并生成配置</h2><p>首次使用时，在准备存放项目的位置执行：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/bytedance/deer-flow.git</span><br><span class="line">cd deer-flow</span><br><span class="line">make config</span><br></pre></td></tr></table></figure><p><code>make config</code> 用于生成本地配置。已有配置的项目跳过这一步，避免把初始化当成日常启动流程。</p><p>官方也提供 <code>make setup</code> 交互式配置向导；本文使用手动配置方式说明各部分作用。执行命令前，确认当前目录是 DeerFlow 仓库根目录。<a href="https://github.com/bytedance/deer-flow/blob/main/Install.md">官方安装流程</a>。</p><h1 id="5、配置模型">5、配置模型</h1><h2 id="5-1、模型配置需要哪些信息">5.1、模型配置需要哪些信息</h2><p>至少准备模型名称、调用凭证和正确的服务地址。模型还需要能够完成所选任务使用的工具调用；普通文本对话可用，不代表完整的智能体流程一定可用。</p><p>下面是使用 OpenAI 兼容协议的<strong>配置片段</strong>，用于说明字段含义。把它合并到生成的 <code>config.yaml</code> 的 <code>models</code> 列表中，保留其余配置，不要重复声明两个 <code>models</code> 键。</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">models:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">my-agent-model</span></span><br><span class="line">    <span class="attr">display_name:</span> <span class="string">自定义任务模型</span></span><br><span class="line">    <span class="attr">use:</span> <span class="string">langchain_openai:ChatOpenAI</span></span><br><span class="line">    <span class="attr">model:</span> <span class="string">replace-with-provider-model-id</span></span><br><span class="line">    <span class="attr">base_url:</span> <span class="string">https://api.example.com/v1</span></span><br><span class="line">    <span class="attr">api_key:</span> <span class="string">$MODEL_API_KEY</span></span><br><span class="line">    <span class="attr">max_tokens:</span> <span class="number">4096</span></span><br><span class="line">    <span class="attr">supports_vision:</span> <span class="literal">false</span></span><br></pre></td></tr></table></figure><p>其中 <code>name</code> 是内部标识，<code>model</code> 是供应商实际接受的模型 ID，<code>base_url</code> 是对应 API 根地址。示例域名与模型 ID 都是占位值，需要替换。<code>max_tokens</code> 是单次调用的输出限制，不是整个任务的总预算。</p><p><code>use</code> 决定适配器，模型特有的推理参数应参考对应示例；不能仅靠设置一个能力标记，就让不支持该功能的模型获得相应能力。<a href="https://github.com/bytedance/deer-flow/blob/main/backend/docs/CONFIGURATION.md#models">模型配置指南</a>。</p><h2 id="5-2、环境变量放在哪里">5.2、环境变量放在哪里</h2><p>上面的 <code>$MODEL_API_KEY</code> 表示从环境变量读取凭证。</p><p>对于官方 Docker 开发编排，Gateway 会读取仓库根目录的 <code>.env</code>。可以在该文件中加入自己的变量：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">MODEL_API_KEY=replace_with_your_api_key</span><br></pre></td></tr></table></figure><p>前端还有独立的 <code>frontend/.env</code>，两者用途不同。模型服务凭证应进入真正运行后端的环境；如果采用其他部署方式，需要核对对应进程或容器如何接收环境变量。<a href="https://github.com/bytedance/deer-flow/blob/main/docker/docker-compose-dev.yaml">Docker 开发编排配置</a>。</p><p>凭证只保存在本地或部署环境中，不写入文章、截图和公开仓库。变更环境变量后，需要让对应服务重新加载配置。</p><h1 id="6、启动与停止服务">6、启动与停止服务</h1><h2 id="6-1、Docker-开发方式">6.1、Docker 开发方式</h2><p>完成配置后，在仓库根目录执行：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">make docker-init</span><br><span class="line">make docker-start</span><br></pre></td></tr></table></figure><p><code>docker-init</code> 负责所选沙箱模式需要的初始化准备；<code>docker-start</code> 才是应用服务的启动入口。启动完成后访问 <a href="http://localhost:2026">http://localhost:2026</a>。</p><p>查看开发环境日志：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make docker-logs</span><br></pre></td></tr></table></figure><p>日常停止开发容器：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make docker-stop</span><br></pre></td></tr></table></figure><p>首次启动的耗时可能包含依赖安装、镜像构建和下载，应结合日志判断当前阶段。应用使用 Docker 部署与任务采用哪一种沙箱模式，是两个需要分别确认的配置。<a href="https://github.com/bytedance/deer-flow/blob/main/CONTRIBUTING.md#option-1-docker-development-recommended">Docker 开发流程</a>。</p><h2 id="6-2、本地开发方式">6.2、本地开发方式</h2><p>本地运行时，可以先检查工具，再安装依赖并启动：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">make check</span><br><span class="line">make install</span><br><span class="line">make dev</span><br></pre></td></tr></table></figure><p>对应的本地服务停止命令为：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make stop</span><br></pre></td></tr></table></figure><p>两种开发方式选择一种运行即可。端口已被另一套实例占用时，先确认正在运行的服务来源，再决定停止哪一套。</p><p><strong><code>make clean</code> 会删除本地运行数据与日志，可能涉及会话、上传文件、记忆等数据。</strong> 日常停止使用上面的停止命令，故障排查先查看日志与配置。<a href="https://github.com/bytedance/deer-flow/blob/main/Makefile">命令定义</a>。</p><h1 id="7、怎样描述一个容易执行的任务">7、怎样描述一个容易执行的任务</h1><p>开始任务前，可以先把需求拆成四部分：目标、材料、约束、交付物。</p><table><thead><tr><th>部分</th><th>可以填写的内容</th></tr></thead><tbody><tr><td>目标</td><td>希望最终完成什么</td></tr><tr><td>材料</td><td>提供哪些链接、附件或数据</td></tr><tr><td>约束</td><td>时间范围、技术版本、引用要求、允许的操作</td></tr><tr><td>交付物</td><td>Markdown 报告、表格、代码或其他文件</td></tr></tbody></table><p>例如准备一篇技术文章：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">请整理一份 DTM 分布式事务的学习报告。</span><br><span class="line"></span><br><span class="line">材料：以 DTM 官方文档和官方示例仓库为主要来源。</span><br><span class="line">范围：Saga、TCC、二阶段消息和子事务屏障。</span><br><span class="line">要求：说明适用场景、关键前提和失败处理，区分事实与实践建议。</span><br><span class="line">代码：展示 Go 接入结构，未运行的示例必须明确标注。</span><br><span class="line">交付：输出一份中文 Markdown 文件，并在相关段落附来源链接。</span><br></pre></td></tr></table></figure><p>这段提示词是本文的使用示例。它将资料范围和验收要求写清楚，便于检查产出，也便于任务中断后继续补充。</p><p>对于文件分析任务，还可以给出需要核对的列名、单位、缺失值处理方式，以及希望保留的原始数据。一次任务包含多个交付物时，明确各文件的名称和用途。</p><h2 id="7-1、根据任务选择执行方式">7.1、根据任务选择执行方式</h2><p>简短的问题可以先直接询问；需要研究、比较、计算和生成文件时，再使用界面提供的规划或子任务能力。</p><p>我的实践思路是先用一个边界清晰的小任务验证模型和工具，再扩大到完整流程。把任务完成与否落实到交付物上，例如报告是否含来源、表格是否能打开、代码是否注明验证范围。</p><h1 id="8、Skills-与-MCP-的区别">8、Skills 与 MCP 的区别</h1><p>Skill 用来组织“这类任务应该怎么做”，Tool 用来执行具体动作，MCP 则可以为智能体接入外部工具与服务。</p><p>例如“技术文章整理”Skill 可以规定资料检索、版本核对和文章结构；搜索工具或 MCP 服务提供实际检索能力。只有工作说明而没有可用工具，无法自动获得对应的外部数据。</p><p>当前官方界面通过工作区的 <strong>Capability Center</strong> 管理 Skills 与插件等能力。安装或导入后，还需要确认该能力对当前任务可用。<a href="https://github.com/bytedance/deer-flow#skills--tools">Skills 与工具说明</a>。</p><h2 id="8-1、一个自定义-Skill-的思路">8.1、一个自定义 Skill 的思路</h2><p>下面是本文编写的 <code>SKILL.md</code> 内容示例，用于表达技术文章整理流程；它不是已经安装到 DeerFlow 的技能包。</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">name: technical-article-notes</span><br><span class="line"><span class="section">description: &quot;根据官方资料整理中文技术文章，保留版本信息、代码前提和来源。&quot;</span></span><br><span class="line"><span class="section">---</span></span><br><span class="line"></span><br><span class="line"><span class="section"># 技术文章整理</span></span><br><span class="line"></span><br><span class="line"><span class="bullet">1.</span> 明确主题、目标读者与技术版本。</span><br><span class="line"><span class="bullet">2.</span> 优先阅读官方文档、源码和维护者提供的示例。</span><br><span class="line"><span class="bullet">3.</span> 记录关键结论及其来源，区分已核实内容和推断。</span><br><span class="line"><span class="bullet">4.</span> 按背景、概念、接入方式、常见问题组织文章。</span><br><span class="line"><span class="bullet">5.</span> 将配置中的真实凭证替换为明确的占位值。</span><br><span class="line"><span class="bullet">6.</span> 对代码标注运行条件和验证范围。</span><br><span class="line"><span class="bullet">7.</span> 交付 Markdown 文件，并检查标题、日期、链接与代码围栏。</span><br></pre></td></tr></table></figure><p>可先将团队反复使用的写作规范整理成这种流程，再按当前版本的技能目录或导入功能接入。引用资源、辅助脚本和工具需求也需要随技能一起组织，不能仅凭一个名称假设依赖已经准备完成。</p><h1 id="9、沙箱、文件与记忆如何理解">9、沙箱、文件与记忆如何理解</h1><h2 id="9-1、确认代码执行的位置">9.1、确认代码执行的位置</h2><p>沙箱模式决定任务在哪里读取文件和执行代码。当前项目提供本地执行与基于容器的执行方式；本地模式中的命令可能直接作用于宿主环境，容器模式则需要核对镜像、挂载与执行范围。</p><p>应用本身在容器中启动，不等于所有业务工具都自动获得同样的隔离边界。准备启用命令执行前，应先确认实际选用的 Provider。<a href="https://github.com/bytedance/deer-flow/blob/main/backend/docs/CONFIGURATION.md#sandbox">沙箱配置说明</a>。</p><h2 id="9-2、工作文件与最终文件">9.2、工作文件与最终文件</h2><p>官方后端为线程组织工作目录、上传文件和输出文件，并使用虚拟路径映射到对应存储位置。</p><p>例如任务内部出现的 <code>/mnt/user-data/outputs</code> 是执行环境中的输出路径，不应直接理解为 Windows 本机磁盘路径。查看交付物时，使用界面提供的文件入口，并确认实际下载的是最终版本。<a href="https://github.com/bytedance/deer-flow/blob/main/backend/README.md#sandbox-system">文件系统说明</a>。</p><h2 id="9-3、会话与长期记忆">9.3、会话与长期记忆</h2><p>会话用于保留本次任务的过程，文件用于保存材料与产物，长期记忆用于跨会话的适当上下文。它们不应被当成同一种数据。</p><p>在实践中，可以将长期写作偏好与临时任务要求分开表达。任务完成后仍需检查实际产物，不把“系统记住了偏好”当成这次输出已经符合要求的证据。</p><h1 id="10、常见问题怎么排查">10、常见问题怎么排查</h1><table><thead><tr><th>现象</th><th>可以优先检查</th></tr></thead><tbody><tr><td>网页能打开，发送消息失败</td><td>Gateway 日志、模型配置、凭证与供应商返回结果</td></tr><tr><td>模型可以聊天，但任务不会调用工具</td><td>所选模型的工具调用能力、适配器和工具配置</td></tr><tr><td>容器内访问本机模型失败</td><td><code>localhost</code> 的实际指向、容器网络及服务监听地址</td></tr><tr><td>搜索没有结果</td><td>搜索工具是否启用、相关凭证、网络和来源限制</td></tr><tr><td>文件处理失败</td><td>文件是否上传成功、执行环境依赖、沙箱路径和权限</td></tr><tr><td>页面长时间没有流式内容</td><td>后端是否仍在运行、网络连接、反向代理的流式转发</td></tr><tr><td>升级后提示配置过旧</td><td>当前模板版本与本地配置差异，先备份再合并</td></tr></tbody></table><p>模型、搜索服务、浏览器和文件执行是不同链路。排查时可以分别验证，再组合成完整任务，避免仅凭网页状态推断后端已经就绪。</p><p>官方提供 <code>make doctor</code> 诊断入口，配置更新还提供 <code>make config-upgrade</code>。升级前保留本地配置与运行数据副本，再依据当前版本说明处理变更。<a href="https://github.com/bytedance/deer-flow/blob/main/Makefile">诊断与升级命令</a>、<a href="https://github.com/bytedance/deer-flow/blob/main/backend/docs/CONFIGURATION.md#config-versioning">配置版本说明</a>。</p><p>如果部署到服务器，应先确定访问人员、鉴权和沙箱边界，再开放相应入口。模型凭证、执行环境和普通静态网页承担的权限不同，访问控制需要跟着实际能力一起配置。<a href="https://github.com/bytedance/deer-flow#security-notice">官方部署说明</a>。</p><h1 id="11、在个人技术学习中的使用思路">11、在个人技术学习中的使用思路</h1><p>结合自己的博客，可以先尝试三个边界明确的场景：</p><ol><li><strong>官方资料整理</strong>：围绕一个版本生成学习提纲，保留来源与待核实事项。</li><li><strong>代码阅读辅助</strong>：提供一组源码文件，整理调用关系与设计问题，再人工核对。</li><li><strong>文章发布前检查</strong>：检查术语、代码前提、引用链接与段落结构，最终由自己确认内容。</li></ol><p>这些是本文提出的任务设计方式，不代表 DeerFlow 对每个任务都能自动给出正确结论。使用时保留任务输入、来源和最终文件，才能持续改进自己的工作流程。</p><p>本文仅完成文档整理与示例说明，未进行 DeerFlow 部署、模型调用或端到端验证。后续使用时可以继续查阅<a href="https://github.com/bytedance/deer-flow">官方仓库</a>、<a href="https://github.com/bytedance/deer-flow/blob/main/Install.md">安装说明</a>与<a href="https://github.com/bytedance/deer-flow/blob/main/config.example.yaml">配置模板</a>。</p>]]></content>
    
    
    <summary type="html">整理 DeerFlow 2.0 的核心概念、本地部署、模型配置、沙箱、Skills、MCP 与任务使用方法，并记录常见问题及实践思路。</summary>
    
    
    
    <category term="技术" scheme="https://daixiaokang.com/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
    <category term="技术开发" scheme="https://daixiaokang.com/tags/%E6%8A%80%E6%9C%AF%E5%BC%80%E5%8F%91/"/>
    
    <category term="AI" scheme="https://daixiaokang.com/tags/AI/"/>
    
    <category term="Agent" scheme="https://daixiaokang.com/tags/Agent/"/>
    
    <category term="DeerFlow" scheme="https://daixiaokang.com/tags/DeerFlow/"/>
    
  </entry>
  
  <entry>
    <title>DTM分布式事务使用总结</title>
    <link href="https://daixiaokang.com/posts/2e041aa4.html"/>
    <id>https://daixiaokang.com/posts/2e041aa4.html</id>
    <published>2026-10-21T16:00:00.000Z</published>
    <updated>2026-10-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="1、为什么需要分布式事务">1、为什么需要分布式事务</h1><p>一次下单可能需要完成三件事：创建订单、扣减库存、扣减账户余额。</p><p>如果这些数据都在一个数据库中，并且能够通过同一个数据库事务操作，通常先使用本地事务即可。出现错误时，数据库负责回滚本次事务中的修改。</p><p>当订单、库存和账户拆成独立服务，各自维护数据库后，订单服务中的一次 <code>Rollback</code> 无法撤销另一个服务已经提交的数据。此时需要设计跨服务的一致性方案。</p><p><strong>DTM 是一个用 Go 编写的分布式事务管理器</strong>，通过事务协调、分支调用和失败重试，帮助多个服务按选定的事务模式完成业务。它支持 HTTP、gRPC 等接入方式；本文围绕 HTTP 和 Go SDK 展开。<a href="https://dtm.pub/">DTM 官方文档</a>、<a href="https://www.dtm.pub/ref/proto">通信协议</a>。</p><p>本文记录学习与接入思路，示例不代表本站已经引入 DTM。示例中的服务地址、业务路由和数据库连接都需要根据实际项目配置。</p><span id="more"></span><h1 id="2、先认识几个角色">2、先认识几个角色</h1><table><thead><tr><th>角色或标识</th><th>含义</th><th>下单示例</th></tr></thead><tbody><tr><td>事务发起方</td><td>组织本次业务流程并提交事务</td><td>接收下单请求的应用服务</td></tr><tr><td>DTM Server</td><td>持久化协调状态，调度分支和重试</td><td>独立部署的协调服务</td></tr><tr><td>事务分支</td><td>参与全局事务的一项业务操作</td><td>扣库存、扣余额</td></tr><tr><td>本地事务</td><td>每个分支内部的数据原子操作</td><td>同时写库存流水与更新库存</td></tr><tr><td>GID</td><td>一次全局事务的标识</td><td>本次下单流程的事务编号</td></tr><tr><td>Branch ID</td><td>全局事务内的分支标识</td><td>库存分支、账户分支的编号</td></tr><tr><td>业务单号</td><td>业务系统自身的唯一标识</td><td>订单号 <code>order_id</code></td></tr></tbody></table><p>GID 和订单号的职责不同。GID 用于协调事务，订单号用于查询订单、业务去重和对账。建议建立两者的持久化关联，以便在调用超时后仍能定位原来的事务。</p><p>DTM 协调的是各个服务的操作流程，各个服务仍然负责自己的本地事务、库存约束、余额约束和业务状态流转。<a href="https://www.dtm.pub/practice/arch">DTM 架构</a>。</p><h1 id="3、常见事务模式怎么选择">3、常见事务模式怎么选择</h1><table><thead><tr><th>模式</th><th>基本做法</th><th>适合考虑的场景</th><th>主要设计成本</th></tr></thead><tbody><tr><td>Saga</td><td>执行正向操作，失败后执行补偿</td><td>能接受中间状态、能够定义补偿的业务</td><td>编写补偿逻辑</td></tr><tr><td>TCC</td><td>Try 预留，Confirm 确认，Cancel 释放</td><td>需要先冻结库存或额度的业务</td><td>维护资源预留及三阶段接口</td></tr><tr><td>XA</td><td>使用数据库的分布式事务能力</td><td>数据库支持相应协议、锁竞争可控的业务</td><td>控制锁持有时间，核对数据库支持</td></tr><tr><td>二阶段消息</td><td>协调本地事务结果和后续分支执行</td><td>本地成功后，后续操作需要持续向前完成</td><td>设计可靠回查与幂等分支</td></tr></tbody></table><p>实际选择时，先问业务三个问题：是否需要撤销已经完成的动作，是否允许处理中状态对外可见，是否能够提前预留资源。再结合并发量和数据库条件选择模式。<a href="https://dtm.pub/practice/choice.html">官方模式选择说明</a>。</p><p>这些模式对数据可见性的处理方式不同，不能仅凭“用了分布式事务”就假设任意跨服务查询都获得同一个一致性快照。读接口与业务状态也需要配合设计。<a href="https://dtm.pub/practice/theory">分布式事务基础理论</a>。</p><h1 id="4、Saga：先执行，失败后补偿">4、Saga：先执行，失败后补偿</h1><h2 id="4-1、正常流程与补偿流程">4.1、正常流程与补偿流程</h2><p>下面以两个分支说明过程：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">正常流程：</span><br><span class="line">提交 Saga → 扣减库存成功 → 扣减余额成功 → 全局事务成功</span><br><span class="line"></span><br><span class="line">业务失败：</span><br><span class="line">提交 Saga → 扣减库存成功 → 扣减余额明确失败</span><br><span class="line">         → 协调补偿 → 恢复库存 → 全局事务回滚完成</span><br></pre></td></tr></table></figure><p>每个正向操作都需要明确对应的补偿语义：库存扣减对应恢复本次扣减数量，账户扣款对应撤销本次扣款。补偿通常需要参考原业务流水，不能简单把数据恢复成某个旧快照，否则可能覆盖其他并发业务的正常修改。</p><p><strong>Saga 的补偿是新的业务操作。</strong> 正向操作的本地事务可能早已提交，因此它与数据库撤销未提交事务的 <code>Rollback</code> 不同。<a href="https://www.dtm.pub/practice/saga">Saga 官方说明</a>。</p><h2 id="4-2、超时不代表没有执行">4.2、超时不代表没有执行</h2><p>假设账户服务已经扣款并提交，但返回响应时网络断开。协调方看到的是超时，账户服务实际已经完成了业务。</p><p>因此，分支可能收到重复请求；结果不确定的分支也需要具备相应的补偿处理能力。业务接口必须围绕“请求可能重复、结果可能暂时未知”来设计，而不能依赖一次 HTTP 请求只发生一次。</p><p>对于发短信、发邮件、调用外部支付平台等动作，需要单独分析可撤销性和对方的幂等机制。不要把它们当成能够跟本地 SQL 一起回滚的操作。</p><h1 id="5、TCC：先预留，再确认或释放">5、TCC：先预留，再确认或释放</h1><p>TCC 将业务拆成三个阶段：</p><table><thead><tr><th>阶段</th><th>库存示例</th><th>账户示例</th></tr></thead><tbody><tr><td>Try</td><td>检查可用库存并冻结本次购买数量</td><td>检查可用余额并冻结本次金额</td></tr><tr><td>Confirm</td><td>将冻结库存转为正式销售消耗</td><td>将冻结金额转为实际扣款</td></tr><tr><td>Cancel</td><td>解除本次库存冻结</td><td>解除本次资金冻结</td></tr></tbody></table><p>Try 阶段应完成必要的约束检查和资源预留。Confirm、Cancel 则围绕已经预留的资源完成收尾；如果到 Confirm 才检查是否还有库存，预留就失去了意义。</p><p>例如可以将资源分为“可用”和“冻结”两部分，另外保存每笔业务的预留记录。读取可用余额、取消预留、执行确认时，都应遵循同一套状态规则，避免其他接口绕过冻结限制。</p><p>TCC 的 Confirm、Cancel，以及 Saga 的补偿操作，都需要设计为在临时故障消除后能够最终完成。出现持续业务冲突时，应修复数据或逻辑，单纯增加重试次数并不能解决问题。<a href="https://dtm.pub/practice/must-succeed">最终成功的设计要求</a>。</p><h1 id="6、二阶段消息：保证后续操作继续完成">6、二阶段消息：保证后续操作继续完成</h1><p>有些业务不适合“失败后撤销”，而是希望在本地操作成功后，让后续任务可靠地执行下去。</p><p>例如本地确认订单后，异步生成一份可重建的统计记录。统计服务临时不可用时，可以稍后补做，无须取消已经确认的订单。</p><p>这里的难点是两个动作之间的空隙：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">提交本地数据库事务 → 进程退出 → 没有通知下游</span><br></pre></td></tr></table></figure><p>把代码写成“先提交数据库，再调用下游”无法消除这个空隙。DTM 的二阶段消息通过准备、提交和本地事务结果回查等机制协调这两个阶段；接入时应使用对应 SDK 流程，并持久化可供回查的本地结果。<a href="https://www.dtm.pub/guide/e-msg">二阶段消息示例</a>。</p><p>回查应依据本地事务的可靠记录判断结果，不能因为临时查询失败就判断“业务没有发生”，也不能仅凭进程内存中的一个变量判断是否已经提交。</p><p>同样可以考虑本地消息表（Outbox）：把业务数据和待发送事件放进同一个本地事务，再由后台任务投递，消费者负责去重。两者都需要完整设计失败恢复路径，具体选择取决于系统已有设施与维护成本。<a href="https://dtm.pub/practice/other">其他事务模式</a>。</p><h1 id="7、子事务屏障解决什么问题">7、子事务屏障解决什么问题</h1><h2 id="7-1、重复、空补偿和悬挂">7.1、重复、空补偿和悬挂</h2><table><thead><tr><th>问题</th><th>发生过程</th><th>未处理时的影响</th></tr></thead><tbody><tr><td>重复调用</td><td>操作成功后响应丢失，协调方再次请求</td><td>重复扣款或重复恢复库存</td></tr><tr><td>空补偿</td><td>正向操作没有执行，补偿先到达</td><td>凭空增加库存或余额</td></tr><tr><td>悬挂</td><td>补偿已处理，延迟的正向请求随后到达</td><td>已取消的业务重新生效</td></tr></tbody></table><p>DTM 的子事务屏障利用本地持久化记录和唯一约束，对同一事务分支的重复、乱序操作进行控制。接入时将业务写操作放入屏障回调，并与屏障记录使用<strong>同一个本地数据库事务</strong>。<a href="https://www.dtm.pub/practice/barrier">异常与子事务屏障</a>。</p><p>屏障表应使用与所选 DTM、SDK 版本匹配的官方建表脚本，并部署在能够与对应业务数据共同提交的数据库中。不要把协调服务的事务表与业务侧的屏障表混为一谈。</p><h2 id="7-2、屏障不替代业务幂等">7.2、屏障不替代业务幂等</h2><p>用户连续点击两次下单，如果每次都创建一个新的 GID，对 DTM 来说就是两次不同的事务。</p><p>业务侧仍需使用订单号、请求幂等键或唯一索引，保证同一次业务请求映射到已有订单及事务。幂等键命中后，还要校验请求参数一致，避免同一个键被用于不同商品或金额。</p><p>屏障也不会自动约束不经过它的写入路径。库存、账户等关键数据应统一写入规则，并通过数据库约束和业务流水保留可核对的依据。</p><h1 id="8、Go-接入-Saga-的基本写法">8、Go 接入 Saga 的基本写法</h1><h2 id="8-1、依赖与地址">8.1、依赖与地址</h2><p>本文使用 <code>github.com/dtm-labs/client/dtmcli</code> 的 HTTP 客户端接口。官方客户端还提供 <code>dtmgrpc</code> 和 <code>workflow</code>；旧文章可能使用其他仓库路径，复制代码时需要先核对项目自己的 <code>go.mod</code>。<a href="https://github.com/dtm-labs/client">官方 Go 客户端</a>。</p><p>DTM 默认 HTTP 端口为 <code>36789</code>，gRPC 端口为 <code>36790</code>。HTTP SDK 常用的协调地址形如 <code>http://127.0.0.1:36789/api/dtmsvr</code>。<a href="https://www.dtm.pub/ref/proto">协议说明</a>。</p><p>服务端和客户端依赖应选择兼容的版本并固定，不在文章中把某个版本号当成永久适用的“最新版”。可先参考<a href="https://github.com/dtm-labs/quick-start-sample/tree/main/dtmcli-qs">官方快速示例</a>，再移入自己的项目。</p><h2 id="8-2、提交两个分支">8.2、提交两个分支</h2><p>下面是应用服务中的提交函数，展示 Saga 的组织方式。前提是 DTM Server 和库存、账户回调接口已经部署，调用方已经持久化订单号与 GID 的关联；它不包含完整的业务服务实现。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> order</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;fmt&quot;</span></span><br><span class="line"><span class="string">&quot;strings&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&quot;github.com/dtm-labs/client/dtmcli&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> SagaConfig <span class="keyword">struct</span> &#123;</span><br><span class="line">DTMServer     <span class="type">string</span></span><br><span class="line">InventoryBase <span class="type">string</span></span><br><span class="line">AccountBase   <span class="type">string</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> OrderPayload <span class="keyword">struct</span> &#123;</span><br><span class="line">OrderID     <span class="type">string</span> <span class="string">`json:&quot;order_id&quot;`</span></span><br><span class="line">UserID      <span class="type">int64</span>  <span class="string">`json:&quot;user_id&quot;`</span></span><br><span class="line">ProductID   <span class="type">int64</span>  <span class="string">`json:&quot;product_id&quot;`</span></span><br><span class="line">Quantity    <span class="type">int64</span>  <span class="string">`json:&quot;quantity&quot;`</span></span><br><span class="line">AmountCents <span class="type">int64</span>  <span class="string">`json:&quot;amount_cents&quot;`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">SubmitOrder</span><span class="params">(cfg SagaConfig, gid <span class="type">string</span>, req OrderPayload)</span></span> <span class="type">error</span> &#123;</span><br><span class="line"><span class="keyword">if</span> gid == <span class="string">&quot;&quot;</span> || req.OrderID == <span class="string">&quot;&quot;</span> || req.UserID &lt;= <span class="number">0</span> ||</span><br><span class="line">req.ProductID &lt;= <span class="number">0</span> || req.Quantity &lt;= <span class="number">0</span> || req.AmountCents &lt;= <span class="number">0</span> &#123;</span><br><span class="line"><span class="keyword">return</span> fmt.Errorf(<span class="string">&quot;事务标识或订单参数不合法&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> cfg.DTMServer == <span class="string">&quot;&quot;</span> || cfg.InventoryBase == <span class="string">&quot;&quot;</span> || cfg.AccountBase == <span class="string">&quot;&quot;</span> &#123;</span><br><span class="line"><span class="keyword">return</span> fmt.Errorf(<span class="string">&quot;DTM 或业务回调地址未配置&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">inventory := strings.TrimRight(cfg.InventoryBase, <span class="string">&quot;/&quot;</span>)</span><br><span class="line">account := strings.TrimRight(cfg.AccountBase, <span class="string">&quot;/&quot;</span>)</span><br><span class="line">saga := dtmcli.NewSaga(cfg.DTMServer, gid)</span><br><span class="line">saga.Add(inventory+<span class="string">&quot;/deduct&quot;</span>, inventory+<span class="string">&quot;/restore&quot;</span>, req)</span><br><span class="line">saga.Add(account+<span class="string">&quot;/debit&quot;</span>, account+<span class="string">&quot;/refund&quot;</span>, req)</span><br><span class="line"><span class="keyword">if</span> err := saga.Submit(); err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> fmt.Errorf(<span class="string">&quot;提交订单事务未获得成功响应，请核对原 GID %s: %w&quot;</span>, gid, err)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>金额使用整数分传递，价格应由服务端根据商品和订单计算。示例中的 <code>AmountCents</code> 是内部服务参数，不应直接信任浏览器传入的金额。</p><p><code>Add</code> 声明正向与补偿地址，<code>Submit</code> 向协调服务提交事务。上述代码没有设置等待全局完成的选项，返回 <code>nil</code> 后应先向用户展示“处理中”，再通过业务状态查询获取结果。<a href="https://github.com/dtm-labs/client/blob/main/dtmcli/trans_saga.go">Saga 客户端实现</a>。</p><p>如果提交请求超时，不能立刻生成新 GID 再扣一次款。应保留原订单和 GID，按状态查询及恢复流程处理，避免把结果未知当成确定失败。</p><h2 id="8-3、业务分支接入屏障">8.3、业务分支接入屏障</h2><p>分支接口收到 DTM 的回调参数后，可以使用以下封装进入本地事务。示例针对 PostgreSQL；<code>db</code> 是已经初始化的 <code>*sql.DB</code>，<code>apply</code> 是使用传入 <code>tx</code> 执行本次业务 SQL 的函数。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> branch</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;database/sql&quot;</span></span><br><span class="line"><span class="string">&quot;net/url&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&quot;github.com/dtm-labs/client/dtmcli&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ApplyPostgresBranch</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function">db *sql.DB,</span></span></span><br><span class="line"><span class="params"><span class="function">query url.Values,</span></span></span><br><span class="line"><span class="params"><span class="function">apply <span class="keyword">func</span>(tx *sql.Tx)</span></span> <span class="type">error</span>,</span><br><span class="line">) <span class="type">error</span> &#123;</span><br><span class="line">barrier, err := dtmcli.BarrierFromQuery(query)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line">barrier.DBType = <span class="string">&quot;postgres&quot;</span></span><br><span class="line"><span class="keyword">return</span> barrier.CallWithDB(db, apply)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>接口层先校验请求，再传入回调 URL 的查询参数及业务函数。数据库驱动、屏障表、业务表和 HTTP 响应映射仍需在项目中配置。屏障负责提交或回滚该本地事务，业务回调不要自行调用 <code>tx.Commit()</code>。<a href="https://github.com/dtm-labs/client/blob/main/dtmcli/barrier.go">屏障 SDK 实现</a>。</p><p>回调里的业务 SQL 必须使用参数 <code>tx</code>。如果在回调中转而调用另一个独立连接上的 <code>db.Exec</code>，屏障记录和业务修改就不再属于同一次提交。</p><p>接入 GoFrame 等 ORM 时，也需要确认数据库方言与事务适配方式，确保所有写入复用屏障管理的事务连接。仅仅在外面包一层函数，内部继续使用默认数据库连接，并不能获得正确的事务边界。</p><h1 id="9、HTTP-分支响应不能只看-JSON-字段">9、HTTP 分支响应不能只看 JSON 字段</h1><p>按 DTM 的 HTTP 分支协议，下面几类结果有不同含义：</p><table><thead><tr><th>HTTP 状态码</th><th>含义</th><th>业务处理示例</th></tr></thead><tbody><tr><td><code>200</code></td><td>操作成功</td><td>扣库存已提交，或重复请求已被正确处理</td></tr><tr><td><code>409</code></td><td>确定的业务失败</td><td>Saga 正向扣款时确认余额不足，且未扣款</td></tr><tr><td><code>425</code></td><td>操作仍在处理中</td><td>已受理的外部流程尚无最终结果</td></tr><tr><td>其他错误，如 <code>500</code></td><td>临时故障</td><td>数据库暂时不可用，需要重试</td></tr></tbody></table><p>因此不能让全局响应中间件把所有分支结果都包装成 HTTP <code>200</code>，再仅在 JSON 中写 <code>code: 500</code>。这可能让协调方误判业务已经成功。具体映射需与所使用的服务端版本保持一致。<a href="https://en.dtm.pub/practice/arch.html">DTM 分支结果协议</a>。</p><p>同样不要把数据库超时、连接失败都映射成 <code>409</code>。这些情况不一定是确定的业务拒绝，应保留重试或核对结果的空间。</p><p>补偿、TCC Confirm/Cancel、二阶段消息的后续分支属于需要最终完成的操作。它们遇到临时故障时应返回可重试结果；若存在永久无法完成的业务条件，需要重新设计流程，不能简单用 <code>409</code> 结束处理。</p><h1 id="10、事务状态如何展示给用户">10、事务状态如何展示给用户</h1><p>推荐在业务表中维护自己的处理状态，例如订单的 <code>processing</code>、<code>completed</code>、<code>cancelled</code>，并保留 <code>order_id</code>、GID 和必要的失败原因。这些名称是业务设计示例，不是 DTM 内部状态枚举。</p><p>客户端提交请求后可以获得订单号，展示“正在处理”，再查询业务状态。页面刷新后仍然可以通过订单号恢复展示，不依赖某次 HTTP 连接一直存在。</p><p>业务的最终成功状态必须在核对全局事务结果及业务数据后更新。不要因为库存分支完成就提前标记整笔订单成功，也不要仅凭浏览器超时就把订单取消。</p><p>查询或对账读取到过渡状态时，使用状态条件更新防止覆盖较新的终态。对于长时间未完成的事务，应提供可追踪的记录和人工处理入口。</p><h1 id="11、部署与故障恢复要点">11、部署与故障恢复要点</h1><h2 id="11-1、区分两类数据库">11.1、区分两类数据库</h2><p>协调服务的存储用于保存全局事务及调度状态；业务数据库保存订单、库存、账户和相应屏障记录。两者承担的职责不同，不能只创建协调服务的表，就认为业务分支已经获得幂等保障。</p><p>实际部署应按所选版本的官方配置初始化存储、设置持久化和备份，并验证协调服务重启后的恢复流程。<a href="https://github.com/dtm-labs/dtm">DTM 服务端仓库</a>。</p><h2 id="11-2、回调地址必须从-DTM-所在网络可达">11.2、回调地址必须从 DTM 所在网络可达</h2><p>提交给 DTM 的分支地址由协调服务访问。如果 DTM 运行在容器内，<code>127.0.0.1</code> 通常指向该容器自身；开发机上能访问的地址，不一定是容器或另一台服务器能访问的地址。</p><p>建议把协调地址与各业务回调地址分别配置。生产环境还应限制回调接口的访问来源，配置服务间认证，避免普通公网请求直接触发扣款或退款分支。</p><h2 id="11-3、重试需要配合监控">11.3、重试需要配合监控</h2><p>网络短暂中断可以靠重试恢复，但代码错误、错误的补偿金额或业务数据损坏不会因为重试就自动消失。</p><p>可以重点监控全局事务处理时长、分支重试次数、持续失败的补偿操作，以及业务账目是否一致。告警阈值按实际业务时效设置，日志中保留订单号、GID、Branch ID 和操作类型，便于跨服务追踪。</p><p>恢复或人工修复前先确认原事务状态。不要直接删除屏障记录来“放开重试”，否则曾经成功的操作可能再次修改数据。</p><h1 id="12、接入时容易踩的坑">12、接入时容易踩的坑</h1><table><thead><tr><th>现象</th><th>常见原因</th><th>改进方向</th></tr></thead><tbody><tr><td>同一订单重复扣款</td><td>每次重试都创建新的事务</td><td>持久化业务幂等键、订单号与 GID 的关联</td></tr><tr><td>补偿多次增加库存</td><td>补偿接口缺少重复与空补偿控制</td><td>正向、补偿都接入一致的屏障机制</td></tr><tr><td>屏障记录成功但业务没完成</td><td>业务写入使用了独立事务</td><td>统一使用屏障回调中的事务连接</td></tr><tr><td>服务报告成功，协调结果异常</td><td>全局中间件覆盖了 HTTP 状态</td><td>为 DTM 分支单独配置协议响应</td></tr><tr><td>一直重试但无法结束</td><td>临时错误和永久业务冲突未区分</td><td>修复业务条件，完善告警与对账</td></tr><tr><td>容器内回调失败</td><td>分支 URL 使用了错误的本机地址</td><td>从协调服务所在网络核对连通性</td></tr><tr><td>通知、外部扣款重复执行</td><td>将外部调用当成本地 SQL 的一部分</td><td>使用外部幂等键、可靠事件及结果查询</td></tr></tbody></table><p>这些问题需要结合数据库约束、业务状态机和恢复流程一起处理。DTM 能承担协调和重试，正确的资源变更与补偿语义仍由业务代码保证。</p><h1 id="13、在自己的项目中如何逐步使用">13、在自己的项目中如何逐步使用</h1><p>学习时可以先构造两个独立业务服务，实现 Saga 正向操作和补偿，再接入屏障，逐步观察重复调用、明确失败、响应丢失和服务重启后的行为。</p><p>进入实际项目之前，应专门验证提交超时后使用原 GID 恢复、补偿先于正向到达、同一分支并发重复请求，以及业务事务提交后进程退出等场景。本文代码用于说明接入结构，未进行服务部署或端到端运行验证。</p><p>对于当前博客，评论与留言主要是单库创建和分页查询，优先使用本地事务即可。数据库写入后让缓存失效的逻辑，也应先按访问规模完善重试或可靠事件机制；等出现明确的跨服务一致性需求，再评估引入 DTM 的收益和维护成本。</p>]]></content>
    
    
    <summary type="html">从订单、库存和账户扣款场景出发，整理 DTM 的 Saga、TCC、XA、二阶段消息、子事务屏障，以及 Go 接入与故障处理要点。</summary>
    
    
    
    <category term="技术" scheme="https://daixiaokang.com/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
    <category term="技术开发" scheme="https://daixiaokang.com/tags/%E6%8A%80%E6%9C%AF%E5%BC%80%E5%8F%91/"/>
    
    <category term="Go" scheme="https://daixiaokang.com/tags/Go/"/>
    
    <category term="DTM" scheme="https://daixiaokang.com/tags/DTM/"/>
    
    <category term="分布式事务" scheme="https://daixiaokang.com/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/"/>
    
  </entry>
  
  <entry>
    <title>DToken-Go认证与权限管理使用指南</title>
    <link href="https://daixiaokang.com/posts/d6d87e57.html"/>
    <id>https://daixiaokang.com/posts/d6d87e57.html</id>
    <published>2026-10-21T16:00:00.000Z</published>
    <updated>2026-10-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="1、DToken-Go-能解决什么问题">1、DToken-Go 能解决什么问题</h1><p>在后台管理系统、用户中心或开放平台中，完成账号密码校验之后，通常还需要签发 Token、保存登录状态、校验接口权限，以及处理退出登录、多设备登录和账号封禁等问题。</p><p><a href="https://github.com/Zany2/dtoken-go">DToken-Go</a> 将这些能力组织为可以按需接入的 Go 模块，提供登录认证、Session、角色与权限、终端管理，以及 Refresh Token、SSO、OAuth2 等扩展能力。</p><p><strong>认证用于确认当前是谁，授权用于判断当前账号能做什么。</strong> 两者都需要服务端执行，不能只靠前端隐藏按钮或菜单。</p><p>本文按项目文档及本地源码副本（提交 <code>91e4df7</code>）整理基础用法，主要介绍默认核心包和 GoFrame 集成。实际接入时应以所选版本的源码与 <code>go.mod</code> 为准；本文没有为本站安装依赖或启动示例服务。</p><span id="more"></span><h1 id="2、模块结构与安装方式">2、模块结构与安装方式</h1><h2 id="2-1、按用途选择模块">2.1、按用途选择模块</h2><p>该仓库使用多模块结构，不是所有代码都位于同一个 Go Module 中。</p><table><thead><tr><th>模块</th><th>用途</th></tr></thead><tbody><tr><td><code>defaults</code></td><td>组装默认存储、编码器、Token 生成器等组件</td></tr><tr><td><code>dtoken</code></td><td>对外提供登录、退出、权限等通用 API</td></tr><tr><td><code>core</code></td><td>配置、Manager、组件接口及核心实现</td></tr><tr><td><code>integrations/gf</code></td><td>GoFrame 上下文、中间件与 API 导出</td></tr><tr><td><code>integrations/gin</code></td><td>Gin 框架集成</td></tr><tr><td><code>com/storage/redis</code></td><td>使用 Redis 保存认证相关状态</td></tr><tr><td><code>sso</code></td><td>按需接入的单点登录模块</td></tr></tbody></table><p>独立使用认证核心时，可以安装：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">go get github.com/Zany2/dtoken-go/defaults</span><br><span class="line">go get github.com/Zany2/dtoken-go/dtoken</span><br></pre></td></tr></table></figure><p>已经使用 GoFrame 的项目，可以直接选择对应集成包：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">go get github.com/Zany2/dtoken-go/integrations/gf</span><br></pre></td></tr></table></figure><p>需要 Redis 存储时，再引入：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">go get github.com/Zany2/dtoken-go/com/storage/redis</span><br></pre></td></tr></table></figure><p>以上命令用于说明模块路径。正式项目应固定经过验证的兼容版本，并提交 <code>go.mod</code>、<code>go.sum</code>。仓库中的 <code>go.work</code> 用于仓库自身的多模块开发，业务项目不需要直接复制它。<a href="https://github.com/Zany2/dtoken-go#installation">项目安装说明</a>。</p><h2 id="2-2、不要混用不同层级的-API">2.2、不要混用不同层级的 API</h2><p>初次使用可以先选定一种方式：普通 Go 程序使用 <code>defaults</code> 和 <code>dtoken</code>，GoFrame 应用使用别名为 <code>gfdt</code> 的框架集成包。</p><p>全局函数、实例门面和请求上下文 API 的参数形式不完全相同。例如全局的 <code>dtoken.Logout(ctx, token)</code> 需要显式 Token，而请求上下文中的 <code>dCtx.Auth().Logout(ctx)</code> 可以从当前请求解析 Token。</p><h1 id="3、一个最小的登录与退出示例">3、一个最小的登录与退出示例</h1><p>默认 Builder 使用内存存储，适合先理解调用流程。下面是一个控制台示例，不包含 HTTP 登录接口，也不执行账号密码校验。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;context&quot;</span></span><br><span class="line"><span class="string">&quot;fmt&quot;</span></span><br><span class="line"><span class="string">&quot;log&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&quot;github.com/Zany2/dtoken-go/defaults&quot;</span></span><br><span class="line"><span class="string">&quot;github.com/Zany2/dtoken-go/dtoken&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line"><span class="keyword">if</span> err := run(); err != <span class="literal">nil</span> &#123;</span><br><span class="line">log.Fatal(err)</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">run</span><span class="params">()</span></span> <span class="type">error</span> &#123;</span><br><span class="line">mgr, err := defaults.NewBuilder().</span><br><span class="line">TokenName(<span class="string">&quot;Authorization&quot;</span>).</span><br><span class="line">Timeout(<span class="number">7200</span>).</span><br><span class="line">AutoRenew(<span class="literal">false</span>).</span><br><span class="line">IsShare(<span class="literal">false</span>).</span><br><span class="line">IsPrintBanner(<span class="literal">false</span>).</span><br><span class="line">Build()</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> fmt.Errorf(<span class="string">&quot;初始化认证管理器: %w&quot;</span>, err)</span><br><span class="line">&#125;</span><br><span class="line">dtoken.SetManager(mgr)</span><br><span class="line"><span class="keyword">defer</span> dtoken.DeleteAllManager()</span><br><span class="line"></span><br><span class="line">ctx := context.Background()</span><br><span class="line"><span class="comment">// 演示假定业务层已经完成身份校验。</span></span><br><span class="line">token, err := dtoken.Login(ctx, <span class="string">&quot;user-1001&quot;</span>, <span class="string">&quot;web&quot;</span>, <span class="string">&quot;browser-demo&quot;</span>)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> fmt.Errorf(<span class="string">&quot;签发登录凭证: %w&quot;</span>, err)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> err := dtoken.CheckLogin(ctx, token); err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line">loginID, err := dtoken.GetLoginID(ctx, token)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;当前登录账号:&quot;</span>, loginID)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> err := dtoken.AddPermissions(ctx, loginID, []<span class="type">string</span>&#123;<span class="string">&quot;article:read&quot;</span>&#125;); err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;可以读取文章:&quot;</span>, dtoken.HasPermission(ctx, loginID, <span class="string">&quot;article:read&quot;</span>))</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> err := dtoken.Logout(ctx, token); err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line">fmt.Println(<span class="string">&quot;退出后仍然登录:&quot;</span>, dtoken.IsLogin(ctx, token))</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>示例依次完成初始化、注册 Manager、登录、查询身份、添加演示权限和退出。<code>AutoRenew(false)</code> 用于先观察固定 TTL；需要活跃续期时再按业务要求开启。</p><p>内存存储跟随进程存在，进程重启后不能指望保留登录态，多实例之间也不会自动共享这些数据。<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/core/authentication_zh.md">登录认证指南</a>。</p><h1 id="4、真实的登录接口应该怎样组织">4、真实的登录接口应该怎样组织</h1><p><code>Login(ctx, loginID)</code> 的含义是为一个已经确认的身份建立登录态。它不会自动查询你的用户表，也不会验证用户填写的密码。</p><p>真实流程可以组织为：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">接收用户名与密码</span><br><span class="line">    → 校验输入并查询用户</span><br><span class="line">    → 校验密码哈希或验证码</span><br><span class="line">    → 得到数据库中的稳定用户 ID</span><br><span class="line">    → 调用 DToken-Go 建立登录态</span><br><span class="line">    → 将 Token 返回给客户端</span><br></pre></td></tr></table></figure><p>不要把浏览器提交的 <code>user_id</code> 直接交给 <code>Login</code>，也不要照搬演示程序，为所有登录用户赋予 <code>admin</code> 角色。用户 ID、角色与权限都应来自服务端可信的业务数据。</p><p>设备类型可以使用 <code>web</code>、<code>app</code> 等业务约定；设备 ID 用于区分具体终端。客户端提供的设备标识属于管理辅助信息，不应单独作为身份认证依据。</p><p>当配置 <code>TokenName(&quot;Authorization&quot;)</code> 并开启 Header 读取时，客户端可以按以下形式携带登录凭证：</p><figure class="highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">GET</span> <span class="string">/api/me</span> <span class="meta">HTTP/1.1</span></span><br><span class="line"><span class="attribute">Host</span><span class="punctuation">: </span>daixiaokang.com</span><br><span class="line"><span class="attribute">Authorization</span><span class="punctuation">: </span>Bearer &lt;登录接口返回的 Token&gt;</span><br></pre></td></tr></table></figure><p>这里的域名和路由仅说明请求结构，不代表本站已经提供该认证接口。Token 不放入 URL，不写入普通访问日志；服务端接收来源应与客户端发送方式保持一致。</p><h1 id="5、有效期、活跃超时和续期">5、有效期、活跃超时和续期</h1><table><thead><tr><th>配置</th><th>含义</th><th>示例值</th></tr></thead><tbody><tr><td><code>Timeout</code></td><td>本次签发或续期后的 Token 有效时长</td><td><code>7200</code>，两小时</td></tr><tr><td><code>ActiveTimeout</code></td><td>允许的最长不活跃时长</td><td><code>1800</code>，半小时</td></tr><tr><td><code>AutoRenew</code></td><td>登录校验时是否按规则触发自动续期</td><td><code>true</code> 或 <code>false</code></td></tr><tr><td><code>RenewMaxRefresh</code></td><td>剩余 TTL 达到该阈值时才考虑续期</td><td><code>3600</code>，一小时</td></tr><tr><td><code>RenewInterval</code></td><td>同一个 Token 的最小自动续期间隔</td><td><code>60</code>，一分钟</td></tr><tr><td><code>RefreshTokenTimeout</code></td><td>刷新凭证的有效时长</td><td><code>2592000</code>，三十天</td></tr></tbody></table><p>Builder 中这些数值时间配置的单位是<strong>秒</strong>，不要直接把 <code>time.Hour</code> 的纳秒数强制转换后传入。对支持 Duration 的配置，也可以使用 <code>TimeoutDuration(2 * time.Hour)</code> 等明确时长的入口。</p><p>开启自动续期后，<code>Timeout</code> 不能理解为“从首次登录起最多只能在线两小时”。持续活跃并成功续期的登录态可能继续存在；若业务需要强制重新认证，应另行设计最长登录时长策略。</p><p>配置之间还有关系：启用自动续期时不能把 <code>Timeout</code> 设成永不过期；续期阈值不能大于有效期，最小续期间隔也应小于有效期及已启用的活跃超时。初始化时检查 <code>Build()</code> 的错误，能及早发现不合法组合。<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/reference/configuration_zh.md">配置指南</a>。</p><h1 id="6、角色与权限怎么使用">6、角色与权限怎么使用</h1><h2 id="6-1、区分角色与权限">6.1、区分角色与权限</h2><p>角色可以表达人员分组，例如 <code>editor</code>、<code>admin</code>；权限可以表达具体动作，例如 <code>article:read</code>、<code>article:publish</code>。</p><p>给账号添加角色，并不意味着框架会自动从业务数据库解析这个角色拥有的所有权限。角色到权限的映射需要由业务系统提供，或通过动态权限来源接入。</p><p>下面的函数适合在可信的服务端授权流程中调用，演示给已有登录会话添加角色和权限：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">GrantEditorAccess</span><span class="params">(ctx context.Context, loginID <span class="type">string</span>)</span></span> <span class="type">error</span> &#123;</span><br><span class="line"><span class="keyword">if</span> err := dtoken.AddRoles(ctx, loginID, []<span class="type">string</span>&#123;<span class="string">&quot;editor&quot;</span>&#125;); err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> dtoken.AddPermissions(ctx, loginID, []<span class="type">string</span>&#123;</span><br><span class="line"><span class="string">&quot;article:read&quot;</span>,</span><br><span class="line"><span class="string">&quot;article:publish&quot;</span>,</span><br><span class="line">&#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这是函数片段，依赖 <code>context</code> 与 <code>dtoken</code> 导入。正式角色分配还应写入业务权限表，并处理权限变更后的缓存或 Session 同步；不要把演示授权函数直接暴露为任意用户可调用的接口。</p><h2 id="6-2、接口中先检查登录，再检查权限">6.2、接口中先检查登录，再检查权限</h2><p>已经持有 Token 的服务端代码，可以使用：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">CheckArticlePublish</span><span class="params">(ctx context.Context, token <span class="type">string</span>)</span></span> <span class="type">error</span> &#123;</span><br><span class="line"><span class="keyword">if</span> err := dtoken.CheckLogin(ctx, token); err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> dtoken.CheckPermissionByToken(ctx, token, <span class="string">&quot;article:publish&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>Has*</code> 适合只需要布尔值的判断；接口层希望保留拒绝或存储异常的具体原因时，可以使用返回错误的 <code>Check*</code>。检查某个权限不等于检查某条数据的归属，编辑文章时仍需判断作者、租户等业务条件。</p><p>多个权限还可以表达 AND、OR 关系，分别表示全部满足或至少满足一个。权限字符串支持分段通配符，例如 <code>article:*</code>；命名时保持分隔符与层级一致，不要把一个宽泛通配符当成所有接口都需要的默认权限。<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/core/permission_zh.md">权限管理指南</a>。</p><h1 id="7、权限从数据库读取：AccessProvider">7、权限从数据库读取：AccessProvider</h1><p>初步接入时可以把角色、权限放在 Session 中；如果业务已经有用户、角色和权限表，或者权限需要频繁调整，可以使用 <code>AccessProvider</code> 从业务系统解析。</p><p>Provider 能获得账号、认证体系和设备等上下文，业务可据此查询数据库或权限服务。使用时需要明确以下区别：</p><table><thead><tr><th>Provider 返回值</th><th>含义</th></tr></thead><tbody><tr><td><code>nil, nil</code></td><td>本次不接管，允许继续使用 Session 权限数据</td></tr><tr><td>空切片、无错误</td><td>明确表示没有权限，不回退到 Session</td></tr><tr><td>非空权限列表</td><td>使用 Provider 返回的数据</td></tr><tr><td>错误</td><td>本次权限解析失败，应拒绝并按接口规则处理</td></tr></tbody></table><p>尤其在权限撤销时，不能把“查到零条权限”误写成 <code>nil, nil</code>，否则可能继续使用旧的 Session 授权。动态查询也要设计超时、缓存失效和故障告警。<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/core/access-provider_zh.md">AccessProvider 指南</a>。</p><h1 id="8、接入-Redis-存储">8、接入 Redis 存储</h1><p>多实例部署时，应让相关实例使用一致的认证配置和共享存储。下面演示在初始化阶段从环境变量读取 Redis URL，创建存储并注册 Manager：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> authsetup</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;fmt&quot;</span></span><br><span class="line"><span class="string">&quot;os&quot;</span></span><br><span class="line"><span class="string">&quot;strings&quot;</span></span><br><span class="line"></span><br><span class="line">dtredis <span class="string">&quot;github.com/Zany2/dtoken-go/com/storage/redis&quot;</span></span><br><span class="line"><span class="string">&quot;github.com/Zany2/dtoken-go/defaults&quot;</span></span><br><span class="line"><span class="string">&quot;github.com/Zany2/dtoken-go/dtoken&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">InitRedisAuth</span><span class="params">()</span></span> <span class="type">error</span> &#123;</span><br><span class="line">redisURL := strings.TrimSpace(os.Getenv(<span class="string">&quot;DTOKEN_REDIS_URL&quot;</span>))</span><br><span class="line"><span class="keyword">if</span> redisURL == <span class="string">&quot;&quot;</span> &#123;</span><br><span class="line"><span class="keyword">return</span> fmt.Errorf(<span class="string">&quot;未配置 DTOKEN_REDIS_URL&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line">storage, err := dtredis.NewStorage(redisURL)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> fmt.Errorf(<span class="string">&quot;初始化认证存储失败: %w&quot;</span>, err)</span><br><span class="line">&#125;</span><br><span class="line">mgr, err := defaults.NewBuilder().</span><br><span class="line">SetStorage(storage).</span><br><span class="line">KeyPrefix(<span class="string">&quot;website:dev&quot;</span>).</span><br><span class="line">TokenName(<span class="string">&quot;Authorization&quot;</span>).</span><br><span class="line">Timeout(<span class="number">7200</span>).</span><br><span class="line">AutoRenew(<span class="literal">false</span>).</span><br><span class="line">IsPrintBanner(<span class="literal">false</span>).</span><br><span class="line">Build()</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">_ = storage.Close()</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line">dtoken.SetManager(mgr)</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>例如本地无密码 Redis 的 URL 可以是 <code>redis://127.0.0.1:6379/0</code>。真实密码从环境配置读取，不写进文章或版本库；连接错误的详细内容留在受控日志中，不直接返回客户端。</p><p><code>KeyPrefix</code> 用于区分项目或环境，生产部署应使用生产环境自己的前缀。Manager 初始化一次后供请求复用，不要在每个请求里创建 Redis 连接和 Manager。</p><p>上面的函数采用默认组件所有权，初始化成功后由应用关闭 Manager 时释放其持有的组件。多个 Manager 共用同一存储客户端时，需要按项目的组件所有权选项安排统一关闭；先停止新请求并排空正在执行的业务，再关闭认证组件。<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/integration/redis-storage_zh.md">Redis 存储指南</a>、<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/core/multi-auth_zh.md">组件生命周期说明</a>。</p><h1 id="9、在-GoFrame-中接入">9、在 GoFrame 中接入</h1><h2 id="9-1、先初始化框架-Manager">9.1、先初始化框架 Manager</h2><p>在 GoFrame 项目启动时，可以使用 <code>gfdt.NewBuilder()</code> 构建 Manager，再调用 <code>gfdt.SetManager(mgr)</code>。Builder 的返回值仍需检查错误；Redis 存储也可以通过 <code>SetStorage</code> 注入。</p><p>基础顺序如下：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">加载配置 → 创建存储和 Manager → 注册 Manager</span><br><span class="line">    → 注册请求上下文中间件 → 注册登录及受保护路由 → 启动服务</span><br></pre></td></tr></table></figure><p>应用退出时，在 HTTP 请求排空后关闭 Manager。不要在普通控制器内调用全局清理函数。</p><h2 id="9-2、路由与中间件示例">9.2、路由与中间件示例</h2><p>下面是路由注册函数。它依赖启动阶段已经注册的默认 Manager，并接收业务已经实现的登录处理器、文章处理器和认证错误处理器；它不是完整的启动程序。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> authroute</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;context&quot;</span></span><br><span class="line"></span><br><span class="line">gfdt <span class="string">&quot;github.com/Zany2/dtoken-go/integrations/gf&quot;</span></span><br><span class="line"><span class="string">&quot;github.com/gogf/gf/v2/net/ghttp&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RegisterAuthRoutes</span><span class="params">(</span></span></span><br><span class="line"><span class="params"><span class="function">s *ghttp.Server,</span></span></span><br><span class="line"><span class="params"><span class="function">loginHandler ghttp.HandlerFunc,</span></span></span><br><span class="line"><span class="params"><span class="function">articlesHandler ghttp.HandlerFunc,</span></span></span><br><span class="line"><span class="params"><span class="function">authFail <span class="keyword">func</span>(r *ghttp.Request, err <span class="type">error</span>)</span></span>,</span><br><span class="line">) &#123;</span><br><span class="line">ctx := context.Background()</span><br><span class="line">failOption := gfdt.WithFailFunc(authFail)</span><br><span class="line">s.Use(gfdt.RegisterDTokenContextMiddleware(ctx, failOption))</span><br><span class="line"></span><br><span class="line"><span class="comment">// 登录接口由业务层校验密码或验证码，不要求已有登录态。</span></span><br><span class="line">s.Group(<span class="string">&quot;/api&quot;</span>, <span class="function"><span class="keyword">func</span><span class="params">(group *ghttp.RouterGroup)</span></span> &#123;</span><br><span class="line">group.POST(<span class="string">&quot;/login&quot;</span>, loginHandler)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">s.Group(<span class="string">&quot;/api&quot;</span>, <span class="function"><span class="keyword">func</span><span class="params">(group *ghttp.RouterGroup)</span></span> &#123;</span><br><span class="line">group.Middleware(gfdt.AuthMiddleware(ctx, failOption))</span><br><span class="line">group.GET(<span class="string">&quot;/articles&quot;</span>, gfdt.CheckPermissionMiddleware(</span><br><span class="line">ctx, []<span class="type">string</span>&#123;<span class="string">&quot;article:read&quot;</span>&#125;, articlesHandler, authFail,</span><br><span class="line">))</span><br><span class="line">group.GET(<span class="string">&quot;/me&quot;</span>, <span class="function"><span class="keyword">func</span><span class="params">(r *ghttp.Request)</span></span> &#123;</span><br><span class="line">dCtx, ok := gfdt.GetDTokenContext(r)</span><br><span class="line"><span class="keyword">if</span> !ok &#123;</span><br><span class="line">authFail(r, gfdt.ErrNotLogin)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line">loginID, err := dCtx.Auth().GetLoginID(r.Context())</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">authFail(r, err)</span><br><span class="line"><span class="keyword">return</span></span><br><span class="line">&#125;</span><br><span class="line">r.Response.WriteJson(<span class="keyword">map</span>[<span class="type">string</span>]<span class="type">string</span>&#123;<span class="string">&quot;login_id&quot;</span>: loginID&#125;)</span><br><span class="line">&#125;)</span><br><span class="line">&#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上下文中间件用于接入请求上下文，不能把“已经注册上下文”理解为“所有接口已经要求登录”。<code>AuthMiddleware</code> 才在受保护路由上校验登录态，权限中间件继续检查对应业务权限。</p><p><code>authFail</code> 应由业务统一实现：未登录或 Token 失效通常返回 HTTP <code>401</code>，权限不足或账号受限返回 <code>403</code>，存储与服务内部故障返回适当的 <code>5xx</code>，详细错误写入服务端日志。返回后终止本次处理，避免继续执行业务。示例中的三个处理器都应传入有效函数。</p><p>项目还有动态路由授权入口 <code>AccessMiddleware</code>，可根据匹配的业务路由声明权限。接入初期先把固定路由的登录与权限关系理清，再集中管理规则，避免误把后台接口设置为公开接口。<a href="https://github.com/Zany2/dtoken-go/blob/main/examples/gf/main.go">完整 GoFrame 示例</a>、<a href="https://github.com/Zany2/dtoken-go/blob/main/integrations/gf/middleware.go">GoFrame 中间件实现</a>。</p><h1 id="10、刷新令牌与自动续期的区别">10、刷新令牌与自动续期的区别</h1><p>自动续期主要围绕当前仍有效的登录凭证延长 TTL；Refresh Token 则用于通过单独的刷新凭证换取新的令牌对。需要双令牌时，可以在身份校验成功后调用 <code>LoginWithRefreshToken</code>。</p><p>下面的函数片段展示调用顺序，假设 Manager 已初始化，<code>loginID</code> 来自可信的身份校验结果：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">RefreshExample</span><span class="params">(ctx context.Context, loginID <span class="type">string</span>)</span></span> <span class="type">error</span> &#123;</span><br><span class="line">pair, err := dtoken.LoginWithRefreshToken(ctx, loginID, <span class="string">&quot;web&quot;</span>, <span class="string">&quot;browser-demo&quot;</span>)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 真实项目由客户端保存刷新凭证，稍后向刷新接口提交。</span></span><br><span class="line">nextPair, err := dtoken.RefreshToken(ctx, pair.RefreshToken)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 演示结束时撤销最新的刷新凭证。</span></span><br><span class="line"><span class="keyword">return</span> dtoken.RevokeRefreshToken(ctx, nextPair.RefreshToken)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>刷新会轮换凭证，客户端应保存新的令牌对，不继续使用旧的 Refresh Token。多个请求同时发现需要刷新时，应合并成一次刷新流程，避免并发消费同一旧凭证。</p><p>刷新接口不能被“必须持有有效 Access Token”的中间件挡住，否则访问令牌到期后反而无法刷新；它应单独校验 Refresh Token，并配合自己的限流与异常处理。当前项目的普通登录刷新与 OAuth2 刷新是不同入口，不要混用。<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/security/refresh-token_zh.md">Refresh Token 指南</a>。</p><h1 id="11、终端管理与多认证体系">11、终端管理与多认证体系</h1><h2 id="11-1、退出、踢下线与顶下线">11.1、退出、踢下线与顶下线</h2><table><thead><tr><th>操作</th><th>主要用途</th></tr></thead><tbody><tr><td><code>Logout</code></td><td>当前凭证正常退出</td></tr><tr><td><code>Kickout</code></td><td>管理端主动踢出，保留下线原因</td></tr><tr><td><code>Replace</code></td><td>登录替换场景，保留被顶下线原因</td></tr><tr><td><code>LogoutByLoginID</code></td><td>对指定账号的全部终端执行退出</td></tr></tbody></table><p>选择操作时也要选择范围：当前 Token、账号、设备类型或某个设备。退出当前浏览器时，不应误调用账号全部终端退出。</p><p><code>IsConcurrent</code>、<code>IsShare</code>、<code>MaxLoginCount</code> 等配置共同决定并发登录和 Token 复用策略。需要多个独立会话时，不要同时期待所有登录都共享同一个 Token；具体组合参考<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/core/session-terminal_zh.md">Session 与终端管理</a>。</p><h2 id="11-2、用户端与管理端隔离">11.2、用户端与管理端隔离</h2><p>同一个应用同时提供用户端和后台管理端时，可以通过 <code>AuthType(&quot;user&quot;)</code>、<code>AuthType(&quot;admin&quot;)</code> 注册不同的 Manager。</p><p><code>AuthType</code> 参与认证数据的命名空间隔离，<code>KeyPrefix</code> 更适合区分项目或环境，两者职责不同。注册不同认证体系之后，登录、查询、退出和路由中间件都应选择对应体系。</p><p>尤其注意全局 <code>Login</code> 的可选参数顺序是设备类型、设备 ID、认证体系。<code>Login(ctx, id, &quot;web&quot;)</code> 中的 <code>web</code> 是设备类型，不是认证体系；需要指定体系时应按完整参数位置传入，或使用项目提供的实例、选项式入口。<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/core/multi-auth_zh.md">多认证体系指南</a>。</p><h1 id="12、常见问题与接入建议">12、常见问题与接入建议</h1><table><thead><tr><th>问题</th><th>排查方向</th></tr></thead><tbody><tr><td>登录后调用接口仍然未登录</td><td>检查 Manager 注册、Token 来源、认证体系和请求头</td></tr><tr><td>本地正常，多实例部署后时好时坏</td><td>检查是否仍使用各进程独立的内存存储</td></tr><tr><td>添加了 <code>admin</code> 角色仍无文章权限</td><td>角色与具体权限的映射需要业务提供</td></tr><tr><td>修改数据库权限后接口权限未变化</td><td>检查 Session 权限、Provider 返回值与缓存失效策略</td></tr><tr><td>刷新一次成功，再用原凭证刷新失败</td><td>刷新凭证已轮换，客户端应保存最新令牌对</td></tr><tr><td>Builder 初始化失败</td><td>检查时间单位、续期约束和组件配置，不忽略错误</td></tr><tr><td>JWT 能解析但登录校验失败</td><td>仍需检查服务端登录态、封禁、会话与有效期</td></tr></tbody></table><p>项目的 JWT 模式并不意味着完全无状态：Session、终端和权限等能力仍会使用服务端存储。需要 JWT 时应按对应指南配置自己的密钥，不能把客户端能够解析 Token 当成服务端认证通过。<a href="https://github.com/Zany2/dtoken-go/blob/main/docs/guide/security/jwt_zh.md">JWT 指南</a>。</p><p>建议先跑通“身份校验 → 登录 → 受保护接口 → 退出”的基本流程，再接入数据库权限、Redis、多终端和双令牌。Nonce、Ticket、ShortKey、OAuth2 等可选能力按实际场景启用，SSO 则作为独立模块设计接入边界。</p><p>本文示例已按项目接口整理，用于说明使用方式；没有运行认证服务、连接 Redis 或进行端到端验证。完整行为和版本变化可继续查阅<a href="https://github.com/Zany2/dtoken-go/tree/main/docs">项目文档中心</a>及<a href="https://github.com/Zany2/dtoken-go/tree/main/examples">示例目录</a>。</p>]]></content>
    
    
    <summary type="html">介绍 dtoken-go 的模块安装、登录与退出、权限角色、Redis 存储、GoFrame 中间件、刷新令牌及多认证体系的接入方式。</summary>
    
    
    
    <category term="技术" scheme="https://daixiaokang.com/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
    <category term="技术开发" scheme="https://daixiaokang.com/tags/%E6%8A%80%E6%9C%AF%E5%BC%80%E5%8F%91/"/>
    
    <category term="Go" scheme="https://daixiaokang.com/tags/Go/"/>
    
    <category term="DToken-Go" scheme="https://daixiaokang.com/tags/DToken-Go/"/>
    
    <category term="认证授权" scheme="https://daixiaokang.com/tags/%E8%AE%A4%E8%AF%81%E6%8E%88%E6%9D%83/"/>
    
  </entry>
  
  <entry>
    <title>GoFrame框架使用总结</title>
    <link href="https://daixiaokang.com/posts/be17033b.html"/>
    <id>https://daixiaokang.com/posts/be17033b.html</id>
    <published>2026-10-08T15:43:00.000Z</published>
    <updated>2026-10-21T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="1、基本介绍">1、基本介绍</h1><p>GoFrame 是一个面向 Go 项目开发的框架，除了 HTTP 服务，还提供配置、日志、校验、数据库访问等组件。学习时可以先围绕一个小接口，把请求接收、业务处理、数据库操作和响应返回串起来，再逐步理解其他模块。</p><p>本文以 <strong>GoFrame v2</strong> 为基础，整理开发中常用的写法和容易忽略的细节。查阅时官方文档处于 2.10.x 分支，实际项目仍应以自己的 <code>go.mod</code> 和 <code>gf</code> 工具版本为准，不直接混用 v1 的导入路径。</p><p>下面的留言示例用于讲解 GoFrame；当前博客的评论、留言后端使用 FastAPI，文章中的示例不代表本站已经迁移了后端框架。</p><ul><li><a href="https://goframe.org/">GoFrame 官网</a></li><li><a href="https://github.com/gogf/gf">官方源码仓库</a></li></ul><span id="more"></span><h1 id="2、创建项目与常用命令">2、创建项目与常用命令</h1><p>安装 Go 和官方 <code>gf</code> 命令行工具后，先确认本机版本。CLI 的安装方式可以参考<a href="https://goframe.org/docs/cli/install">官方工具安装文档</a>，项目依赖和 CLI 尽量使用相互匹配的版本。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">go version</span><br><span class="line">gf version</span><br><span class="line"></span><br><span class="line">gf init gf-notes</span><br><span class="line">cd gf-notes</span><br><span class="line">go mod tidy</span><br><span class="line">gf run main.go</span><br></pre></td></tr></table></figure><p><code>gf init</code> 创建脚手架项目；<code>gf run main.go</code> 会监视代码变化，重新编译并重启程序，适合开发阶段。它不是在原进程里替换代码，重启期间内存中的临时状态也会丢失。<a href="https://goframe.org/docs/cli/init">项目创建说明</a>、<a href="https://goframe.org/docs/cli/run">自动编译说明</a>。</p><p>其他常用命令：</p><table><thead><tr><th>命令</th><th>用途</th><th>使用时注意</th></tr></thead><tbody><tr><td><code>gf gen ctrl</code></td><td>根据 API 定义生成控制器相关代码</td><td>生成后检查路由注册和待实现方法</td></tr><tr><td><code>gf gen dao</code></td><td>根据数据库表生成 DAO、DO、Entity</td><td>数据库要先有表，不会代替建表迁移</td></tr><tr><td><code>gf gen service</code></td><td>从符合规范的 logic 实现生成 service 接口</td><td>手工维护接口时注意工具覆盖规则</td></tr><tr><td><code>go test ./...</code></td><td>执行 Go 测试</td><td>依赖数据库的测试与纯函数测试分开组织</td></tr><tr><td><code>go build -o bin/gf-notes .</code></td><td>编译当前项目</td><td>Windows 可把输出名写成 <code>bin/gf-notes.exe</code></td></tr></tbody></table><p>生成代码前先阅读对应目录的文件头。标明由工具维护的文件，不适合直接塞入业务逻辑，否则下次生成可能被覆盖。<a href="https://goframe.org/docs/cli/gen-dao">DAO 生成文档</a>、<a href="https://goframe.org/docs/cli/gen-service">Service 生成文档</a>。</p><h1 id="3、项目目录应该怎么理解">3、项目目录应该怎么理解</h1><p>官方脚手架中经常见到这些目录：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">api/                    对外接口的请求、响应定义</span><br><span class="line">internal/</span><br><span class="line">  cmd/                  启动命令与路由组装</span><br><span class="line">  controller/           将请求转换为业务调用和响应</span><br><span class="line">  service/              业务接口定义</span><br><span class="line">  logic/                业务接口的具体实现</span><br><span class="line">  dao/                  数据访问对象</span><br><span class="line">  model/</span><br><span class="line">    do/                 数据操作模型</span><br><span class="line">    entity/             数据表实体模型</span><br><span class="line">manifest/config/        应用配置</span><br><span class="line">resource/               静态资源</span><br><span class="line">main.go                 程序入口</span><br></pre></td></tr></table></figure><p>例如一个“发表留言”请求，可以按下面的顺序理解：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">HTTP 请求</span><br><span class="line">  → api：定义字段与基础校验</span><br><span class="line">  → controller：组织输入、调用业务服务</span><br><span class="line">  → service 接口 / logic 实现：执行业务规则</span><br><span class="line">  → dao：访问数据库</span><br><span class="line">  → controller：组装对外响应</span><br></pre></td></tr></table></figure><p><code>service</code> 在这套规范里主要是接口层，具体业务实现通常放在 <code>logic</code>。小演示可以直接在控制器里写逻辑；当多个入口需要复用同一套规则时，再抽到业务层更合适。<a href="https://goframe.org/en/docs/design/project-structure">官方工程目录设计</a>。</p><p>我会按以下边界组织自己的代码：</p><ul><li>API 对象只暴露接口确实需要的字段，不把数据库实体直接作为公开响应。</li><li>昵称整理、回复关系校验、状态控制等规则放在业务层，方便 HTTP、管理端和任务程序复用。</li><li>DAO 层不承包所有业务判断，避免出现“Service 只转发、DAO 装下所有逻辑”的情况。</li><li>使用生成式 Service 注册时，检查启动入口是否已经引入 logic 的注册包；生成了接口，不等于具体实现已经注册。</li></ul><h1 id="4、规范路由、参数校验与接口文档">4、规范路由、参数校验与接口文档</h1><p>规范路由把路径、请求方法和字段规则写进结构体，并用固定的处理函数签名接收请求。基础校验由框架完成，控制器处理校验后的请求。<a href="https://goframe.org/docs/web/router-registering-strict-router">规范路由文档</a>。</p><p>下面是一个独立的 <code>main.go</code> 演示。它只展示<strong>留言输入校验与统一响应</strong>，回显整理后的内容，不会保存到数据库。已有脚手架项目应把这些定义拆到对应目录，不要直接覆盖原入口。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">&quot;context&quot;</span></span><br><span class="line"><span class="string">&quot;strings&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="string">&quot;github.com/gogf/gf/v2/errors/gcode&quot;</span></span><br><span class="line"><span class="string">&quot;github.com/gogf/gf/v2/errors/gerror&quot;</span></span><br><span class="line"><span class="string">&quot;github.com/gogf/gf/v2/frame/g&quot;</span></span><br><span class="line"><span class="string">&quot;github.com/gogf/gf/v2/net/ghttp&quot;</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> MessagePreviewReq <span class="keyword">struct</span> &#123;</span><br><span class="line">g.Meta   <span class="string">`path:&quot;/messages/preview&quot; method:&quot;post&quot; tags:&quot;留言&quot; summary:&quot;校验留言内容&quot;`</span></span><br><span class="line">Nickname <span class="type">string</span> <span class="string">`json:&quot;nickname&quot; v:&quot;required|length:1,50&quot; dc:&quot;昵称&quot;`</span></span><br><span class="line">Content  <span class="type">string</span> <span class="string">`json:&quot;content&quot; v:&quot;required|length:1,2000&quot; dc:&quot;留言内容&quot;`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> MessagePreviewRes <span class="keyword">struct</span> &#123;</span><br><span class="line">Nickname <span class="type">string</span> <span class="string">`json:&quot;nickname&quot;`</span></span><br><span class="line">Content  <span class="type">string</span> <span class="string">`json:&quot;content&quot;`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> MessageController <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *MessageController)</span></span> Preview(ctx context.Context, req *MessagePreviewReq) (*MessagePreviewRes, <span class="type">error</span>) &#123;</span><br><span class="line">nickname := strings.TrimSpace(req.Nickname)</span><br><span class="line">content := strings.TrimSpace(req.Content)</span><br><span class="line"><span class="keyword">if</span> nickname == <span class="string">&quot;&quot;</span> || content == <span class="string">&quot;&quot;</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, gerror.NewCode(gcode.CodeValidationFailed, <span class="string">&quot;昵称和内容不能只包含空白字符&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> &amp;MessagePreviewRes&#123;Nickname: nickname, Content: content&#125;, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> &#123;</span><br><span class="line">s := g.Server()</span><br><span class="line">s.SetAddr(<span class="string">&quot;:8199&quot;</span>)</span><br><span class="line">s.SetOpenApiPath(<span class="string">&quot;/api.json&quot;</span>)</span><br><span class="line">s.SetSwaggerPath(<span class="string">&quot;/swagger&quot;</span>)</span><br><span class="line">s.Group(<span class="string">&quot;/api&quot;</span>, <span class="function"><span class="keyword">func</span><span class="params">(group *ghttp.RouterGroup)</span></span> &#123;</span><br><span class="line">group.Middleware(ghttp.MiddlewareHandlerResponse)</span><br><span class="line">group.Bind(<span class="built_in">new</span>(MessageController))</span><br><span class="line">&#125;)</span><br><span class="line">s.Run()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这个例子的接口地址为 <code>POST /api/messages/preview</code>；OpenAPI JSON 位于 <code>/api.json</code>，Swagger 页面位于 <code>/swagger</code>。请求体示例：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;nickname&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Zany&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;content&quot;</span><span class="punctuation">:</span> <span class="string">&quot;记录一下今天学到的内容。&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>几个常用标签可以这样记：</p><table><thead><tr><th>标签</th><th>作用</th><th>示例</th></tr></thead><tbody><tr><td><code>g.Meta</code></td><td>接口路径、方法、分组和说明</td><td><code>path:&quot;/messages&quot; method:&quot;get&quot;</code></td></tr><tr><td><code>json</code></td><td>JSON 字段名称</td><td><code>json:&quot;nickname&quot;</code></td></tr><tr><td><code>v</code></td><td>输入校验规则</td><td>`v:&quot;required</td></tr><tr><td><code>d</code></td><td>参数默认值</td><td><code>d:&quot;1&quot;</code></td></tr><tr><td><code>dc</code></td><td>文档字段说明</td><td><code>dc:&quot;页码&quot;</code></td></tr></tbody></table><p><code>required</code> 建议放在组合校验规则的前面。字段必填、长度合法，不等于业务合法；例如回复目标是否存在、用户是否有权限，还需要业务层继续判断。修改接口涉及 <code>0</code>、<code>false</code> 或“未传字段”的区别时，可以使用指针字段表达可选输入。<a href="https://goframe.org/docs/core/gvalid-rules">校验规则</a>。</p><p>注册 <code>MiddlewareHandlerResponse</code> 后，处理函数通常返回 <code>Res</code> 和 <code>error</code>，由中间件组织结果。不要在同一个普通 JSON 接口里既手动写响应，又返回另一份结果。业务码也不等于 HTTP 状态码；正式项目需要明确两者的对应规则，并对数据库内部错误做脱敏。<a href="https://goframe.org/docs/web/router-registering-strict-router-usage">规范路由使用说明</a>。</p><h1 id="5、配置与数据库驱动">5、配置与数据库驱动</h1><p>脚手架通常使用 <code>manifest/config/config.yaml</code>。以下为开发环境的配置形状，数据库账号是示例值：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">address:</span> <span class="string">&quot;:8199&quot;</span></span><br><span class="line">  <span class="attr">openapiPath:</span> <span class="string">&quot;/api.json&quot;</span></span><br><span class="line">  <span class="attr">swaggerPath:</span> <span class="string">&quot;/swagger&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="attr">logger:</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">&quot;./logs&quot;</span></span><br><span class="line">  <span class="attr">level:</span> <span class="string">&quot;all&quot;</span></span><br><span class="line">  <span class="attr">stdout:</span> <span class="literal">true</span></span><br><span class="line"></span><br><span class="line"><span class="attr">database:</span></span><br><span class="line">  <span class="attr">default:</span></span><br><span class="line">    <span class="attr">link:</span> <span class="string">&quot;pgsql:app:replace_me@tcp(127.0.0.1:5432)/gf_notes&quot;</span></span><br></pre></td></tr></table></figure><p>第 4 节为了便于单文件演示，在代码里设置了 Server 参数。回到工程项目时，可以统一使用配置文件，避免配置值与硬编码各维护一份。</p><p>GoFrame v2 的数据库驱动需要单独引入。例如 PostgreSQL 使用以下驱动包，并在程序启动时完成导入注册；驱动版本应与项目采用的框架版本匹配。<a href="https://goframe.org/en/docs/core/gdb">ORM 介绍</a>、<a href="https://goframe.org/docs/core/gdb-config-file">数据库配置格式</a>。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> _ <span class="string">&quot;github.com/gogf/gf/contrib/drivers/pgsql/v2&quot;</span></span><br></pre></td></tr></table></figure><p>配置组件可以通过 <code>g.Cfg()</code> 读取；<code>Get</code> 返回配置值和错误，<code>MustGet</code> 在读取失败时会触发 panic，因此关键业务路径应按需要选择错误处理方式。想用环境变量提供秘密信息时，要明确使用相应读取方法或配置适配逻辑，不要默认 YAML 中的任意 <code>$&#123;变量&#125;</code> 都会自动展开。<a href="https://goframe.org/docs/core/gcfg-funcs">配置读取方法</a>。</p><p>生产数据库密码放在部署环境或受保护的配置中，文章、仓库和日志里只保留示例。切换数据库类型时，驱动、连接格式、SQL 方言和主键返回方式都需要一起检查。</p><h1 id="6、数据库操作：先把查询边界写清楚">6、数据库操作：先把查询边界写清楚</h1><p>这一节的代码是业务函数片段，需要放入已配置 GoFrame 和 PostgreSQL 驱动的 Go 包中，并补齐对应 import。它们不属于上面的无数据库演示。</p><p>为了便于理解，约定演示表为 <code>demo_messages</code>，不是当前博客的生产表：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> demo_messages (</span><br><span class="line">    id <span class="type">BIGINT</span> GENERATED ALWAYS <span class="keyword">AS</span> <span class="keyword">IDENTITY</span> <span class="keyword">PRIMARY</span> KEY,</span><br><span class="line">    nickname <span class="type">VARCHAR</span>(<span class="number">50</span>) <span class="keyword">NOT</span> <span class="keyword">NULL</span>,</span><br><span class="line">    content TEXT <span class="keyword">NOT</span> <span class="keyword">NULL</span>,</span><br><span class="line">    status <span class="type">SMALLINT</span> <span class="keyword">NOT</span> <span class="keyword">NULL</span> <span class="keyword">DEFAULT</span> <span class="number">1</span>,</span><br><span class="line">    created_at <span class="type">TIMESTAMP</span> <span class="keyword">NOT</span> <span class="keyword">NULL</span> <span class="keyword">DEFAULT</span> <span class="built_in">CURRENT_TIMESTAMP</span>,</span><br><span class="line">    deleted_at <span class="type">TIMESTAMP</span> <span class="keyword">NULL</span></span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">CREATE</span> INDEX idx_demo_messages_public</span><br><span class="line">    <span class="keyword">ON</span> demo_messages (created_at <span class="keyword">DESC</span>, id <span class="keyword">DESC</span>)</span><br><span class="line">    <span class="keyword">WHERE</span> status <span class="operator">=</span> <span class="number">1</span> <span class="keyword">AND</span> deleted_at <span class="keyword">IS</span> <span class="keyword">NULL</span>;</span><br></pre></td></tr></table></figure><p>建表 SQL 和后面的代码都只是文章示例，运行前应使用独立的演示数据库。<code>gf gen dao</code> 是“从已有表生成代码”，数据库表结构变更仍需维护迁移脚本。</p><h2 id="6-1-创建：白名单组织写入字段">6.1 创建：白名单组织写入字段</h2><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">CreateMessage</span><span class="params">(ctx context.Context, nickname, content <span class="type">string</span>)</span></span> <span class="type">error</span> &#123;</span><br><span class="line">_, err := g.DB().Model(<span class="string">&quot;demo_messages&quot;</span>).Ctx(ctx).Data(g.Map&#123;</span><br><span class="line"><span class="string">&quot;nickname&quot;</span>: nickname,</span><br><span class="line"><span class="string">&quot;content&quot;</span>:  content,</span><br><span class="line"><span class="string">&quot;status&quot;</span>:   <span class="number">1</span>,</span><br><span class="line">&#125;).Insert()</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>调用这个函数前要完成输入整理和业务校验。<code>status</code> 由服务端决定，不让访客通过请求体修改。客户端提交什么就整包写入数据库，很容易把内部字段也暴露成可写字段。</p><p>创建与更新最好明确区分；<code>Save</code> 涉及冲突时的插入或更新语义，不能一律当成“新增”使用。涉及返回自增 ID 时，应核对具体数据库驱动的支持方式，尤其不要把所有数据库都当成 MySQL 的 <code>LastInsertId</code>。<a href="https://goframe.org/docs/core/gdb-chaining-insert-save">写入保存文档</a>。</p><h2 id="6-2-查询：列表和总数使用同一组过滤条件">6.2 查询：列表和总数使用同一组过滤条件</h2><p>下面片段需导入 <code>context</code>、<code>gerror</code>、<code>g</code> 和 <code>gtime</code>：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> MessageItem <span class="keyword">struct</span> &#123;</span><br><span class="line">ID        <span class="type">int64</span>       <span class="string">`json:&quot;id&quot; orm:&quot;id&quot;`</span></span><br><span class="line">Nickname  <span class="type">string</span>      <span class="string">`json:&quot;nickname&quot; orm:&quot;nickname&quot;`</span></span><br><span class="line">Content   <span class="type">string</span>      <span class="string">`json:&quot;content&quot; orm:&quot;content&quot;`</span></span><br><span class="line">CreatedAt *gtime.Time <span class="string">`json:&quot;created_at&quot; orm:&quot;created_at&quot;`</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">ListMessages</span><span class="params">(ctx context.Context, page, size <span class="type">int</span>)</span></span> ([]MessageItem, <span class="type">int</span>, <span class="type">error</span>) &#123;</span><br><span class="line"><span class="keyword">if</span> page &lt; <span class="number">1</span> || page &gt; <span class="number">10000</span> || size &lt; <span class="number">1</span> || size &gt; <span class="number">50</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, <span class="number">0</span>, gerror.New(<span class="string">&quot;分页参数不合法&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line">items := <span class="built_in">make</span>([]MessageItem, <span class="number">0</span>)</span><br><span class="line"><span class="keyword">var</span> total <span class="type">int</span></span><br><span class="line">err := g.DB().Model(<span class="string">&quot;demo_messages&quot;</span>).Ctx(ctx).</span><br><span class="line">Fields(<span class="string">&quot;id&quot;</span>, <span class="string">&quot;nickname&quot;</span>, <span class="string">&quot;content&quot;</span>, <span class="string">&quot;created_at&quot;</span>).</span><br><span class="line">Where(<span class="string">&quot;status&quot;</span>, <span class="number">1</span>).</span><br><span class="line">WhereNull(<span class="string">&quot;deleted_at&quot;</span>).</span><br><span class="line">OrderDesc(<span class="string">&quot;created_at&quot;</span>).OrderDesc(<span class="string">&quot;id&quot;</span>).</span><br><span class="line">Page(page, size).</span><br><span class="line">ScanAndCount(&amp;items, &amp;total, <span class="literal">false</span>)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, <span class="number">0</span>, err</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> items, total, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>ScanAndCount</code> 用来组织列表和总数查询，但不代表它们被合并成一条 SQL，也不自动保证并发写入时两次查询看到相同快照。这里第三个参数传 <code>false</code>，表示计数不沿用 <code>Fields</code> 作为 COUNT 参数。<a href="https://goframe.org/docs/core/gdb-chaining-query-scan-and-count">ScanAndCount 文档</a>。</p><p>公开列表需要始终带上状态和软删除条件。排序增加 <code>id</code> 作为相同创建时间下的确定顺序；深分页或持续新增的动态列表，可以考虑使用游标分页，而不是无限增大页码。</p><h2 id="6-3-更新与软删除：带上明确条件">6.3 更新与软删除：带上明确条件</h2><p>以下是软删除函数示例，需额外导入 <code>gtime</code>。调用前还要完成身份和权限校验：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">SoftDeleteMessage</span><span class="params">(ctx context.Context, id <span class="type">int64</span>)</span></span> <span class="type">error</span> &#123;</span><br><span class="line"><span class="keyword">if</span> id &lt;= <span class="number">0</span> &#123;</span><br><span class="line"><span class="keyword">return</span> gerror.New(<span class="string">&quot;留言 ID 不合法&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line">result, err := g.DB().Model(<span class="string">&quot;demo_messages&quot;</span>).Ctx(ctx).</span><br><span class="line">Where(<span class="string">&quot;id&quot;</span>, id).WhereNull(<span class="string">&quot;deleted_at&quot;</span>).</span><br><span class="line">Data(g.Map&#123;<span class="string">&quot;deleted_at&quot;</span>: gtime.Now()&#125;).Update()</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line">affected, err := result.RowsAffected()</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> affected == <span class="number">0</span> &#123;</span><br><span class="line"><span class="keyword">return</span> gerror.New(<span class="string">&quot;留言不存在或已经删除&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>软删除仅改变记录状态，不会自动保证你写的每条查询都排除已删除数据。需要区分框架已配置的软删除规则与自己手动维护的字段，避免只加了 <code>deleted_at</code>，查询时却忘记过滤。</p><p>条件值交给 ORM 参数化处理；排序字段、表名等不能简单视为普通参数，动态排序应使用服务端白名单映射，不能直接拼接用户输入。<a href="https://goframe.org/en/docs/core/gdb">ORM 使用说明</a>。</p><h1 id="7、事务与-Context">7、事务与 Context</h1><p>当多个数据库操作必须一起成功或失败时，使用事务。下面演示“创建一条留言并读取当前事务内可见的公开留言数”，只操作上面的演示表；计数仅用于展示事务读取，不应作为高并发计数器方案。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">CreateAndCount</span><span class="params">(ctx context.Context, nickname, content <span class="type">string</span>)</span></span> (<span class="type">int</span>, <span class="type">error</span>) &#123;</span><br><span class="line"><span class="keyword">var</span> total <span class="type">int</span></span><br><span class="line">err := g.DB().Transaction(ctx, <span class="function"><span class="keyword">func</span><span class="params">(ctx context.Context, tx gdb.TX)</span></span> <span class="type">error</span> &#123;</span><br><span class="line">_, err := tx.Model(<span class="string">&quot;demo_messages&quot;</span>).Data(g.Map&#123;</span><br><span class="line"><span class="string">&quot;nickname&quot;</span>: nickname,</span><br><span class="line"><span class="string">&quot;content&quot;</span>:  content,</span><br><span class="line"><span class="string">&quot;status&quot;</span>:   <span class="number">1</span>,</span><br><span class="line">&#125;).Insert()</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br><span class="line">total, err = tx.Model(<span class="string">&quot;demo_messages&quot;</span>).</span><br><span class="line">Where(<span class="string">&quot;status&quot;</span>, <span class="number">1</span>).WhereNull(<span class="string">&quot;deleted_at&quot;</span>).Count()</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>, err</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> total, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>该片段还需导入 <code>github.com/gogf/gf/v2/database/gdb</code>。事务闭包返回 <code>nil</code> 时提交，返回错误时回滚；示例显式使用 <code>tx</code>，让事务边界更容易看清。<a href="https://goframe.org/docs/core/gdb-chaining-transaction">事务文档</a>。</p><p>开发时要特别注意：</p><ul><li>请求的 <code>ctx</code> 应沿控制器、业务层、DAO 继续传递，不要随手替换成 <code>context.Background()</code>。</li><li>事务内遇到错误需要返回；只打印日志再返回 <code>nil</code>，可能导致本应回滚的操作提交。</li><li>不在事务里长时间请求外部 HTTP 服务，避免连接和锁一直被占用。</li><li>数据库提交与 Redis 操作不属于同一个本地事务，不能假设会一起回滚。</li><li>独立后台任务需要自己的生命周期与超时，不能永久依附已结束的请求 Context。</li></ul><h1 id="8、错误处理与日志">8、错误处理与日志</h1><p>业务失败与系统失败应区分处理。比如“回复目标不存在”可以返回明确提示；数据库连接串、SQL 和调用栈则留在服务端，不能直接返回给访客。</p><p><code>gerror.Wrap</code> 可以在保留错误链的同时补充操作语境，适合定位“哪一步失败”。不要每一层都重复打印同一个错误，最终处理边界统一记录通常更清晰。<a href="https://goframe.org/docs/core/gerror">错误处理文档</a>。</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">CountPublicMessages</span><span class="params">(ctx context.Context)</span></span> (<span class="type">int</span>, <span class="type">error</span>) &#123;</span><br><span class="line">total, err := g.DB().Model(<span class="string">&quot;demo_messages&quot;</span>).Ctx(ctx).</span><br><span class="line">Where(<span class="string">&quot;status&quot;</span>, <span class="number">1</span>).WhereNull(<span class="string">&quot;deleted_at&quot;</span>).Count()</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>, gerror.Wrap(err, <span class="string">&quot;查询公开留言总数失败&quot;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> total, <span class="literal">nil</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>日志建议记录请求标识、操作名、耗时和必要的业务 ID，方便把一次请求串起来。密码、Token、完整请求头和访客的私密信息不作为默认日志内容。</p><p>使用 <code>g.Log()</code> 时可通过 <code>logger</code> 配置业务日志的路径、级别和轮转。HTTP Server、ORM 等组件有各自的日志配置，修改 <code>logger</code> 并不意味着所有组件都会采用同样设置。<a href="https://goframe.org/docs/core/glog">日志组件</a>、<a href="https://goframe.org/docs/core/glog-config">日志配置</a>。</p><h1 id="9、结合留言和评论场景的设计思路">9、结合留言和评论场景的设计思路</h1><p>以下是接口设计建议，与具体框架无关。使用 GoFrame 时，可以把这些规则放在业务层和中间件中。</p><h2 id="9-1-分页与楼中楼">9.1 分页与楼中楼</h2><p>留言板使用普通分页即可，例如每页 30 条。文章评论则拆成两个查询入口：</p><ul><li>根评论列表：每页最多 30 条，每个根评论先带 3 条回复预览。</li><li>某楼层的回复列表：用户点击“查看更多”后，再按游标取下一批。</li></ul><p>不要先查所有评论，再在 Go 内存里截取第一页；也不要针对每条根评论单独执行一次回复查询。对于 30 个根评论，可以使用批量查询或窗口函数限制每个根评论的预览数量，避免 N+1 和无限展开。</p><p>回复要验证目标仍然存在、属于同一篇文章，并由服务端确定根评论 ID。文章关联标识使用稳定的文章 Key，不把完整域名作为唯一标识，后续换域名时更容易保留讨论记录。</p><h2 id="9-2-创建限流">9.2 创建限流</h2><p>对于公开留言，可以先采用“同一 IP，10 秒内最多创建一次”。多进程部署时应在 Redis 中执行原子操作，例如 <code>SET key value NX EX 10</code>；不要用“先 GET、再 SET”模拟互斥。</p><p>限流 Key 是否跨评论、留言共享，需要在产品规则中明确。代理后的真实 IP 只能从可信代理链获取，不能直接相信任意客户端提交的 <code>X-Forwarded-For</code>。IP 限流也不能代替登录权限、内容长度限制和必要的内容审核。</p><h2 id="9-3-查询缓存与创建后的可见性">9.3 查询缓存与创建后的可见性</h2><p>可以从短时间缓存公开列表开始，例如缓存第一页 30 秒。缓存 Key 至少包含文章标识、页码、每页数量和排序规则，不缓存访客邮箱等非公开信息。</p><p>创建成功后的流程可以设计为：</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">数据库提交成功</span><br><span class="line">  → 失效相关列表缓存，或递增文章/留言板的缓存版本</span><br><span class="line">  → 返回已创建的数据</span><br><span class="line">  → 前端立即显示自己的新内容</span><br><span class="line">  → 再刷新列表进行校准</span><br></pre></td></tr></table></figure><p>缓存失效必须在数据库提交成功后进行。若先删缓存、再提交，其他请求可能在这段时间读到旧数据库内容，并把旧结果重新写入缓存。即使提交后删除，仍需考虑已经在途的旧查询，因此并发较高时可结合版本号、短 TTL 和前端临时合并策略处理。</p><p>单机内存缓存可以作为轻量优化，但多个服务实例不会天然共享。限流和缓存需要跨实例一致时，应明确采用共享存储，并定义 Redis 暂不可用时是降级、拒绝，还是受控直查数据库。</p><h1 id="10、开发时容易踩的坑">10、开发时容易踩的坑</h1><table><thead><tr><th>现象</th><th>优先检查</th></tr></thead><tbody><tr><td>修改接口后路由没出现</td><td>API 元数据、控制器生成结果、路由组 <code>Bind</code> 是否完整</td></tr><tr><td>接口前缀重复</td><td>组路径和 <code>g.Meta path</code> 是否各写了一次 <code>/api</code></td></tr><tr><td>参数校验没按预期执行</td><td>是否使用规范路由、<code>v</code> 标签是否正确、必填规则和默认值是否冲突</td></tr><tr><td>找不到数据库驱动</td><td>对应 contrib 驱动是否安装并在启动路径导入</td></tr><tr><td>生成的字段与数据库不同</td><td>是否更新了表结构并重新执行 DAO 生成</td></tr><tr><td>事务没有回滚</td><td>闭包是否吞掉错误、操作是否真的使用了事务对象</td></tr><tr><td>列表空时返回 <code>null</code></td><td>切片是否初始化为空切片，接口契约是否约定为数组</td></tr><tr><td>查不到某行却没有报错</td><td>不要一律按 <code>sql.ErrNoRows</code> 判断；检查所用查询方法及返回对象是否为空</td></tr><tr><td>更新“成功”但数据没变</td><td>查询条件、更新字段和受影响行数是否符合预期</td></tr><tr><td>修改日志配置没生效</td><td>修改的是业务 logger，还是 Server / ORM 各自的日志配置</td></tr><tr><td>生成后手写代码丢失</td><td>是否修改了标明由工具维护的文件</td></tr><tr><td>新留言刚发表却看不到</td><td>缓存失效时机、在途旧查询与前端列表合并是否正确</td></tr></tbody></table><p>当前这篇先覆盖常见的 HTTP 与数据库开发过程。后续可以继续补充登录鉴权、文件上传、定时任务、自动化测试，以及更完整的业务项目示例。</p>]]></content>
    
    
    <summary type="html">整理 GoFrame v2 的项目分层、规范路由、参数校验、数据库操作、事务，以及分页、限流和缓存的实践思路。</summary>
    
    
    
    <category term="技术" scheme="https://daixiaokang.com/categories/%E6%8A%80%E6%9C%AF/"/>
    
    
    <category term="技术开发" scheme="https://daixiaokang.com/tags/%E6%8A%80%E6%9C%AF%E5%BC%80%E5%8F%91/"/>
    
    <category term="Go" scheme="https://daixiaokang.com/tags/Go/"/>
    
    <category term="GoFrame" scheme="https://daixiaokang.com/tags/GoFrame/"/>
    
  </entry>
  
  <entry>
    <title>个人网站总结</title>
    <link href="https://daixiaokang.com/posts/325ed63b.html"/>
    <id>https://daixiaokang.com/posts/325ed63b.html</id>
    <published>2026-10-07T18:19:03.000Z</published>
    <updated>2026-10-07T18:19:03.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="1、基本信息">1、基本信息</h1><ul><li>主域名： <a href="https://daixiaokang.com/">daixiaokang.com</a></li><li>www 入口： <a href="https://www.daixiaokang.com/">www.daixiaokang.com</a>（部署时统一跳转至主域名）</li></ul><h1 id="2、技术栈">2、技术栈</h1><ul><li>博客框架：Hexo 6.3.0</li><li>主题：Butterfly 4.3.1</li><li>源码仓库：Github</li><li>托管与部署：本网站采用多线部署，包括Vercel + Netlify + Cloudflare + Railway + Fleek + Render + Zeabur + Github Pages 等</li><li>评论系统：Twikoo系统 + Vercel部署 + MongoDB提供存储服务</li><li>CDN： 七牛云</li><li>SEO优化：谷歌 + 必应 + 百度</li><li>音乐平台：hexo-tag-aplayer + MetingJS</li><li>开发语言：HTML5 + CSS3 + JavaScript + Pug + YML等</li><li>版权声明：详见CC BY-NC-SA 4.0</li><li>文章摘要生成：Post-Abstract-AI</li></ul><h1 id="3、网站记录">3、网站记录</h1><ul><li>大学的时候就想搭一个自己的网站，但是迫于自己技术栈的限制没有成功。那个时候主要学习的还是linux系统和kali渗透，接触后端语言是从大二开始，那个时候Golang还没有现在这么火，于是就自学了Go和Java。但是看到学前端的同学可以制作这么炫酷的网页真的非常羡慕。于是在工作的第一年抽出时间搭了自己的网站。使用hexo的原因是因为框架偏前端，易上手。刚开始的时候也尝试过搭建一个可管理的网站，搜了很多模板。但是前端的效果都没有达到自己的预期。虽然现在网站使用的技术个人感觉比较简单，但是效果还是可以接受的。在这里非常感谢网站开源的作者<font color=blue>Fomalhuat</font>，借用他的开源版本搭建了自己的网站。</li></ul>]]></content>
    
    
    <summary type="html">个人网站介绍总结🌈</summary>
    
    
    
    <category term="生活" scheme="https://daixiaokang.com/categories/%E7%94%9F%E6%B4%BB/"/>
    
    
    <category term="个人网站" scheme="https://daixiaokang.com/tags/%E4%B8%AA%E4%BA%BA%E7%BD%91%E7%AB%99/"/>
    
  </entry>
  
  <entry>
    <title>Markdown语法与外挂标签写法汇总</title>
    <link href="https://daixiaokang.com/posts/2013454d.html"/>
    <id>https://daixiaokang.com/posts/2013454d.html</id>
    <published>2026-10-07T16:00:00.000Z</published>
    <updated>2026-10-07T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="1-Markdown语法自带格式">1.Markdown语法自带格式</h1><div class="note info flat"><p>参考：<a href="https://blog.csdn.net/u014061630/article/details/81359144">Markdown语法图文全面详解(10分钟学会)</a></p></div><div class="note warning flat"><p>注意：此页面偶尔会存在CSS冲突问题!</p></div><h2 id="1-1-代码块">1.1 代码块</h2><div class="tabs" id="guide-tabs-01"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-01-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-01-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-01-1"><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">\```shell</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">VSCode终端</span></span><br><span class="line">hexo clean; hexo s</span><br><span class="line">hexo clean; hexo g; hexo d</span><br><span class="line">git add .; git commit -m &quot;npm publish&quot;; npm version patch;</span><br><span class="line">git push</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Cmder终端</span></span><br><span class="line">hexo clean &amp;&amp; hexo s</span><br><span class="line">hexo clean &amp;&amp; hexo g &amp;&amp; hexo d</span><br><span class="line">git add . &amp;&amp; git commit -m &quot;npm publish&quot; &amp;&amp; npm version patch</span><br><span class="line">git push</span><br><span class="line">\```</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-01-2"><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">VSCode终端</span></span><br><span class="line">hexo clean; hexo s</span><br><span class="line">hexo clean; hexo g; hexo d</span><br><span class="line">git add .; git commit -m &quot;npm publish&quot;; npm version patch;</span><br><span class="line">git push</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Cmder终端</span></span><br><span class="line">hexo clean &amp;&amp; hexo s</span><br><span class="line">hexo clean &amp;&amp; hexo g &amp;&amp; hexo d</span><br><span class="line">git add . &amp;&amp; git commit -m &quot;npm publish&quot; &amp;&amp; npm version patch</span><br><span class="line">git push</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-2-多级标题">1.2 多级标题</h2><div class="tabs" id="guide-tabs-02"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-02-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-02-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-02-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># H1</span></span><br><span class="line"><span class="section">## H2</span></span><br><span class="line"><span class="section">### H3</span></span><br><span class="line"><span class="section">#### H4</span></span><br><span class="line"><span class="section">##### H5</span></span><br><span class="line"><span class="section">###### H6</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-02-2"><p>见本文章标题!</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-3-文字样式">1.3 文字样式</h2><div class="tabs" id="guide-tabs-03"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-03-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-03-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-03-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">u</span>&gt;</span></span>下划线演示<span class="language-xml"><span class="tag">&lt;/<span class="name">u</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line">文字<span class="strong">**加粗**</span>演示</span><br><span class="line"></span><br><span class="line">文字<span class="emphasis">*斜体*</span>演示</span><br><span class="line"></span><br><span class="line">文本<span class="code">`高亮`</span>演示</span><br><span class="line"></span><br><span class="line">文本~~删除~~线演示</span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">font</span> <span class="attr">size</span> = <span class="string">5</span>&gt;</span></span>5号字<span class="language-xml"><span class="tag">&lt;/<span class="name">font</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">font</span> <span class="attr">face</span>=<span class="string">&quot;黑体&quot;</span>&gt;</span></span>黑体<span class="language-xml"><span class="tag">&lt;/<span class="name">font</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">font</span> <span class="attr">color</span>=<span class="string">blue</span>&gt;</span></span>蓝色<span class="language-xml"><span class="tag">&lt;/<span class="name">font</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">table</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">tr</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">td</span> <span class="attr">bgcolor</span>=<span class="string">MistyRose</span>&gt;</span></span>这里的背景色是：MistyRosen，此处输入任意想输入的内容<span class="language-xml"><span class="tag">&lt;/<span class="name">td</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">tr</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">table</span>&gt;</span></span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-03-2"><p><u>下划线演示</u></p><p>文字<strong>加粗</strong>演示</p><p>文字<em>斜体</em>演示</p><p>文本<code>高亮</code>演示</p><p>文本<s>删除</s>线演示</p><p><font size = 5>5号字</font><br><font face="黑体">黑体</font><br><font color=blue>蓝色</font></p><table><tr><td bgcolor=MistyRose>这里的背景色是：MistyRosen，此处输入任意想输入的内容</td></tr></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><div class="note info flat"><p>上述要点可参考:<a href="https://blog.csdn.net/qq_43732429/article/details/108034518">【Markdown语法】字体颜色大小及文字底色设置</a></p></div><h2 id="1-4-引用">1.4 引用</h2><div class="tabs" id="guide-tabs-04"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-04-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-04-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-04-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="quote">&gt;  Java</span></span><br><span class="line"><span class="quote">&gt; 二级引用演示</span></span><br><span class="line"><span class="quote">&gt; MySQL</span></span><br><span class="line"><span class="quote">&gt; &gt;外键</span></span><br><span class="line"><span class="quote">&gt; &gt;</span></span><br><span class="line"><span class="quote">&gt; &gt;事务</span></span><br><span class="line"><span class="quote">&gt; &gt;</span></span><br><span class="line"><span class="quote">&gt; &gt;<span class="strong">**行级锁**</span>(引用内部一样可以用格式)</span></span><br><span class="line"><span class="quote">&gt;</span></span><br><span class="line"><span class="quote">&gt; ....</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-04-2"><blockquote><p>Java<br>二级引用演示<br>MySQL</p><blockquote><p>外键</p><p>事务</p><p><strong>行级锁</strong>(引用内部一样可以用格式)</p></blockquote><p>…</p></blockquote><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-5-分割线">1.5 分割线</h2><div class="tabs" id="guide-tabs-05"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-05-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-05-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-05-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line"><span class="strong">**<span class="emphasis">*</span></span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-05-2"><hr><hr><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-6-列表-跟空格都可以">1.6 列表(*,+,-跟空格都可以)</h2><h3 id="1-6-1-无序列表">1.6.1 无序列表</h3><div class="tabs" id="guide-tabs-06"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-06-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-06-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-06-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">*</span> Java</span><br><span class="line"><span class="bullet">*</span> Python</span><br><span class="line"><span class="bullet">*</span> ...</span><br><span class="line"></span><br><span class="line"><span class="bullet">+</span> Java</span><br><span class="line"><span class="bullet">+</span> Python</span><br><span class="line"><span class="bullet">+</span> ...</span><br><span class="line"></span><br><span class="line"><span class="bullet">-</span> Java</span><br><span class="line"><span class="bullet">-</span> Python</span><br><span class="line"><span class="bullet">-</span> ...</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-06-2"><ul><li>Java</li><li>Python</li><li>…</li></ul><ul><li>Java</li><li>Python</li><li>…</li></ul><ul><li>Java</li><li>Python</li><li>…</li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h3 id="1-6-2-有序列表">1.6.2 有序列表</h3><div class="tabs" id="guide-tabs-07"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-07-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-07-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-07-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 注意后面有空格</span></span><br><span class="line"><span class="bullet">1.</span></span><br><span class="line"><span class="bullet">2.</span></span><br><span class="line"><span class="bullet">3.</span></span><br><span class="line">4.</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-07-2"><ol><li></li><li></li><li></li><li></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-7-图片">1.7 图片</h2><div class="tabs" id="guide-tabs-08"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-08-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-08-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-08-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 本地图片</span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;/assets/home/optimized/pc_23-cover.webp&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;示例图片&quot;</span> <span class="attr">style</span>=<span class="string">&quot;zoom:50%;&quot;</span> /&gt;</span></span></span><br><span class="line"><span class="section"># 本站静态图片</span></span><br><span class="line">![<span class="string">背景示例</span>](<span class="link">/assets/home/optimized/pc_22-cover.webp</span>)</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-08-2"><p>本地图片:<br><img src="/assets/home/optimized/pc_23-cover.webp" alt="示例图片" style="zoom:50%;" /><br>本站静态图片:<br><img src="/assets/home/optimized/pc_22-cover.webp" alt="背景示例"></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-8-表格">1.8 表格</h2><div class="tabs" id="guide-tabs-09"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-09-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-09-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-09-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">| 项目标号 | 资金     | 备注 |</span><br><span class="line">| -------- | -------- | ---- |</span><br><span class="line">| 1        | 100，000 | 无   |</span><br><span class="line">| 2        | 200，000 | 无   |</span><br><span class="line">| 3        | 300,600  | 重要 |</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-09-2"><table><thead><tr><th>项目标号</th><th>资金</th><th>备注</th></tr></thead><tbody><tr><td>1</td><td>100，000</td><td>无</td></tr><tr><td>2</td><td>200，000</td><td>无</td></tr><tr><td>3</td><td>300,600</td><td>重要</td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="1-9-公式">1.9 公式</h2><div class="tabs" id="guide-tabs-10"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-10-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-10-2">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-10-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$$</span><br><span class="line">\Gamma(z)=\int<span class="emphasis">_0^\infty t^&#123;z-1&#125;e^&#123;-t&#125;dt.</span></span><br><span class="line"><span class="emphasis">$$</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-10-2"><p>$$<br>\Gamma(z)=\int_0^\infty t^{z-1}e^{-t}dt.<br>$$</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h1 id="2-Butterfly外挂标签">2.Butterfly外挂标签</h1><div class="note info flat"><p>这部分参考安知鱼:<a href="https://anzhiy.cn/posts/7d58.html">基于Butterfly的外挂标签引入</a></p></div><h2 id="2-1-行内文本样式-text">2.1 行内文本样式 text</h2><div class="tabs" id="guide-tabs-11"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-11-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-11-2">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-11-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-11-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;% u 文本内容 %&#125;</span><br><span class="line">&#123;% emp 文本内容 %&#125;</span><br><span class="line">&#123;% wavy 文本内容 %&#125;</span><br><span class="line">&#123;% del 文本内容 %&#125;</span><br><span class="line">&#123;% kbd 文本内容 %&#125;</span><br><span class="line">&#123;% psw 文本内容 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-11-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">1.</span> 带 &#123;% u 下划线 %&#125; 的文本</span><br><span class="line"><span class="bullet">2.</span> 带 &#123;% emp 着重号 %&#125; 的文本</span><br><span class="line"><span class="bullet">3.</span> 带 &#123;% wavy 波浪线 %&#125; 的文本</span><br><span class="line"><span class="bullet">4.</span> 带 &#123;% del 删除线 %&#125; 的文本</span><br><span class="line"><span class="bullet">5.</span> 键盘样式的文本 &#123;% kbd command %&#125; + &#123;% kbd D %&#125;</span><br><span class="line"><span class="bullet">6.</span> 密码样式的文本：&#123;% psw 这里没有验证码 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-11-3"><ol><li>带 <u>下划线</u> 的文本</li><li>带 <emp>着重号</emp> 的文本</li><li>带 <wavy>波浪线</wavy> 的文本</li><li>带 <del>删除线</del> 的文本</li><li>键盘样式的文本 <kbd>command</kbd> + <kbd>D</kbd></li><li>密码样式的文本：<psw>这里没有验证码</psw></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-2-行内文本-span">2.2 行内文本 span</h2><div class="tabs" id="guide-tabs-12"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-12-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-12-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-12-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-12-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-12-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% span 样式参数(参数以空格划分), 文本内容 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-12-2"><ol><li><code>字体</code>: logo, code</li><li><code>颜色</code>: red,yellow,green,cyan,blue,gray</li><li><code>大小</code>: small, h4, h3, h2, h1, large, huge, ultra</li><li><code>对齐方向</code>: left, center, right</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-12-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> 彩色文字</span><br><span class="line">在一段话中方便插入各种颜色的标签，包括：&#123;% span red, 红色 %&#125;、&#123;% span yellow, 黄色 %&#125;、&#123;% span green, 绿色 %&#125;、&#123;% span cyan, 青色 %&#125;、&#123;% span blue, 蓝色 %&#125;、&#123;% span gray, 灰色 %&#125;。</span><br><span class="line"><span class="bullet">-</span> 超大号文字</span><br><span class="line">文档「开始」页面中的标题部分就是超大号文字。</span><br><span class="line">&#123;% span center logo large, Volantis %&#125;</span><br><span class="line">&#123;% span center small, A Wonderful Theme for Hexo %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-12-4"><ul><li>彩色文字<br>在一段话中方便插入各种颜色的标签，包括：<span class='p red'>红色</span>、<span class='p yellow'>黄色</span>、<span class='p green'>绿色</span>、<span class='p cyan'>青色</span>、<span class='p blue'>蓝色</span>、<span class='p gray'>灰色</span>。</li><li>超大号文字<br>文档「开始」页面中的标题部分就是超大号文字。<br><span class='p center logo large'>Volantis</span><br><span class='p center small'>A Wonderful Theme for Hexo</span></li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-3-段落文本-p">2.3 段落文本 p</h2><div class="tabs" id="guide-tabs-13"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-13-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-13-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-13-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-13-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-13-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% p 样式参数(参数以空格划分), 文本内容 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-13-2"><ol><li><code>字体</code>: logo, code</li><li><code>颜色</code>: red,yellow,green,cyan,blue,gray</li><li><code>大小</code>: small, h4, h3, h2, h1, large, huge, ultra</li><li><code>对齐方向</code>: left, center, right</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-13-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> 彩色文字</span><br><span class="line">在一段话中方便插入各种颜色的标签，包括：&#123;% p red, 红色 %&#125;、&#123;% p yellow, 黄色 %&#125;、&#123;% p green, 绿色 %&#125;、&#123;% p cyan, 青色 %&#125;、&#123;% p blue, 蓝色 %&#125;、&#123;% p gray, 灰色 %&#125;。</span><br><span class="line"><span class="bullet">-</span> 超大号文字</span><br><span class="line">文档「开始」页面中的标题部分就是超大号文字。</span><br><span class="line">&#123;% p center logo large, Volantis %&#125;</span><br><span class="line">&#123;% p center small, A Wonderful Theme for Hexo %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-13-4"><ul><li>彩色文字<br>在一段话中方便插入各种颜色的标签，包括：<p class='p red'>红色</p>、<p class='p yellow'>黄色</p>、<p class='p green'>绿色</p>、<p class='p cyan'>青色</p>、<p class='p blue'>蓝色</p>、<p class='p gray'>灰色</p>。</li><li>超大号文字<br>文档「开始」页面中的标题部分就是超大号文字。</li></ul><p class='p center logo large'>Volantis</p><p class='p center small'>A Wonderful Theme for Hexo</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-4-引用note">2.4 引用note</h2><div class="tabs" id="guide-tabs-14"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-14-1">通用配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-14-2">语法格式</button></li><li class="tab"><button type="button" data-href="#guide-tabs-14-3">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-14-4">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-14-5">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-14-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">note:</span><br><span class="line">  # Note tag style values:</span><br><span class="line">  #  - simple    bs-callout old alert style. Default.</span><br><span class="line">  #  - modern    bs-callout new (v2-v3) alert style.</span><br><span class="line">  #  - flat      flat callout style with background, like on Mozilla or StackOverflow.</span><br><span class="line">  #  - disabled  disable all CSS styles import of note tag.</span><br><span class="line">  style: simple</span><br><span class="line">  icons: false</span><br><span class="line">  border<span class="emphasis">_radius: 3</span></span><br><span class="line"><span class="emphasis">  # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6).</span></span><br><span class="line"><span class="emphasis">  # Offset also applied to label tag variables. This option can work with disabled note tag.</span></span><br><span class="line"><span class="emphasis">  light_</span>bg<span class="emphasis">_offset: 0</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-14-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 自带icon</span></span><br><span class="line">&#123;% note [class] [no-icon] [style] %&#125;</span><br><span class="line">Any content (support inline tags too.io).</span><br><span class="line">&#123;% endnote %&#125;</span><br><span class="line"><span class="section"># 外部icon</span></span><br><span class="line">&#123;% note [color] [icon] [style] %&#125;</span><br><span class="line">Any content (support inline tags too.io).</span><br><span class="line">&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-14-3"><p>1.自带icon</p><table><thead><tr><th>参数</th><th style="text-align:center">用法</th></tr></thead><tbody><tr><td>class</td><td style="text-align:center">【可选】标识，不同的标识有不同的配色 （ default / primary / success / info / warning / danger ）</td></tr><tr><td>no-icon</td><td style="text-align:center">【可选】不显示 icon</td></tr><tr><td>style</td><td style="text-align:center">【可选】可以覆盖配置中的 style （simple/modern/flat/disabled）</td></tr></tbody></table><p>2.外部icon</p><table><thead><tr><th>参数</th><th style="text-align:center">用法</th></tr></thead><tbody><tr><td>class</td><td style="text-align:center">【可选】标识，不同的标识有不同的配色 （ default / blue / pink / red / purple / orange / green ）</td></tr><tr><td>no-icon</td><td style="text-align:center">【可选】可配置自定义 icon (只支持 fontawesome 图标, 也可以配置 no-icon )</td></tr><tr><td>style</td><td style="text-align:center">【可选】可以覆盖配置中的 style （simple/modern/flat/disabled）</td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-14-4"><details class="folding-tag" blue><summary> 1.自带icon </summary>              <div class='content'>              <p>1.<code>simple</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note simple %&#125;默认 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default simple %&#125;default 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary simple %&#125;primary 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success simple %&#125;success 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info simple %&#125;info 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning simple %&#125;warning 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger simple %&#125;danger 提示块标签&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>2.<code>modern</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note modern %&#125;默认 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default modern %&#125;default 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary modern %&#125;primary 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success modern %&#125;success 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info modern %&#125;info 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning modern %&#125;warning 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger modern %&#125;danger 提示块标签&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>3.<code>flat</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note flat %&#125;默认 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default flat %&#125;default 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary flat %&#125;primary 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success flat %&#125;success 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info flat %&#125;info 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning flat %&#125;warning 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger flat %&#125;danger 提示块标签&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>4.<code>disabled</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note disabled %&#125;默认 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default disabled %&#125;default 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary disabled %&#125;primary 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success disabled %&#125;success 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info disabled %&#125;info 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning disabled %&#125;warning 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger disabled %&#125;danger 提示块标签&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>5.<code>no-icon</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note no-icon %&#125;默认 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note default no-icon %&#125;default 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note primary no-icon %&#125;primary 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note success no-icon %&#125;success 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note info no-icon %&#125;info 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note warning no-icon %&#125;warning 提示块标签&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note danger no-icon %&#125;danger 提示块标签&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure>              </div>            </details><details class="folding-tag" blue><summary> 2.外部icon </summary>              <div class='content'>              <p>1.<code>simple</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note &#x27;fab fa-cc-visa&#x27; simple %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note blue &#x27;fas fa-bullhorn&#x27; simple %&#125;2021年快到了....&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note pink &#x27;fas fa-car-crash&#x27; simple %&#125;小心开车 安全至上&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note red &#x27;fas fa-fan&#x27; simple%&#125;这是三片呢？还是四片？&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note orange &#x27;fas fa-battery-half&#x27; simple %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note purple &#x27;far fa-hand-scissors&#x27; simple %&#125;剪刀石头布&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note green &#x27;fab fa-internet-explorer&#x27; simple %&#125;前端最讨厌的浏览器&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>2.<code>modern</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note &#x27;fab fa-cc-visa&#x27; modern %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note blue &#x27;fas fa-bullhorn&#x27; modern %&#125;2021年快到了....&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note pink &#x27;fas fa-car-crash&#x27; modern %&#125;小心开车 安全至上&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note red &#x27;fas fa-fan&#x27; modern%&#125;这是三片呢？还是四片？&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note orange &#x27;fas fa-battery-half&#x27; modern %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note purple &#x27;far fa-hand-scissors&#x27; modern %&#125;剪刀石头布&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note green &#x27;fab fa-internet-explorer&#x27; modern %&#125;前端最讨厌的浏览器&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>3.<code>flat</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note &#x27;fab fa-cc-visa&#x27; flat %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note blue &#x27;fas fa-bullhorn&#x27; flat %&#125;2021年快到了....&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note pink &#x27;fas fa-car-crash&#x27; flat %&#125;小心开车 安全至上&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note red &#x27;fas fa-fan&#x27; flat%&#125;这是三片呢？还是四片？&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note orange &#x27;fas fa-battery-half&#x27; flat %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note purple &#x27;far fa-hand-scissors&#x27; flat %&#125;剪刀石头布&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note green &#x27;fab fa-internet-explorer&#x27; flat %&#125;前端最讨厌的浏览器&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>4.<code>disabled</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note &#x27;fab fa-cc-visa&#x27; disabled %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note blue &#x27;fas fa-bullhorn&#x27; disabled %&#125;2021年快到了....&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note pink &#x27;fas fa-car-crash&#x27; disabled %&#125;小心开车 安全至上&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note red &#x27;fas fa-fan&#x27; disabled %&#125;这是三片呢？还是四片？&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note orange &#x27;fas fa-battery-half&#x27; disabled %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note purple &#x27;far fa-hand-scissors&#x27; disabled %&#125;剪刀石头布&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note green &#x27;fab fa-internet-explorer&#x27; disabled %&#125;前端最讨厌的浏览器&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure><p>5.<code>no-icon</code>样式</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% note no-icon %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note blue no-icon %&#125;2021年快到了....&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note pink no-icon %&#125;小心开车 安全至上&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note red no-icon %&#125;这是三片呢？还是四片？&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note orange no-icon %&#125;你是刷 Visa 还是 UnionPay&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note purple no-icon %&#125;剪刀石头布&#123;% endnote %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% note green no-icon %&#125;前端最讨厌的浏览器&#123;% endnote %&#125;</span><br></pre></td></tr></table></figure>              </div>            </details><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-14-5"><details class="folding-tag" blue><summary> 1.自带icon </summary>              <div class='content'>              <p>1.<code>simple</code>样式</p><div class="note simple"><p>默认 提示块标签</p></div><div class="note default simple"><p>default 提示块标签</p></div><div class="note primary simple"><p>primary 提示块标签</p></div><div class="note success simple"><p>success 提示块标签</p></div><div class="note info simple"><p>info 提示块标签</p></div><div class="note warning simple"><p>warning 提示块标签</p></div><div class="note danger simple"><p>danger 提示块标签</p></div>2.`modern`样式<div class="note modern"><p>默认 提示块标签</p></div><div class="note default modern"><p>default 提示块标签</p></div><div class="note primary modern"><p>primary 提示块标签</p></div><div class="note success modern"><p>success 提示块标签</p></div><div class="note info modern"><p>info 提示块标签</p></div><div class="note warning modern"><p>warning 提示块标签</p></div><div class="note danger modern"><p>danger 提示块标签</p></div><p>3.<code>flat</code>样式</p><div class="note flat"><p>默认 提示块标签</p></div><div class="note default flat"><p>default 提示块标签</p></div><div class="note primary flat"><p>primary 提示块标签</p></div><div class="note success flat"><p>success 提示块标签</p></div><div class="note info flat"><p>info 提示块标签</p></div><div class="note warning flat"><p>warning 提示块标签</p></div><div class="note danger flat"><p>danger 提示块标签</p></div><p>4.<code>disabled</code>样式</p><div class="note disabled"><p>默认 提示块标签</p></div><div class="note default disabled"><p>default 提示块标签</p></div><div class="note primary disabled"><p>primary 提示块标签</p></div><div class="note success disabled"><p>success 提示块标签</p></div><div class="note info disabled"><p>info 提示块标签</p></div><div class="note warning disabled"><p>warning 提示块标签</p></div><div class="note danger disabled"><p>danger 提示块标签</p></div><p>5.<code>no-icon</code>样式</p><div class="note no-icon flat"><p>默认 提示块标签</p></div><div class="note default no-icon flat"><p>default 提示块标签</p></div><div class="note primary no-icon flat"><p>primary 提示块标签</p></div><div class="note success no-icon flat"><p>success 提示块标签</p></div><div class="note info no-icon flat"><p>info 提示块标签</p></div><div class="note warning no-icon flat"><p>warning 提示块标签</p></div><div class="note danger no-icon flat"><p>danger 提示块标签</p></div>              </div>            </details><details class="folding-tag" blue><summary> 2.外部icon </summary>              <div class='content'>              <p>1.<code>simple</code>样式</p><div class="note icon-padding simple"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue icon-padding simple"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了…</p></div><div class="note pink icon-padding simple"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note red icon-padding simple"><i class="note-icon fas fa-fan"></i><p>这是三片呢？还是四片？</p></div><div class="note orange icon-padding simple"><i class="note-icon fas fa-battery-half"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple icon-padding simple"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石头布</p></div><div class="note green icon-padding simple"><i class="note-icon fab fa-internet-explorer"></i><p>前端最讨厌的浏览器</p></div><p>2.<code>modern</code>样式</p><div class="note icon-padding modern"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue icon-padding modern"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了…</p></div><div class="note pink icon-padding modern"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note red icon-padding modern"><i class="note-icon fas fa-fan"></i><p>这是三片呢？还是四片？</p></div><div class="note orange icon-padding modern"><i class="note-icon fas fa-battery-half"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple icon-padding modern"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石头布</p></div><div class="note green icon-padding modern"><i class="note-icon fab fa-internet-explorer"></i><p>前端最讨厌的浏览器</p></div><p>3.<code>flat</code>样式</p><div class="note icon-padding flat"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue icon-padding flat"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了…</p></div><div class="note pink icon-padding flat"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note red icon-padding flat"><i class="note-icon fas fa-fan"></i><p>这是三片呢？还是四片？</p></div><div class="note orange icon-padding flat"><i class="note-icon fas fa-battery-half"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple icon-padding flat"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石头布</p></div><div class="note green icon-padding flat"><i class="note-icon fab fa-internet-explorer"></i><p>前端最讨厌的浏览器</p></div><p>4.<code>disabled</code>样式</p><div class="note icon-padding disabled"><i class="note-icon fab fa-cc-visa"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue icon-padding disabled"><i class="note-icon fas fa-bullhorn"></i><p>2021年快到了…</p></div><div class="note pink icon-padding disabled"><i class="note-icon fas fa-car-crash"></i><p>小心开车 安全至上</p></div><div class="note red icon-padding disabled"><i class="note-icon fas fa-fan"></i><p>这是三片呢？还是四片？</p></div><div class="note orange icon-padding disabled"><i class="note-icon fas fa-battery-half"></i><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple icon-padding disabled"><i class="note-icon far fa-hand-scissors"></i><p>剪刀石头布</p></div><div class="note green icon-padding disabled"><i class="note-icon fab fa-internet-explorer"></i><p>前端最讨厌的浏览器</p></div><p>5.<code>no-icon</code>样式</p><div class="note no-icon flat"><p>你是刷 Visa 还是 UnionPay</p></div><div class="note blue no-icon flat"><p>2021年快到了…</p></div><div class="note pink no-icon flat"><p>小心开车 安全至上</p></div><div class="note red no-icon flat"><p>这是三片呢？还是四片？</p></div><div class="note orange no-icon flat"><p>你是刷 Visa 还是 UnionPay</p></div><div class="note purple no-icon flat"><p>剪刀石头布</p></div><div class="note green no-icon flat"><p>前端最讨厌的浏览器</p></div>              </div>            </details><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-5-上标标签-tip">2.5 上标标签 tip</h2><div class="tabs" id="guide-tabs-15"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-15-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-15-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-15-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-15-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-15-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip [参数，可选] %&#125;文本内容&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-15-2"><ol><li><code>样式</code>: success,error,warning,bolt,ban,home,sync,cogs,key,bell</li><li><code>自定义图标</code>: 支持fontawesome。</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-15-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip %&#125;default&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip info %&#125;info&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip success %&#125;success&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip error %&#125;error&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip warning %&#125;warning&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip bolt %&#125;bolt&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban %&#125;ban&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip home %&#125;home&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip sync %&#125;sync&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip cogs %&#125;cogs&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip key %&#125;key&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip bell %&#125;bell&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip fa-atom %&#125;自定义font awesome图标&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-15-4"><div class="tip "><p>default</p></div><div class="tip info"><p>info</p></div><div class="tip success"><p>success</p></div><div class="tip error"><p>error</p></div><div class="tip warning"><p>warning</p></div><div class="tip bolt"><p>bolt</p></div><div class="tip ban"><p>ban</p></div><div class="tip home"><p>home</p></div><div class="tip sync"><p>sync</p></div><div class="tip cogs"><p>cogs</p></div><div class="tip key"><p>key</p></div><div class="tip bell"><p>bell</p></div><div class="tip fa-atom"><p>自定义font awesome图标</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-6-动态标签-anima">2.6 动态标签 anima</h2><div class="tabs" id="guide-tabs-16"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-16-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-16-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-16-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-16-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-16-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip [参数，可选] %&#125;文本内容&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-16-2"><div class="note info flat"><ol><li>将所需的CSS类添加到图标（或DOM中的任何元素）。</li><li>对于父级悬停样式，需要给目标元素添加指定CSS类，同时还要给目标元素的父级元素添加CSS类<code>faa-parent animated-hover</code>。（详情见示例及示例源码）<br>You can regulate the speed of the animation by adding the CSS class or . faa-fastfaa-slow</li><li>可以通过给目标元素添加CSS类<code>faa-fast</code>或<code>faa-slow</code>来控制动画快慢。</li></ol></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-16-3"><p>1.On DOM load（当页面加载时显示动画）</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip warning faa-horizontal animated %&#125;warning&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban faa-flash animated %&#125;ban&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure><p>2.调整动画速度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip warning faa-horizontal animated faa-fast %&#125;warning&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban faa-flash animated faa-slow %&#125;ban&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure><p>3.On hover（当鼠标悬停时显示动画）</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip warning faa-horizontal animated-hover %&#125;warning&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban faa-flash animated-hover %&#125;ban&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure><p>4.On parent hover（当鼠标悬停在父级元素时显示动画）</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tip warning faa-parent animated-hover %&#125;<span class="language-xml"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;faa-horizontal&quot;</span>&gt;</span></span>warning<span class="language-xml"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span>&#123;% endtip %&#125;</span><br><span class="line">&#123;% tip ban faa-parent animated-hover %&#125;<span class="language-xml"><span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;faa-flash&quot;</span>&gt;</span></span>ban<span class="language-xml"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span>&#123;% endtip %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-16-4"><p>1.On DOM load（当页面加载时显示动画）</p><div class="tip warning faa-horizontal animated"><p>warning</p></div><div class="tip ban faa-flash animated"><p>ban</p></div>2.调整动画速度<div class="tip warning faa-horizontal animated faa-fast"><p>warning</p></div><div class="tip ban faa-flash animated faa-slow"><p>ban</p></div>3.On hover（当鼠标悬停时显示动画）<div class="tip warning faa-horizontal animated-hover"><p>warning</p></div><div class="tip ban faa-flash animated-hover"><p>ban</p></div>4.On parent hover（当鼠标悬停在父级元素时显示动画）<div class="tip warning faa-parent animated-hover"><p class="faa-horizontal">warning</p></div><div class="tip ban faa-parent animated-hover"><p class="faa-flash">ban</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-7-复选列表-checkbox">2.7 复选列表 checkbox</h2><div class="tabs" id="guide-tabs-17"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-17-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-17-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-17-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-17-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-17-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% checkbox 样式参数（可选）, 文本（支持简单md） %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-17-2"><ol><li><code>样式</code>: plus, minus, times</li><li><code>颜色</code>: red,yellow,green,cyan,blue,gray</li><li><code>选中状态</code>: checked</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-17-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;% checkbox 纯文本测试 %&#125;</span><br><span class="line">&#123;% checkbox checked, 支持简单的 [<span class="string">markdown</span>](<span class="link">https://guides.github.com/features/mastering-markdown/</span>) 语法 %&#125;</span><br><span class="line">&#123;% checkbox red, 支持自定义颜色 %&#125;</span><br><span class="line">&#123;% checkbox green checked, 绿色 + 默认选中 %&#125;</span><br><span class="line">&#123;% checkbox yellow checked, 黄色 + 默认选中 %&#125;</span><br><span class="line">&#123;% checkbox cyan checked, 青色 + 默认选中 %&#125;</span><br><span class="line">&#123;% checkbox blue checked, 蓝色 + 默认选中 %&#125;</span><br><span class="line">&#123;% checkbox plus green checked, 增加 %&#125;</span><br><span class="line">&#123;% checkbox minus yellow checked, 减少 %&#125;</span><br><span class="line">&#123;% checkbox times red checked, 叉 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-17-4"><div class='checkbox'><input type="checkbox" />            <p>纯文本测试</p>            </div><div class='checkbox checked'><input type="checkbox" checked="checked"/>            <p>支持简单的 <a href="https://guides.github.com/features/mastering-markdown/">markdown</a> 语法</p>            </div><div class='checkbox red'><input type="checkbox" />            <p>支持自定义颜色</p>            </div><div class='checkbox green checked'><input type="checkbox" checked="checked"/>            <p>绿色 + 默认选中</p>            </div><div class='checkbox yellow checked'><input type="checkbox" checked="checked"/>            <p>黄色 + 默认选中</p>            </div><div class='checkbox cyan checked'><input type="checkbox" checked="checked"/>            <p>青色 + 默认选中</p>            </div><div class='checkbox blue checked'><input type="checkbox" checked="checked"/>            <p>蓝色 + 默认选中</p>            </div><div class='checkbox plus green checked'><input type="checkbox" checked="checked"/>            <p>增加</p>            </div><div class='checkbox minus yellow checked'><input type="checkbox" checked="checked"/>            <p>减少</p>            </div><div class='checkbox times red checked'><input type="checkbox" checked="checked"/>            <p>叉</p>            </div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-8-单选列表-radio">2.8 单选列表 radio</h2><div class="tabs" id="guide-tabs-18"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-18-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-18-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-18-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-18-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-18-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% radio 样式参数（可选）, 文本（支持简单md） %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-18-2"><ol><li><code>颜色</code>: red,yellow,green,cyan,blue,gray</li><li><code>选中状态</code>: checked</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-18-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;% radio 纯文本测试 %&#125;</span><br><span class="line">&#123;% radio checked, 支持简单的 [<span class="string">markdown</span>](<span class="link">https://guides.github.com/features/mastering-markdown/</span>) 语法 %&#125;</span><br><span class="line">&#123;% radio red, 支持自定义颜色 %&#125;</span><br><span class="line">&#123;% radio green, 绿色 %&#125;</span><br><span class="line">&#123;% radio yellow, 黄色 %&#125;</span><br><span class="line">&#123;% radio cyan, 青色 %&#125;</span><br><span class="line">&#123;% radio blue, 蓝色 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-18-4"><div class='checkbox'><input type="radio" />            <p>纯文本测试</p>            </div><div class='checkbox checked'><input type="radio" checked="checked"/>            <p>支持简单的 <a href="https://guides.github.com/features/mastering-markdown/">markdown</a> 语法</p>            </div><div class='checkbox red'><input type="radio" />            <p>支持自定义颜色</p>            </div><div class='checkbox green'><input type="radio" />            <p>绿色</p>            </div><div class='checkbox yellow'><input type="radio" />            <p>黄色</p>            </div><div class='checkbox cyan'><input type="radio" />            <p>青色</p>            </div><div class='checkbox blue'><input type="radio" />            <p>蓝色</p>            </div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-9-时间轴-timeline">2.9 时间轴 timeline</h2><div class="tabs" id="guide-tabs-19"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-19-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-19-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-19-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-19-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-19-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;% timeline 时间线标题（可选）[,color] %&#125;</span><br><span class="line">&lt;!-- timeline 时间节点（标题） --&gt;</span><br><span class="line">正文内容</span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line">&lt;!-- timeline 时间节点（标题） --&gt;</span><br><span class="line">正文内容</span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line">&#123;% endtimeline %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-19-2"><ol><li><code>title</code>:标题/时间线</li><li><code>color</code>:<code>timeline</code>颜色:default(留空) / blue / pink / red / purple / orange / green</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-19-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">&#123;% timeline 时间轴样式,blue %&#125;</span><br><span class="line"></span><br><span class="line">&lt;!-- timeline 2020-07-24 [<span class="string">2.6.6 -&gt; 3.0</span>](<span class="link">https://github.com/volantis-x/hexo-theme-volantis/releases</span>) --&gt;</span><br><span class="line"></span><br><span class="line"><span class="bullet">1.</span> 如果有 <span class="code">`hexo-lazyload-image`</span> 插件，需要删除并重新安装最新版本，设置 <span class="code">`lazyload.isSPA: true`</span>。</span><br><span class="line"><span class="bullet">2.</span> 2.x 版本的 css 和 js 不适用于 3.x 版本，如果使用了 <span class="code">`use_cdn: true`</span> 则需要删除。</span><br><span class="line"><span class="bullet">3.</span> 2.x 版本的 fancybox 标签在 3.x 版本中被重命名为 gallery 。</span><br><span class="line"><span class="bullet">4.</span> 2.x 版本的置顶 <span class="code">`top: true`</span> 改为了 <span class="code">`pin: true`</span>，并且同样适用于 <span class="code">`layout: page`</span> 的页面。</span><br><span class="line"><span class="bullet">5.</span> 如果使用了 <span class="code">`hexo-offline`</span> 插件，建议卸载，3.0 版本默认开启了 pjax 服务。</span><br><span class="line"></span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- timeline 2020-05-15 [<span class="string">2.6.3 -&gt; 2.6.6</span>](<span class="link">https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.6</span>) --&gt;</span><br><span class="line"></span><br><span class="line">不需要额外处理。</span><br><span class="line"></span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- timeline 2020-04-20 [<span class="string">2.6.2 -&gt; 2.6.3</span>](<span class="link">https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.3</span>) --&gt;</span><br><span class="line"></span><br><span class="line"><span class="bullet">1.</span> 全局搜索 <span class="code">`seotitle`</span> 并替换为 <span class="code">`seo_title`</span>。</span><br><span class="line"><span class="bullet">2.</span> group 组件的索引规则有变，使用 group 组件的文章内，<span class="code">`group: group_name`</span> 对应的组件名必须是 <span class="code">`group_name`</span>。</span><br><span class="line"><span class="bullet">2.</span> group 组件的列表名优先显示文章的 <span class="code">`short_title`</span> 其次是 <span class="code">`title`</span>。</span><br><span class="line"></span><br><span class="line">&lt;!-- endtimeline --&gt;</span><br><span class="line"></span><br><span class="line">&#123;% endtimeline %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-19-4"><div class="timeline blue"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>时间轴样式</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2020-07-24 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases">2.6.6 -&gt; 3.0</a></p></div></div><div class='timeline-item-content'><ol><li>如果有 <code>hexo-lazyload-image</code> 插件，需要删除并重新安装最新版本，设置 <code>lazyload.isSPA: true</code>。</li><li>2.x 版本的 css 和 js 不适用于 3.x 版本，如果使用了 <code>use_cdn: true</code> 则需要删除。</li><li>2.x 版本的 fancybox 标签在 3.x 版本中被重命名为 gallery 。</li><li>2.x 版本的置顶 <code>top: true</code> 改为了 <code>pin: true</code>，并且同样适用于 <code>layout: page</code> 的页面。</li><li>如果使用了 <code>hexo-offline</code> 插件，建议卸载，3.0 版本默认开启了 pjax 服务。</li></ol></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2020-05-15 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.6">2.6.3 -&gt; 2.6.6</a></p></div></div><div class='timeline-item-content'><p>不需要额外处理。</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>2020-04-20 <a href="https://github.com/volantis-x/hexo-theme-volantis/releases/tag/2.6.3">2.6.2 -&gt; 2.6.3</a></p></div></div><div class='timeline-item-content'><ol><li>全局搜索 <code>seotitle</code> 并替换为 <code>seo_title</code>。</li><li>group 组件的索引规则有变，使用 group 组件的文章内，<code>group: group_name</code> 对应的组件名必须是 <code>group_name</code>。</li><li>group 组件的列表名优先显示文章的 <code>short_title</code> 其次是 <code>title</code>。</li></ol></div></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-10-链接卡片-link">2.10 链接卡片 link</h2><div class="tabs" id="guide-tabs-20"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-20-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-20-2">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-20-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-20-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% link 标题, 链接, 图片链接（可选） %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-20-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% link 糖果屋教程贴, https://akilar.top/posts/615e2dec/, /assets/avatar.png %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-20-3"><div class="tag link"><a class="link-card" title="糖果屋教程贴" href="https://akilar.top/posts/615e2dec/"><div class="left"><img src="/assets/avatar.png"/></div><div class="right"><p class="text">糖果屋教程贴</p><p class="url">https://akilar.top/posts/615e2dec/</p></div></a></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-11-按钮-btns">2.11 按钮 btns</h2><div class="tabs" id="guide-tabs-21"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-21-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-21-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-21-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-21-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-21-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btns 样式参数 %&#125;</span><br><span class="line">&#123;% cell 标题, 链接, 图片或者图标 %&#125;</span><br><span class="line">&#123;% cell 标题, 链接, 图片或者图标 %&#125;</span><br><span class="line">&#123;% endbtns %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-21-2"><ol><li>圆角样式：rounded, circle</li><li>增加文字样式：可以在容器内增加 <code>&lt;b&gt;</code>标题<code>&lt;/b&gt;</code>和<code>&lt;p&gt;</code>描述文字<code>&lt;/p&gt;</code></li><li>布局方式：<br>默认为自动宽度，适合视野内只有一两个的情况。</li></ol><table><thead><tr><th>参数</th><th>含义</th></tr></thead><tbody><tr><td>wide</td><td>宽一点的按钮</td></tr><tr><td>fill</td><td>填充布局，自动铺满至少一行，多了会换行</td></tr><tr><td>center</td><td>居中，按钮之间是固定间距</td></tr><tr><td>around</td><td>居中分散</td></tr><tr><td>grid2</td><td>等宽最多2列，屏幕变窄会适当减少列数</td></tr><tr><td>grid3</td><td>等宽最多3列，屏幕变窄会适当减少列数</td></tr><tr><td>grid4</td><td>等宽最多4列，屏幕变窄会适当减少列数</td></tr><tr><td>grid5</td><td>等宽最多5列，屏幕变窄会适当减少列数</td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-21-3"><p>1.如果需要显示类似「团队成员」之类的一组含有头像的链接</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btns circle grid5 %&#125;</span><br><span class="line">&#123;% cell xaoxuu, https://xaoxuu.com, /assets/fallback/avatar.png %&#125;</span><br><span class="line">&#123;% cell xaoxuu, https://xaoxuu.com, /assets/fallback/avatar.png %&#125;</span><br><span class="line">&#123;% cell xaoxuu, https://xaoxuu.com, /assets/fallback/avatar.png %&#125;</span><br><span class="line">&#123;% cell xaoxuu, https://xaoxuu.com, /assets/fallback/avatar.png %&#125;</span><br><span class="line">&#123;% cell xaoxuu, https://xaoxuu.com, /assets/fallback/avatar.png %&#125;</span><br><span class="line">&#123;% endbtns %&#125;</span><br></pre></td></tr></table></figure><p>2.或者含有图标的按钮</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btns rounded grid5 %&#125;</span><br><span class="line">&#123;% cell 下载源码, /, fas fa-download %&#125;</span><br><span class="line">&#123;% cell 查看文档, /, fas fa-book-open %&#125;</span><br><span class="line">&#123;% endbtns %&#125;</span><br></pre></td></tr></table></figure><p>3.圆形图标 + 标题 + 描述 + 图片 + 网格5列 + 居中</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&#123;% btns circle center grid5 %&#125;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&#x27;/box/gallery/wallpaper/&#x27;</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&#x27;fas fa-image&#x27;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">b</span>&gt;</span></span>横屏背景<span class="language-xml"><span class="tag">&lt;/<span class="name">b</span>&gt;</span></span></span><br><span class="line">  &#123;% p red, 本站图片示例 %&#125;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&#x27;/assets/home/optimized/pc_22-cover.webp&#x27;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&#x27;/box/gallery/wallpaper/&#x27;</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&#x27;fas fa-mobile-screen&#x27;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span></span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">b</span>&gt;</span></span>竖屏背景<span class="language-xml"><span class="tag">&lt;/<span class="name">b</span>&gt;</span></span></span><br><span class="line">  &#123;% p green, 本站图片示例 %&#125;</span><br><span class="line">  <span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&#x27;/assets/home/optimized/home_mobile_05-cover.webp&#x27;</span>&gt;</span></span></span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></span><br><span class="line">&#123;% endbtns %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-21-4"><p>1.如果需要显示类似「团队成员」之类的一组含有头像的链接</p><div class="btns circle grid5">            <a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='/assets/fallback/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='/assets/fallback/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='/assets/fallback/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='/assets/fallback/avatar.png'>xaoxuu</a><a class="button" href='https://xaoxuu.com' title='xaoxuu'><img src='/assets/fallback/avatar.png'>xaoxuu</a>          </div>2.或者含有图标的按钮<div class="btns rounded grid5">            <a class="button" href='/' title='下载源码'><i class='fas fa-download'></i>下载源码</a><a class="button" href='/' title='查看文档'><i class='fas fa-book-open'></i>查看文档</a>          </div>3.圆形图标 + 标题 + 描述 + 图片 + 网格5列 + 居中<div class="btns circle center grid5">            <a href='/box/gallery/wallpaper/'>  <i class='fas fa-image'></i>  <b>横屏背景</b>  <p class='p red'>本站图片示例</p>  <img src='/assets/home/optimized/pc_22-cover.webp'></a><a href='/box/gallery/wallpaper/'>  <i class='fas fa-mobile-screen'></i>  <b>竖屏背景</b>  <p class='p green'>本站图片示例</p>  <img src='/assets/home/optimized/home_mobile_05-cover.webp'></a>          </div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-12-github卡片-ghcard">2.12 github卡片 ghcard</h2><div class="tabs" id="guide-tabs-22"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-22-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-22-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-22-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-22-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-22-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% ghcard 用户名, 其它参数（可选） %&#125;</span><br><span class="line">&#123;% ghcard 用户名/仓库, 其它参数（可选） %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-22-2"><p>使用<code>,</code>分割各个参数。写法为：<code>参数名=参数值</code><br>以下只写几个常用参数值。</p><table><thead><tr><th><strong>参数名</strong></th><th>取值</th><th>释义</th></tr></thead><tbody><tr><td>hide</td><td>stars,commits,prs,issues,contribs</td><td>隐藏指定统计</td></tr><tr><td>count_private</td><td>true</td><td>将私人项目贡献添加到总提交计数中</td></tr><tr><td>show_icons</td><td>true</td><td>显示图标</td></tr><tr><td>theme</td><td>查阅:<a href="https://github.com/anuraghazra/github-readme-stats/blob/master/themes/README.md">Available Themes</a></td><td>主题</td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-22-3"><p>1.用户信息卡片</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">| &#123;% ghcard fomalhaut1998 %&#125; | &#123;% ghcard fomalhaut1998, theme=vue %&#125; |</span><br><span class="line">| -- | -- |</span><br><span class="line">| &#123;% ghcard fomalhaut1998, theme=buefy %&#125; | &#123;% ghcard fomalhaut1998, theme=solarized-light %&#125; |</span><br><span class="line">| &#123;% ghcard fomalhaut1998, theme=onedark %&#125; | &#123;% ghcard fomalhaut1998, theme=solarized-dark %&#125; |</span><br><span class="line">| &#123;% ghcard fomalhaut1998, theme=algolia %&#125; | &#123;% ghcard fomalhaut1998, theme=calm %&#125; |</span><br></pre></td></tr></table></figure><p>2.仓库信息卡片</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">| &#123;% ghcard volantis-x/hexo-theme-volantis %&#125; | &#123;% ghcard volantis-x/hexo-theme-volantis, theme=vue %&#125; |</span><br><span class="line">| -- | -- |</span><br><span class="line">| &#123;% ghcard volantis-x/hexo-theme-volantis, theme=buefy %&#125; | &#123;% ghcard volantis-x/hexo-theme-volantis, theme=solarized-light %&#125; |</span><br><span class="line">| &#123;% ghcard volantis-x/hexo-theme-volantis, theme=onedark %&#125; | &#123;% ghcard volantis-x/hexo-theme-volantis, theme=solarized-dark %&#125; |</span><br><span class="line">| &#123;% ghcard volantis-x/hexo-theme-volantis, theme=algolia %&#125; | &#123;% ghcard volantis-x/hexo-theme-volantis, theme=calm %&#125; |</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-22-4"><p>1.用户信息卡片</p><table><thead><tr><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&show_owner=true"/></a></th><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=vue&show_owner=true"/></a></th></tr></thead><tbody><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=buefy&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=solarized-light&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=onedark&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=solarized-dark&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=algolia&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/fomalhaut1998"><img src="https://github-readme-stats.vercel.app/api/?username=fomalhaut1998&theme=calm&show_owner=true"/></a></td></tr></tbody></table><p>2.仓库信息卡片</p><table><thead><tr><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&show_owner=true"/></a></th><th><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=vue&show_owner=true"/></a></th></tr></thead><tbody><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=buefy&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=solarized-light&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=onedark&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=solarized-dark&show_owner=true"/></a></td></tr><tr><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=algolia&show_owner=true"/></a></td><td><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/volantis-x/hexo-theme-volantis"><img src="https://github-readme-stats.vercel.app/api/pin/?username=volantis-x&repo=hexo-theme-volantis&theme=calm&show_owner=true"/></a></td></tr></tbody></table><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-13-github徽标-ghbdage">2.13 github徽标 ghbdage</h2><div class="tabs" id="guide-tabs-23"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-23-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-23-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-23-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-23-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-23-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bdage [right],[left],[logo]||[color],[link],[title]||[option] %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-23-2"><ol><li><code>left</code>：徽标左边的信息，必选参数。</li><li><code>right</code>: 徽标右边的信息，必选参数，</li><li><code>logo</code>：徽标图标，图标名称详见<a href="https://simpleicons.org/">simpleicons</a>，可选参数。</li><li><code>color</code>：徽标右边的颜色，可选参数。</li><li><code>link</code>：指向的链接，可选参数。</li><li><code>title</code>：徽标的额外信息，可选参数。主要用于优化SEO，但<code>object</code>标签不会像<code>a</code>标签一样在鼠标悬停显示<code>title</code>信息。</li><li><code>option</code>：自定义参数，支持<a href="https://shields.io/">shields.io</a>的全部API参数支持，具体参数可以参看上文中的拓展写法示例。形式为<code>name1=value2&amp;name2=value2</code>。</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-23-3"><p>1.基本参数,定义徽标左右文字和图标</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bdage Theme,Butterfly %&#125;</span><br><span class="line">&#123;% bdage Frame,Hexo,hexo %&#125;</span><br></pre></td></tr></table></figure><p>2.信息参数，定义徽标右侧内容背景色，指向链接</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bdage CDN,JsDelivr,jsDelivr||abcdef,https://metroui.org.ua/index.html,本站使用JsDelivr为静态资源提供CDN加速 %&#125;</span><br><span class="line">//如果是跨顺序省略可选参数，仍然需要写个逗号,用作分割</span><br><span class="line">&#123;% bdage Source,GitHub,GitHub||,https://github.com/ %&#125;</span><br></pre></td></tr></table></figure><p>3.拓展参数，支持shields的API的全部参数内容</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bdage Hosted,Vercel,Vercel||brightgreen,https://vercel.com/,本站采用双线部署，默认线路托管于Vercel||style=social&amp;logoWidth=20 %&#125;</span><br><span class="line">//如果是跨顺序省略可选参数组，仍然需要写双竖线||用作分割</span><br><span class="line">&#123;% bdage Hosted,Vercel,Vercel||||style=social&amp;logoWidth=20&amp;logoColor=violet %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-23-4"><p>1.基本参数,定义徽标左右文字和图标</p><p><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Butterfly-Theme-orange?logo=&color=orange&link=&"></object><br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Hexo-Frame-orange?logo=hexo&color=orange&link=&"></object></p><p>2.信息参数，定义徽标右侧内容背景色，指向链接</p><p><object class="ghbdage" style="margin-inline:5px" title="本站使用JsDelivr为静态资源提供CDN加速" standby="loading..." data="https://img.shields.io/badge/JsDelivr-CDN-orange?logo=jsDelivr&color=abcdef&link=https://metroui.org.ua/index.html&"></object><br>//如果是跨顺序省略可选参数，仍然需要写个逗号,用作分割<br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/GitHub-Source-orange?logo=GitHub&color=orange&link=https://github.com/&"></object></p><p>3.拓展参数，支持shields的API的全部参数内容</p><p><object class="ghbdage" style="margin-inline:5px" title="本站采用双线部署，默认线路托管于Vercel" standby="loading..." data="https://img.shields.io/badge/Vercel-Hosted-orange?logo=Vercel&color=brightgreen&link=https://vercel.com/&style=social&logoWidth=20"></object><br>//如果是跨顺序省略可选参数组，仍然需要写双竖线||用作分割<br><object class="ghbdage" style="margin-inline:5px" title="" standby="loading..." data="https://img.shields.io/badge/Vercel-Hosted-orange?logo=Vercel&color=orange&link=&style=social&logoWidth=20&logoColor=violet"></object></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-14-网站卡片-sites">2.14 网站卡片 sites</h2><div class="tabs" id="guide-tabs-24"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-24-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-24-2">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-24-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-24-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% sitegroup %&#125;</span><br><span class="line">&#123;% site 标题, url=链接, screenshot=截图链接, avatar=头像链接（可选）, description=描述（可选） %&#125;</span><br><span class="line">&#123;% site 标题, url=链接, screenshot=截图链接, avatar=头像链接（可选）, description=描述（可选） %&#125;</span><br><span class="line">&#123;% endsitegroup %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-24-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">&#123;% sitegroup %&#125;</span><br><span class="line">&#123;% site xaoxuu, url=https://xaoxuu.com, screenshot=/assets/home/optimized/pc<span class="emphasis">_23-cover.webp, avatar=/assets/fallback/avatar.png, description=简约风格 %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% site inkss, url=https://inkss.cn, screenshot=/assets/home/optimized/pc_</span>24-cover.webp, avatar=/assets/fallback/avatar.png, description=这是一段关于这个网站的描述文字 %&#125;</span><br><span class="line">&#123;% site MHuiG, url=https://blog.mhuig.top, screenshot=/assets/home/optimized/pc<span class="emphasis">_25-cover.webp, avatar=/assets/fallback/avatar.png, description=这是一段关于这个网站的描述文字 %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% site Colsrch, url=https://colsrch.top, screenshot=/assets/home/optimized/pc_</span>26-cover.webp, avatar=/assets/fallback/avatar.png, description=这是一段关于这个网站的描述文字 %&#125;</span><br><span class="line">&#123;% site Linhk1606, url=https://linhk1606.github.io, screenshot=/assets/home/optimized/pc<span class="emphasis">_27-cover.webp, avatar=/assets/fallback/avatar.png, description=这是一段关于这个网站的描述文字 %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% endsitegroup %&#125;</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-24-3"><div class="site-card-group"><a class="site-card" href="https://fomalhaut1998.com"><div class="img"><img src="/assets/home/optimized/pc_23-cover.webp"/></div><div class="info"><img src="/assets/fallback/avatar.png"/><span class="title">fomalhaut1998</span><span class="desc">简约风格</span></div></a><a class="site-card" href="https://inkss.cn"><div class="img"><img src="/assets/home/optimized/pc_24-cover.webp"/></div><div class="info"><img src="/assets/fallback/avatar.png"/><span class="title">inkss</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://blog.mhuig.top"><div class="img"><img src="/assets/home/optimized/pc_25-cover.webp"/></div><div class="info"><img src="/assets/fallback/avatar.png"/><span class="title">MHuiG</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://colsrch.top"><div class="img"><img src="/assets/home/optimized/pc_26-cover.webp"/></div><div class="info"><img src="/assets/fallback/avatar.png"/><span class="title">Colsrch</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a><a class="site-card" href="https://linhk1606.github.io"><div class="img"><img src="/assets/home/optimized/pc_27-cover.webp"/></div><div class="info"><img src="/assets/fallback/avatar.png"/><span class="title">Linhk1606</span><span class="desc">这是一段关于这个网站的描述文字</span></div></a></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-15-行内图片-inlineimage">2.15 行内图片 inlineimage</h2><div class="tabs" id="guide-tabs-25"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-25-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-25-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-25-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-25-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-25-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% inlineimage 图片链接, height=高度（可选） %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-25-2"><ol><li><code>高度</code>：height=20px</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-25-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">这是 &#123;% inlineimage /assets/home/optimized/pc<span class="emphasis">_28-cover.webp %&#125; 一段话。</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">这又是 &#123;% inlineimage /assets/home/optimized/pc_</span>29-cover.webp, height=40px %&#125; 一段话。</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-25-4"><p>这是 <img no-lazy class="inline" src="/assets/home/optimized/pc_28-cover.webp" style="height:1.5em"/> 一段话。</p><p>这又是 <img no-lazy class="inline" src="/assets/home/optimized/pc_29-cover.webp" style="height:40px;"/> 一段话。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-16-单张图片-image">2.16 单张图片 image</h2><div class="tabs" id="guide-tabs-26"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-26-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-26-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-26-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-26-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-26-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image 链接, width=宽度（可选）, height=高度（可选）, alt=描述（可选）, bg=占位颜色（可选） %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-26-2"><ol><li>图片宽度高度：width=300px, height=32px</li><li>图片描述：alt=图片描述（butterfly需要在主题配置文件中开启图片描述）</li><li>占位背景色：bg=#f2f2f2</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-26-3"><p>1.添加描述：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image /assets/home/optimized/pc<span class="emphasis">_30-cover.webp, alt=本站静态背景图片示例 %&#125;</span></span><br></pre></td></tr></table></figure><p>2.指定宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image /assets/home/optimized/pc<span class="emphasis">_30-cover.webp, width=400px %&#125;</span></span><br></pre></td></tr></table></figure><p>3.指定宽度并添加描述：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image /assets/home/optimized/pc<span class="emphasis">_30-cover.webp, width=400px, alt=本站静态背景图片示例 %&#125;</span></span><br></pre></td></tr></table></figure><p>4.设置占位背景色：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% image /assets/home/optimized/pc<span class="emphasis">_30-cover.webp, width=400px, bg=#1D0C04, alt=优化不同宽度浏览的观感 %&#125;</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-26-4"><p>1.添加描述：</p><div class="img-wrap"><div class="img-bg"><img class="img" src="/assets/home/optimized/pc_30-cover.webp" alt="本站静态背景图片示例"/></div><span class="image-caption">本站静态背景图片示例</span></div>2..指定宽度<div class="img-wrap"><div class="img-bg"><img class="img" src="/assets/home/optimized/pc_30-cover.webp" style="width:400px;"/></div></div>3.指定宽度并添加描述：<div class="img-wrap"><div class="img-bg"><img class="img" src="/assets/home/optimized/pc_30-cover.webp" alt="本站静态背景图片示例" style="width:400px;"/></div><span class="image-caption">本站静态背景图片示例</span></div>4.设置占位背景色：<div class="img-wrap"><div class="img-bg" style="background:#1D0C04"><img class="img" src="/assets/home/optimized/pc_30-cover.webp" alt="优化不同宽度浏览的观感" style="width:400px;"/></div><span class="image-caption">优化不同宽度浏览的观感</span></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-17-音频-audio">2.17 音频 audio</h2><div class="tabs" id="guide-tabs-27"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-27-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-27-2">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-27-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-27-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% audio 音频链接 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-27-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% audio https://github.com/volantis-x/volantis-docs/releases/download/assets/Lumia1020.mp3 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-27-3"><div class="audio"><audio controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/Lumia1020.mp3' type='audio/mp3'>Your browser does not support the audio tag.</audio></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-18-视频-video">2.18 视频 video</h2><div class="tabs" id="guide-tabs-28"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-28-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-28-2">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-28-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-28-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-28-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% video 视频链接 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-28-2"><ol><li><code>对齐方向</code>：left, center, right</li><li><code>列数</code>：逗号后面直接写列数，支持 1 ～ 4 列。</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-28-3"><p>1.100%宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %&#125;</span></span><br></pre></td></tr></table></figure><p>2.50%宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;% videos, 2 %&#125;</span><br><span class="line">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %&#125;</span><br><span class="line">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %&#125;</span><br><span class="line">&#123;% endvideos %&#125;</span><br></pre></td></tr></table></figure><p>3.25%宽度</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;% videos, 4 %&#125;</span><br><span class="line">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %&#125;</span><br><span class="line">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %&#125;</span><br><span class="line">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %&#125;</span><br><span class="line">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG<span class="emphasis">_0341.mov %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% video https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_</span>0341.mov %&#125;</span><br><span class="line">&#123;% endvideos %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-28-4"><p>1.100%宽度</p><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div>2.50%宽度<div class="videos" col='2'><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div></div>3.25%宽度<div class="videos" col='4'><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div><div class="video"><video controls preload><source src='https://github.com/volantis-x/volantis-docs/releases/download/assets/IMG_0341.mov' type='video/mp4'>Your browser does not support the video tag.</video></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-19-相册-gallery">2.19 相册 gallery</h2><div class="tabs" id="guide-tabs-29"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-29-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-29-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-29-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-29-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-29-1"><p>1.gallerygroup 相册图库</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;gallery-group-main&quot;</span>&gt;</span></span></span><br><span class="line">&#123;% galleryGroup name description link img-url %&#125;</span><br><span class="line">&#123;% galleryGroup name description link img-url %&#125;</span><br><span class="line">&#123;% galleryGroup name description link img-url %&#125;</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br></pre></td></tr></table></figure><p>2.gallery 相册</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% gallery %&#125;</span><br><span class="line">markdown 圖片格式</span><br><span class="line">&#123;% endgallery %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-29-2"><ul><li>gallerygroup 相册图库</li></ul><table><thead><tr><th>参数名</th><th>释义</th></tr></thead><tbody><tr><td>name</td><td>图库名字</td></tr><tr><td>description</td><td>图库描述</td></tr><tr><td>link</td><td>链接到对应相册的地址</td></tr><tr><td>img-url</td><td>图库封面</td></tr></tbody></table><ul><li><p>gallery 相册</p><p>区别于旧版的Gallery相册,新的Gallery相册会自动根据图片长度进行排版，书写也更加方便，与markdown格式一样。可根据需要插入到相应的md。无需再自己配置长宽。<strong>建议在粘贴时故意使用长短、大小、横竖不一的图片</strong>，会有更好的效果。（尺寸完全相同的图片只会平铺输出，效果很糟糕）</p></li></ul><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-29-3"><p>1.gallerygroup 相册图库</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;gallery-group-main&quot;</span>&gt;</span></span></span><br><span class="line">&#123;% galleryGroup MC 在Rikkaの六花服务器里留下的足迹 &#x27;/gallery/MC/&#x27; /assets/home/optimized/pc<span class="emphasis">_22-cover.webp %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% galleryGroup Gundam 哦咧哇gundam哒！ &#x27;/gallery/Gundam/&#x27; /assets/home/optimized/pc_</span>23-cover.webp %&#125;</span><br><span class="line">&#123;% galleryGroup I-am-Akilar 某种意义上也算自拍吧 &#x27;/gallery/I-am-Akilar/&#x27; /assets/home/optimized/pc<span class="emphasis">_24-cover.webp %&#125;</span></span><br><span class="line"><span class="emphasis"><span class="language-xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br></pre></td></tr></table></figure><p>2.gallery 相册</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% gallery %&#125;</span><br><span class="line">![](<span class="link">/assets/home/optimized/pc_25-cover.webp</span>)</span><br><span class="line">![](<span class="link">/assets/home/optimized/pc_26-cover.webp</span>)</span><br><span class="line">&#123;% endgallery %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-29-4"><p>1.gallerygroup 相册图库</p><div class="gallery-group-main">  <figure class="gallery-group">  <img class="gallery-group-img no-lightbox" src='/assets/home/optimized/pc_22-cover.webp' alt="Group Image Gallery">  <figcaption>  <div class="gallery-group-name">MC</div>  <p>在Rikkaの六花服务器里留下的足迹</p>  <a href='/gallery/MC/' aria-label="MC"></a>  </figcaption>  </figure>  <figure class="gallery-group">  <img class="gallery-group-img no-lightbox" src='/assets/home/optimized/pc_23-cover.webp' alt="Group Image Gallery">  <figcaption>  <div class="gallery-group-name">Gundam</div>  <p>哦咧哇gundam哒！</p>  <a href='/gallery/Gundam/' aria-label="Gundam"></a>  </figcaption>  </figure>  <figure class="gallery-group">  <img class="gallery-group-img no-lightbox" src='/assets/home/optimized/pc_24-cover.webp' alt="Group Image Gallery">  <figcaption>  <div class="gallery-group-name">I-am-Akilar</div>  <p>某种意义上也算自拍吧</p>  <a href='/gallery/I-am-Akilar/' aria-label="I-am-Akilar"></a>  </figcaption>  </figure></div>2.gallery 相册<div class="fj-gallery"><p><img src="/assets/home/optimized/pc_25-cover.webp" alt=""><br><img src="/assets/home/optimized/pc_26-cover.webp" alt=""></p>          </div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-20-折叠框-folding">2.20 折叠框 folding</h2><div class="tabs" id="guide-tabs-30"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-30-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-30-2">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-30-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-30-1"><p>1.gallerygroup 相册图库</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% folding 参数（可选）, 标题 %&#125;</span><br><span class="line">![](<span class="link">/assets/home/optimized/pc_27-cover.webp</span>)</span><br><span class="line">&#123;% endfolding %&#125;</span><br></pre></td></tr></table></figure><!-- tab 参数配置 --><ol><li><p><code>颜色</code>：blue, cyan, green, yellow, red</p></li><li><p><code>状态</code>：状态填写 open 代表默认打开。</p></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-30-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">&#123;% folding 查看图片测试 %&#125;</span><br><span class="line"></span><br><span class="line">![](<span class="link">/assets/home/optimized/pc_27-cover.webp</span>)</span><br><span class="line"></span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding cyan open, 查看默认打开的折叠框 %&#125;</span><br><span class="line"></span><br><span class="line">这是一个默认打开的折叠框。</span><br><span class="line"></span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding green, 查看代码测试 %&#125;</span><br><span class="line">假装这里有代码块（代码块没法嵌套代码块）</span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding yellow, 查看列表测试 %&#125;</span><br><span class="line"></span><br><span class="line"><span class="bullet">-</span> haha</span><br><span class="line"><span class="bullet">-</span> hehe</span><br><span class="line"></span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding red, 查看嵌套测试 %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding blue, 查看嵌套测试2 %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% folding 查看嵌套测试3 %&#125;</span><br><span class="line"></span><br><span class="line">hahaha <span class="language-xml"><span class="tag">&lt;<span class="name">span</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&#x27;/assets/home/optimized/pc_28-cover.webp&#x27;</span> <span class="attr">style</span>=<span class="string">&#x27;height:24px&#x27;</span>&gt;</span></span><span class="language-xml"><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% endfolding %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% endfolding %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-30-3"><details class="folding-tag" ><summary> 查看图片测试 </summary>              <div class='content'>              <p><img src="/assets/home/optimized/pc_27-cover.webp" alt=""></p>              </div>            </details><details class="folding-tag" cyan open><summary> 查看默认打开的折叠框 </summary>              <div class='content'>              <p>这是一个默认打开的折叠框。</p>              </div>            </details><details class="folding-tag" green><summary> 查看代码测试 </summary>              <div class='content'>              <p>假装这里有代码块（代码块没法嵌套代码块）</p>              </div>            </details><details class="folding-tag" yellow><summary> 查看列表测试 </summary>              <div class='content'>              <ul><li>haha</li><li>hehe</li></ul>              </div>            </details><details class="folding-tag" red><summary> 查看嵌套测试 </summary>              <div class='content'>              <details class="folding-tag" blue><summary> 查看嵌套测试2 </summary>              <div class='content'>              <details class="folding-tag" ><summary> 查看嵌套测试3 </summary>              <div class='content'>              <p>hahaha <span><img src='/assets/home/optimized/pc_28-cover.webp' style='height:24px'></span></p>              </div>            </details>              </div>            </details>              </div>            </details><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-21-分栏-tab">2.21 分栏 tab</h2><div class="tabs" id="guide-tabs-31"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-31-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-31-2">配置参数</button></li><li class="tab"><button type="button" data-href="#guide-tabs-31-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-31-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-31-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs Unique name, [index] %&#125;</span><br><span class="line">&lt;!-- tab [Tab caption] [@icon] --&gt;</span><br><span class="line">Any content (support inline tags too).</span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-31-2"><ol><li><p>Unique name :</p><ul><li><p>选项卡块标签的唯一名称，不带逗号。</p></li><li><p>将在#id中用作每个标签及其索引号的前缀。</p></li><li><p>如果名称中包含空格，则对于生成#id，所有空格将由破折号代替。</p></li><li><p>仅当前帖子/页面的URL必须是唯一的！</p></li></ul></li><li><p>[index]:</p><ul><li><p>活动选项卡的索引号。</p></li><li><p>如果未指定，将选择第一个标签（1）。</p></li><li><p>如果index为-1，则不会选择任何选项卡。</p></li><li><p>可选参数。</p></li></ul></li><li><p>[Tab caption]:</p><ul><li><p>当前选项卡的标题。</p></li><li><p>如果未指定标题，则带有制表符索引后缀的唯一名称将用作制表符的标题。</p></li><li><p>如果未指定标题，但指定了图标，则标题将为空。</p></li><li><p>可选参数。</p></li></ul></li><li><p>[@icon]:</p><ul><li><p>FontAwesome图标名称（全名，看起来像“ fas fa-font”）</p></li><li><p>可以指定带空格或不带空格；</p></li><li><p>例如’Tab caption @icon’ 和 ‘Tab caption@icon’.</p></li><li><p>可选参数。</p></li></ul></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-31-3"><p>1.示例 1 - 预设选择第一个【默认】</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs test1 %&#125;</span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><p>2.示例 2 - 预设选择tabs</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs test2, 3 %&#125;</span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><p>3.示例 3 - 没有预设值</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs test3, -1 %&#125;</span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 1.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 2.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab --&gt;</span><br><span class="line"><span class="strong">**This is Tab 3.**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><p>4.示例 4 - 自定义Tab名 + 只有icon + icon和Tab名</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;% tabs test4 %&#125;</span><br><span class="line">&lt;!-- tab 第一个Tab --&gt;</span><br><span class="line"><span class="strong">**tab名字为第一个Tab**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab @fab fa-apple-pay --&gt;</span><br><span class="line"><span class="strong">**只有图标 没有Tab名字**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- tab 炸弹@fas fa-bomb --&gt;</span><br><span class="line"><span class="strong">**名字+icon**</span></span><br><span class="line">&lt;!-- endtab --&gt;</span><br><span class="line">&#123;% endtabs %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-31-4"><p>1.示例 1 - 预设选择第一个【默认】</p><div class="tabs" id="test1"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#test1-1">test1 1</button></li><li class="tab"><button type="button" data-href="#test1-2">test1 2</button></li><li class="tab"><button type="button" data-href="#test1-3">test1 3</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="test1-1"><p><strong>This is Tab 1.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test1-2"><p><strong>This is Tab 2.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test1-3"><p><strong>This is Tab 3.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><p>2.示例 2 - 预设选择tabs</p><div class="tabs" id="test2"><ul class="nav-tabs"><li class="tab"><button type="button" data-href="#test2-1">test2 1</button></li><li class="tab"><button type="button" data-href="#test2-2">test2 2</button></li><li class="tab active"><button type="button" data-href="#test2-3">test2 3</button></li></ul><div class="tab-contents"><div class="tab-item-content" id="test2-1"><p><strong>This is Tab 1.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test2-2"><p><strong>This is Tab 2.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content active" id="test2-3"><p><strong>This is Tab 3.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><p>3.示例 3 - 没有预设值</p><div class="tabs" id="test3"><ul class="nav-tabs"><li class="tab"><button type="button" data-href="#test3-1">test3 1</button></li><li class="tab"><button type="button" data-href="#test3-2">test3 2</button></li><li class="tab"><button type="button" data-href="#test3-3">test3 3</button></li></ul><div class="tab-contents"><div class="tab-item-content" id="test3-1"><p><strong>This is Tab 1.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test3-2"><p><strong>This is Tab 2.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test3-3"><p><strong>This is Tab 3.</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><p>4.示例 4 - 自定义Tab名 + 只有icon + icon和Tab名</p><div class="tabs" id="test4"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#test4-1">第一个Tab</button></li><li class="tab"><button type="button" data-href="#test4-2"><i class="fab fa-apple-pay" style="text-align: center;"></i></button></li><li class="tab"><button type="button" data-href="#test4-3"><i class="fas fa-bomb"></i>炸弹</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="test4-1"><p><strong>tab名字为第一个Tab</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test4-2"><p><strong>只有图标 没有Tab名字</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="test4-3"><p><strong>名字+icon</strong></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-22-诗词标签-poem">2.22 诗词标签 poem</h2><div class="tabs" id="guide-tabs-32"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-32-1">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-32-2">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-32-3">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-32-1"><ol><li><code>title</code>：诗词标题</li><li><code>author</code>：作者，可以不写</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-32-2"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&#123;% poem 水调歌头,苏轼 %&#125;</span><br><span class="line">丙辰中秋，欢饮达旦，大醉，作此篇，兼怀子由。</span><br><span class="line">明月几时有？把酒问青天。</span><br><span class="line">不知天上宫阙，今夕是何年？</span><br><span class="line">我欲乘风归去，又恐琼楼玉宇，高处不胜寒。</span><br><span class="line">起舞弄清影，何似在人间？</span><br><span class="line"></span><br><span class="line">转朱阁，低绮户，照无眠。</span><br><span class="line">不应有恨，何事长向别时圆？</span><br><span class="line">人有悲欢离合，月有阴晴圆缺，此事古难全。</span><br><span class="line">但愿人长久，千里共婵娟。</span><br><span class="line">&#123;% endpoem %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-32-3"><div class='poem'><div class='poem-title'>水调歌头</div><div class='poem-author'>苏轼</div><p>丙辰中秋，欢饮达旦，大醉，作此篇，兼怀子由。<br>明月几时有？把酒问青天。<br>不知天上宫阙，今夕是何年？<br>我欲乘风归去，又恐琼楼玉宇，高处不胜寒。<br>起舞弄清影，何似在人间？</p><p>转朱阁，低绮户，照无眠。<br>不应有恨，何事长向别时圆？<br>人有悲欢离合，月有阴晴圆缺，此事古难全。<br>但愿人长久，千里共婵娟。</p></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-23-阿里图标-icon">2.23 阿里图标 icon</h2><div class="tabs" id="guide-tabs-33"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-33-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-33-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-33-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-33-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-33-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% icon [icon-xxxx],[font-size] %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-33-2"><ol><li><code>icon-xxxx</code>：表示图标<code>font-class</code>,可以在自己的阿里矢量图标库项目的<code>font-class</code>引用方案内查询并复制。</li><li><code>font-size</code>：表示图标大小，直接填写数字即可，单位为<code>em</code>。图标大小默认值为<code>1em</code>。</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-33-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&#123;% icon icon-rat<span class="emphasis">_zi %&#125;&#123;% icon icon-rat,2 %&#125;</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">&#123;% icon icon-ox_</span>chou,3 %&#125;&#123;% icon icon-ox,4 %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% icon icon-tiger<span class="emphasis">_yin,5 %&#125;&#123;% icon icon-tiger,6 %&#125;</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">&#123;% icon icon-rabbit_</span>mao,1 %&#125;&#123;% icon icon-rabbit,2 %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% icon icon-dragon<span class="emphasis">_chen,3 %&#125;&#123;% icon icon-dragon,4 %&#125;</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">&#123;% icon icon-snake_</span>si,5 %&#125;&#123;% icon icon-snake,6 %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% icon icon-horse<span class="emphasis">_wu %&#125;&#123;% icon icon-horse,2 %&#125;</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">&#123;% icon icon-goat_</span>wei,3 %&#125;&#123;% icon icon-goat,4 %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% icon icon-monkey<span class="emphasis">_shen,5 %&#125;&#123;% icon icon-monkey,6 %&#125;</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">&#123;% icon icon-rooster_</span>you %&#125;&#123;% icon icon-rooster,2 %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% icon icon-dog<span class="emphasis">_xu,3 %&#125;&#123;% icon icon-dog,4 %&#125;</span></span><br><span class="line"><span class="emphasis"></span></span><br><span class="line"><span class="emphasis">&#123;% icon icon-boar_</span>hai,5 %&#125;&#123;% icon icon-boar,6 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-33-4"><p><svg class="icon" style="width:1em; height:1em" aria-hidden="true"><use xlink:href="#icon-rat_zi"></use></svg><svg class="icon" style="width:2em; height:2em" aria-hidden="true"><use xlink:href="#icon-rat"></use></svg></p><p><svg class="icon" style="width:3em; height:3em" aria-hidden="true"><use xlink:href="#icon-ox_chou"></use></svg><svg class="icon" style="width:4em; height:4em" aria-hidden="true"><use xlink:href="#icon-ox"></use></svg></p><p><svg class="icon" style="width:5em; height:5em" aria-hidden="true"><use xlink:href="#icon-tiger_yin"></use></svg><svg class="icon" style="width:6em; height:6em" aria-hidden="true"><use xlink:href="#icon-tiger"></use></svg></p><p><svg class="icon" style="width:1em; height:1em" aria-hidden="true"><use xlink:href="#icon-rabbit_mao"></use></svg><svg class="icon" style="width:2em; height:2em" aria-hidden="true"><use xlink:href="#icon-rabbit"></use></svg></p><p><svg class="icon" style="width:3em; height:3em" aria-hidden="true"><use xlink:href="#icon-dragon_chen"></use></svg><svg class="icon" style="width:4em; height:4em" aria-hidden="true"><use xlink:href="#icon-dragon"></use></svg></p><p><svg class="icon" style="width:5em; height:5em" aria-hidden="true"><use xlink:href="#icon-snake_si"></use></svg><svg class="icon" style="width:6em; height:6em" aria-hidden="true"><use xlink:href="#icon-snake"></use></svg></p><p><svg class="icon" style="width:1em; height:1em" aria-hidden="true"><use xlink:href="#icon-horse_wu"></use></svg><svg class="icon" style="width:2em; height:2em" aria-hidden="true"><use xlink:href="#icon-horse"></use></svg></p><p><svg class="icon" style="width:3em; height:3em" aria-hidden="true"><use xlink:href="#icon-goat_wei"></use></svg><svg class="icon" style="width:4em; height:4em" aria-hidden="true"><use xlink:href="#icon-goat"></use></svg></p><p><svg class="icon" style="width:5em; height:5em" aria-hidden="true"><use xlink:href="#icon-monkey_shen"></use></svg><svg class="icon" style="width:6em; height:6em" aria-hidden="true"><use xlink:href="#icon-monkey"></use></svg></p><p><svg class="icon" style="width:1em; height:1em" aria-hidden="true"><use xlink:href="#icon-rooster_you"></use></svg><svg class="icon" style="width:2em; height:2em" aria-hidden="true"><use xlink:href="#icon-rooster"></use></svg></p><p><svg class="icon" style="width:3em; height:3em" aria-hidden="true"><use xlink:href="#icon-dog_xu"></use></svg><svg class="icon" style="width:4em; height:4em" aria-hidden="true"><use xlink:href="#icon-dog"></use></svg></p><p><svg class="icon" style="width:5em; height:5em" aria-hidden="true"><use xlink:href="#icon-boar_hai"></use></svg><svg class="icon" style="width:6em; height:6em" aria-hidden="true"><use xlink:href="#icon-boar"></use></svg></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-24-特效标签wow">2.24 特效标签wow</h2><div class="tabs" id="guide-tabs-34"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-34-1">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-34-2">渲染演示</button></li><li class="tab"><button type="button" data-href="#guide-tabs-34-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-34-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-34-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% wow [animete],[duration],[delay],[offset],[iteration] %&#125;</span><br><span class="line">内容</span><br><span class="line">&#123;% endwow %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-34-2"><ol><li><code>animate</code>: 动画样式，效果详见<a href="https://animate.style/">animate.css参考文档</a></li><li><code>duration</code>: 选填项，动画持续时间，单位可以是<code>ms</code>也可以是<code>s</code>。例如<code>3s</code>，<code>700ms</code>。</li><li><code>delay</code>: 选填项，动画开始的延迟时间，单位可以是<code>ms</code>也可以是<code>s</code>。例如<code>3s</code>，<code>700ms</code>。</li><li><code>offset</code>: 选填项，开始动画的距离（相对浏览器底部）</li><li><code>iteration</code>: 选填项，动画重复的次数</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-34-3"><p>1.flip动画效果。</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;% wow animate<span class="strong">__zoomIn,5s,5s,100,10 %&#125;</span></span><br><span class="line"><span class="strong">&#123;% note blue &#x27;fas fa-bullhorn&#x27; modern%&#125;</span></span><br><span class="line"><span class="strong">`zoomIn`动画效果，持续`5s`，延时`5s`，离底部`100`距离时启动，重复`10`次</span></span><br><span class="line"><span class="strong">&#123;% endnote %&#125;</span></span><br><span class="line"><span class="strong">&#123;% endwow %&#125;</span></span><br></pre></td></tr></table></figure><p>2.zoomIn动画效果，持续5s，延时5s，离底部100距离时启动，重复10次</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;% wow animate<span class="strong">__zoomIn,5s,5s,100,10 %&#125;</span></span><br><span class="line"><span class="strong">&#123;% note blue &#x27;fas fa-bullhorn&#x27; modern%&#125;</span></span><br><span class="line"><span class="strong">`zoomIn`动画效果，持续`5s`，延时`5s`，离底部`100`距离时启动，重复`10`次</span></span><br><span class="line"><span class="strong">&#123;% endnote %&#125;</span></span><br><span class="line"><span class="strong">&#123;% endwow %&#125;</span></span><br></pre></td></tr></table></figure><p>3.slideInRight动画效果，持续5s，延时5s</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;% wow animate<span class="strong">__slideInRight,5s,5s %&#125;</span></span><br><span class="line"><span class="strong">&#123;% note orange &#x27;fas fa-car&#x27; modern%&#125;</span></span><br><span class="line"><span class="strong">`slideInRight`动画效果，持续`5s`，延时`5s`。</span></span><br><span class="line"><span class="strong">&#123;% endnote %&#125;</span></span><br><span class="line"><span class="strong">&#123;% endwow %&#125;</span></span><br></pre></td></tr></table></figure><p>4.heartBeat动画效果，延时5s，重复10次。此处注意不用的参数位置要留空，用逗号间隔。</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;% wow animate<span class="strong">__heartBeat,,5s,,10 %&#125;</span></span><br><span class="line"><span class="strong">&#123;% note red &#x27;fas fa-battery-half&#x27; modern%&#125;</span></span><br><span class="line"><span class="strong">`heartBeat`动画效果，延时`5s`，重复`10`次。</span></span><br><span class="line"><span class="strong">&#123;% endnote %&#125;</span></span><br><span class="line"><span class="strong">&#123;% endwow %&#125;</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-34-4"><p>1.flip动画效果。</p><div class='wow animate__zoomIn' data-wow-duration='5s' data-wow-delay='5s' data-wow-offset='100'  data-wow-iteration='10' ><div class="note blue icon-padding modern"><i class="note-icon fas fa-bullhorn"></i><p><code>zoomIn</code>动画效果，持续<code>5s</code>，延时<code>5s</code>，离底部<code>100</code>距离时启动，重复<code>10</code>次</p></div></div><p>2.zoomIn动画效果，持续5s，延时5s，离底部100距离时启动，重复10次</p><div class='wow animate__zoomIn' data-wow-duration='5s' data-wow-delay='5s' data-wow-offset='100'  data-wow-iteration='10' ><div class="note blue icon-padding modern"><i class="note-icon fas fa-bullhorn"></i><p><code>zoomIn</code>动画效果，持续<code>5s</code>，延时<code>5s</code>，离底部<code>100</code>距离时启动，重复<code>10</code>次</p></div></div><p>3.slideInRight动画效果，持续5s，延时5s</p><div class='wow animate__slideInRight' data-wow-duration='5s' data-wow-delay='5s' data-wow-offset=''  data-wow-iteration='' ><div class="note orange icon-padding modern"><i class="note-icon fas fa-car"></i><p><code>slideInRight</code>动画效果，持续<code>5s</code>，延时<code>5s</code>。</p></div></div><p>4.heartBeat动画效果，延时5s，重复10次。此处注意不用的参数位置要留空，用逗号间隔。</p><div class='wow animate__heartBeat' data-wow-duration='' data-wow-delay='5s' data-wow-offset=''  data-wow-iteration='10' ><div class="note red icon-padding modern"><i class="note-icon fas fa-battery-half"></i><p><code>heartBeat</code>动画效果，延时<code>5s</code>，重复<code>10</code>次。</p></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-25-进度条-progress">2.25  进度条 progress</h2><div class="note info flat"><p>进度条标签参考<a href="https://rongbuqiu.com/jdt.html">沂佰孜猫-给HEXO文章添加彩色进度条</a>。<br>源样式提取自<a href="https://zwying0814.gitbook.io/cuteen/">Cuteen</a>主题。</p></div><div class="tabs" id="guide-tabs-35"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-35-1">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-35-2">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-35-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-35-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-35-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% progress [width] [color] [text] %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-35-2"><ol><li><code>width</code>: 0到100的阿拉伯数字</li><li><code>color</code>: 颜色，取值有red,yellow,green,cyan,blue,gray</li><li><code>text</code>:进度条上的文字内容</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-35-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&#123;% progress 10 red 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 30 yellow 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 50 green 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 70 cyan 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 90 blue 进度条样式预览 %&#125;</span><br><span class="line">&#123;% progress 100 gray 进度条样式预览 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-35-4"><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-red"  style="width: 10%" aria-valuenow="10" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-yellow"  style="width: 30%" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-green"  style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-cyan"  style="width: 70%" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-blue"  style="width: 90%" aria-valuenow="90" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><div class="progress"><div class="progress-bar-animated progress-bar progress-bar-striped bg-gray"  style="width: 100%" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"><p>进度条样式预览</p></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-26-注释-notation">2.26 注释 notation</h2><div class="tabs" id="guide-tabs-36"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-36-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-36-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-36-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-36-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-36-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% nota [label] , [text] %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-36-2"><ol><li><p><code>label</code>: 注释词汇</p></li><li><p><code>text</code>: 悬停显示的注解内容</p></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-36-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% nota 把鼠标移动到我上面试试 ,可以看到注解内容出现在顶栏 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-36-4"><p><span class='nota' data-nota='可以看到注解内容出现在顶栏'>把鼠标移动到我上面试试</span></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-27-气泡注释-bubble">2.27 气泡注释 bubble</h2><div class="tabs" id="guide-tabs-37"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-37-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-37-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-37-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-37-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-37-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% bubble [content] , [notation] ,[background-color] %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-37-2"><ol><li><code>content</code>: 注释词汇</li><li><code>notation</code>: 悬停显示的注解内容</li><li><code>background-color</code>: 可选，气泡背景色。默认为“#71a4e3”</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-37-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">最近我学到了不少新玩意儿（虽然对很多大佬来说这些已经是旧技术了），比如CSS的&#123;% bubble 兄弟相邻选择器,&quot;例如 h1 + p &#123;margin-top:50px;&#125;&quot; %&#125;，&#123;% bubble flex布局,&quot;Flex 是 Flexible Box 的缩写，意为&quot;弹性布局&quot;，用来为盒状模型提供最大的灵活性&quot;,&quot;#ec5830&quot; %&#125;，&#123;% bubble transform变换,&quot;transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜。&quot;,&quot;#1db675&quot; %&#125;，animation的&#123;% bubble 贝塞尔速度曲线,&quot;贝塞尔曲线(Bézier curve)，又称贝兹曲线或贝济埃曲线，是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线，贝兹曲线由线段与节点组成，节点是可拖动的支点，线段像可伸缩的皮筋&quot;,&quot;#de4489&quot; %&#125;写法，还有今天刚看到的&#123;% bubble clip-path,&quot;clip-path属性使用裁剪方式创建元素的可显示区域。区域内的部分显示，区域外的隐藏。&quot;,&quot;#868fd7&quot; %&#125;属性。这些对我来说很新颖的概念狠狠的冲击着我以前积累起来的设计思路。</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-37-4"><p>最近我学到了不少新玩意儿（虽然对很多大佬来说这些已经是旧技术了），比如CSS的<span class="bubble-content">兄弟相邻选择器</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#71a4e3;">例如 h1 + p {margin-top:50px;}</span></span>，<span class="bubble-content">flex布局</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#ec5830;">Flex 是 Flexible Box 的缩写，意为弹性布局&quot;，用来为盒状模型提供最大的灵活性&quot;</span></span>，<span class="bubble-content">transform变换</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#1db675;">transform 属性向元素应用 2D 或 3D 转换。该属性允许我们对元素进行旋转、缩放、移动或倾斜。</span></span>，animation的<span class="bubble-content">贝塞尔速度曲线</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#de4489;">贝塞尔曲线(Bézier curve)，又称贝兹曲线或贝济埃曲线，是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线，贝兹曲线由线段与节点组成，节点是可拖动的支点，线段像可伸缩的皮筋</span></span>写法，还有今天刚看到的<span class="bubble-content">clip-path</span><span class="bubble-notation"><span class="bubble-item" style="background-color:#868fd7;">clip-path属性使用裁剪方式创建元素的可显示区域。区域内的部分显示，区域外的隐藏。</span></span>属性。这些对我来说很新颖的概念狠狠的冲击着我以前积累起来的设计思路。</p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-28-引用文献-reference">2.28 引用文献 reference</h2><div class="tabs" id="guide-tabs-38"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-38-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-38-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-38-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-38-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-38-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% referto [id] , [literature] %&#125;</span><br><span class="line">&#123;% referfrom [id] , [literature] , [url] %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-38-2"><ol><li><p>referto 引用上标</p><ul><li><p><code>id</code>: 上标序号内容，需与referfrom标签的id对应才能实现跳转</p></li><li><p><code>literature</code>: 引用的参考文献名称</p></li></ul></li><li><p>referfrom 引用出处</p><ul><li><p><code>id</code>: 序号内容，需与referto标签的id对应才能实现 跳转</p></li><li><p><code>literature</code>: 引用的参考文献名称</p></li><li><p><code>url</code>: 引用的参考文献链接，可省略</p></li></ul></li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-38-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Akilarの糖果屋(akilar.top)是一个私人性质的博客&#123;% referto &#x27;[1]&#x27;,&#x27;Akilarの糖果屋群聊简介&#x27; %&#125;，从各类教程至生活点滴，无话不谈。建群的目的是提供一个闲聊的场所。博客采用Hexo框架&#123;% referto &#x27;[2]&#x27;,&#x27;Hexo中文文档&#x27; %&#125;，Butterfly主题&#123;% referto &#x27;[3]&#x27;,&#x27;Butterfly 安装文档(一) 快速开始&#x27; %&#125;</span><br><span class="line"></span><br><span class="line">本项目参考了Volantis&#123;% referto &#x27;[4]&#x27;,&#x27;hexo-theme-volantis 标签插件&#x27; %&#125;的标签样式。引入<span class="code">`[tag].js`</span>，并针对<span class="code">`butterfly`</span>主题修改了相应的<span class="code">`[tag].styl`</span>。在此鸣谢<span class="code">`Volantis`</span>主题众开发者。</span><br><span class="line">主要参考内容包括各个volantis的内置标签插件文档&#123;% referto &#x27;[5]&#x27;,&#x27;Volantis文档:内置标签插件&#x27; %&#125;</span><br><span class="line">Butterfly主题的各个衍生魔改&#123;% referto &#x27;[6]&#x27;,&#x27;Butterfly 安装文档:标签外挂（Tag Plugins&#x27; %&#125;&#123;% referto &#x27;[7]&#x27;,&#x27;小弋の生活馆全样式预览&#x27; %&#125;&#123;% referto &#x27;[8]&#x27;,&#x27;l-lin-font-awesome-animation&#x27; %&#125;&#123;% referto &#x27;[9]&#x27;,&#x27;小康的butterfly主题使用文档&#x27; %&#125;</span><br><span class="line"></span><br><span class="line">&#123;% referfrom &#x27;[1]&#x27;,&#x27;Akilarの糖果屋群聊简介&#x27;,&#x27;https://jq.qq.com/?<span class="emphasis">_wv=1027&amp;k=pGLB2C0N&#x27; %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% referfrom &#x27;[2]&#x27;,&#x27;Hexo中文文档&#x27;,&#x27;https://hexo.io/zh-cn/docs/&#x27; %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% referfrom &#x27;[3]&#x27;,&#x27;Butterfly 安装文档(一) 快速开始&#x27;,&#x27;https://butterfly.js.org/posts/21cfbf15/&#x27; %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% referfrom &#x27;[4]&#x27;,&#x27;hexo-theme-volantis 标签插件&#x27;,&#x27;https://volantis.js.org/v5/tag-plugins/&#x27; %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% referfrom &#x27;[5]&#x27;,&#x27;Volantis文档:内置标签插件&#x27;,&#x27;https://volantis.js.org/tag-plugins/&#x27; %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% referfrom &#x27;[6]&#x27;,&#x27;Butterfly 安装文档:标签外挂（Tag Plugins&#x27;,&#x27;https://butterfly.js.org/posts/4aa8abbe/#%E6%A8%99%E7%B1%A4%E5%A4%96%E6%8E%9B%EF%BC%88Tag-Plugins%EF%BC%89&#x27; %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% referfrom &#x27;[7]&#x27;,&#x27;小弋の生活馆全样式预览&#x27;,&#x27;https://lovelijunyi.gitee.io/posts/c898.html&#x27; %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% referfrom &#x27;[8]&#x27;,&#x27;l-lin-font-awesome-animation&#x27;,&#x27;https://github.com/l-lin/font-awesome-animation&#x27; %&#125;</span></span><br><span class="line"><span class="emphasis">&#123;% referfrom &#x27;[9]&#x27;,&#x27;小康的butterfly主题使用文档&#x27;,&#x27;https://www.antmoe.com/posts/3b43914f/&#x27; %&#125;</span></span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-38-4"><p>Akilarの糖果屋(akilar.top)是一个私人性质的博客<span class="hidden-anchor" id="referto_[1]"></span><sup class="reference"><a href="#referfrom_[1]">[1]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Akilarの糖果屋群聊简介</span><span class="reference-title">参考资料</span></span></span>，从各类教程至生活点滴，无话不谈。建群的目的是提供一个闲聊的场所。博客采用Hexo框架<span class="hidden-anchor" id="referto_[2]"></span><sup class="reference"><a href="#referfrom_[2]">[2]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Hexo中文文档</span><span class="reference-title">参考资料</span></span></span>，Butterfly主题<span class="hidden-anchor" id="referto_[3]"></span><sup class="reference"><a href="#referfrom_[3]">[3]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Butterfly 安装文档(一) 快速开始</span><span class="reference-title">参考资料</span></span></span></p><p>本项目参考了Volantis<span class="hidden-anchor" id="referto_[4]"></span><sup class="reference"><a href="#referfrom_[4]">[4]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">hexo-theme-volantis 标签插件</span><span class="reference-title">参考资料</span></span></span>的标签样式。引入<code>[tag].js</code>，并针对<code>butterfly</code>主题修改了相应的<code>[tag].styl</code>。在此鸣谢<code>Volantis</code>主题众开发者。<br>主要参考内容包括各个volantis的内置标签插件文档<span class="hidden-anchor" id="referto_[5]"></span><sup class="reference"><a href="#referfrom_[5]">[5]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Volantis文档:内置标签插件</span><span class="reference-title">参考资料</span></span></span><br>Butterfly主题的各个衍生魔改<span class="hidden-anchor" id="referto_[6]"></span><sup class="reference"><a href="#referfrom_[6]">[6]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">Butterfly 安装文档:标签外挂（Tag Plugins</span><span class="reference-title">参考资料</span></span></span><span class="hidden-anchor" id="referto_[7]"></span><sup class="reference"><a href="#referfrom_[7]">[7]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">小弋の生活馆全样式预览</span><span class="reference-title">参考资料</span></span></span><span class="hidden-anchor" id="referto_[8]"></span><sup class="reference"><a href="#referfrom_[8]">[8]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">l-lin-font-awesome-animation</span><span class="reference-title">参考资料</span></span></span><span class="hidden-anchor" id="referto_[9]"></span><sup class="reference"><a href="#referfrom_[9]">[9]</a></sup><span class="reference-bubble"><span class="reference-item"><span class="reference-literature">小康的butterfly主题使用文档</span><span class="reference-title">参考资料</span></span></span></p><div class="reference-source"><span class="hidden-anchor" id="referfrom_[1]"></span><a class="reference-anchor" href="#referto_[1]">[1]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://jq.qq.com/?_wv=1027&k=pGLB2C0N">Akilarの糖果屋群聊简介</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[2]"></span><a class="reference-anchor" href="#referto_[2]">[2]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://hexo.io/zh-cn/docs/">Hexo中文文档</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[3]"></span><a class="reference-anchor" href="#referto_[3]">[3]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://butterfly.js.org/posts/21cfbf15/">Butterfly 安装文档(一) 快速开始</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[4]"></span><a class="reference-anchor" href="#referto_[4]">[4]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://volantis.js.org/v5/tag-plugins/">hexo-theme-volantis 标签插件</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[5]"></span><a class="reference-anchor" href="#referto_[5]">[5]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://volantis.js.org/tag-plugins/">Volantis文档:内置标签插件</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[6]"></span><a class="reference-anchor" href="#referto_[6]">[6]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://butterfly.js.org/posts/4aa8abbe/#%E6%A8%99%E7%B1%A4%E5%A4%96%E6%8E%9B%EF%BC%88Tag-Plugins%EF%BC%89">Butterfly 安装文档:标签外挂（Tag Plugins</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[7]"></span><a class="reference-anchor" href="#referto_[7]">[7]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://lovelijunyi.gitee.io/posts/c898.html">小弋の生活馆全样式预览</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[8]"></span><a class="reference-anchor" href="#referto_[8]">[8]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://github.com/l-lin/font-awesome-animation">l-lin-font-awesome-animation</a></div><div class="reference-source"><span class="hidden-anchor" id="referfrom_[9]"></span><a class="reference-anchor" href="#referto_[9]">[9]<div class="reference-anchor-up fa-solid fa-angles-up"></div></a><a class="reference-link" href="https://www.antmoe.com/posts/3b43914f/">小康的butterfly主题使用文档</a></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-29-PDF展示">2.29 PDF展示</h2><div class="tabs" id="guide-tabs-39"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-39-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-39-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-39-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-39-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-39-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% pdf 文件路径 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-39-2"><ol><li><code>文件路径</code>: 可以是相对路径或者是在线链接</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-39-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 1.本地文件:在md文件路径下创建一个同名文件夹，其内放pdf文件名为xxx.pdf的文件</span></span><br><span class="line">&#123;% pdf xxx.pdf %&#125;</span><br><span class="line"><span class="section"># 2.在线链接</span></span><br><span class="line">&#123;% pdf https://cdn.jsdelivr.net/gh/Justlovesmile/CDN/pdf/小作文讲义.pdf %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-39-4"><p>2.在线链接(要放到最外层才能起作用)</p><pre><code>&lt;div class=&quot;row&quot;&gt;&lt;embed src=&quot;https://cdn.jsdelivr.net/gh/Justlovesmile/CDN/pdf/小作文讲义.pdf&quot; width=&quot;100%&quot; height=&quot;550&quot; type=&quot;application/pdf&quot;&gt;&lt;/div&gt;</code></pre><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-30-Hexo-tag-map-插件">2.30 Hexo-tag-map 插件</h2><div class="tabs" id="guide-tabs-40"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-40-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-40-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-40-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-40-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-40-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;% + 标签值 + 经度 + 纬度 + 文本 + 缩放等级 + 宽 + 高 + 默认图层 + %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-40-2"><table><thead><tr><th style="text-align:center">地图名</th><th style="text-align:center">标签值 &lt;必填&gt;</th><th style="text-align:center">宽 (默认 100%) / 高 (默认 360px)</th><th style="text-align:center">缩放等级 (默认 14)</th><th style="text-align:center">宽 (默认 100%) / 高 (默认 360px)</th><th style="text-align:center">默认图层 (默认 1)</th></tr></thead><tbody><tr><td style="text-align:center">混合地图</td><td style="text-align:center">map</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 3~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~7</td></tr><tr><td style="text-align:center">谷歌地图</td><td style="text-align:center">googleMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~20</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~3</td></tr><tr><td style="text-align:center">高德地图</td><td style="text-align:center">gaodeMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 3~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~3</td></tr><tr><td style="text-align:center">百度地图</td><td style="text-align:center">baiduMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 4~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~2</td></tr><tr><td style="text-align:center">Geoq 地图</td><td style="text-align:center">geoqMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~5</td></tr><tr><td style="text-align:center">openstreet 地图</td><td style="text-align:center">openstreetMap</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">取值 1~18</td><td style="text-align:center">百分数或具体值 (100% 或 360px)</td><td style="text-align:center">不支持此参数</td></tr></tbody></table><ol><li>参数之间，用英文逗号相隔</li><li>参数必须按上述事例顺序输入，不得为空</li><li>同一个页面，同一组经纬度值，只能插入一个相同标签值的地图 (若有需要，可以将第二个地图上，经度或纬度末尾删除一两个数)</li><li>参数取值必须在上述范围内</li><li>默认图层：即地图叠加层的值，默认常规地图还是卫星地图，可按地图显示顺序取值</li><li>缩放等级，数字越大，地图比例尺越小，显示的越精细</li><li>除标签值外，其他参数选填，但 每个参数的左边的参数必填</li><li>谷歌地图需要外网才能加载查看</li></ol><p>坐标获取：<a href="https://lbs.amap.com/tools/picker">高德地图坐标拾取系统</a> 、<a href="https://api.map.baidu.com/lbsapi/getpoint/index.html">百度地图坐标拾取系统</a></p><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-40-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% map 120.101101,30.239119 %&#125;</span><br><span class="line">&#123;% googleMap 120.101101,30.239119, 这里是西湖灵隐寺，据说求姻缘很灵验哦！ %&#125;</span><br><span class="line">&#123;% geoqMap 120.101101,30.239119, 这里是西湖灵隐寺，据说求姻缘很灵验哦！, 13, 90%, 320px, 3 %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-40-4"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet@1.7.1.css"><script data-pjax src="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet@1.7.1.js"></script><script data-pjax src="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet.ChineseTmsProviders@1.0.4.js"></script><div class="map-box"><div id="map-120.101101-30.239119" style="max-width:100%; height:360px;display: block;margin:0 auto;z-index:1;border-radius: 5px;"></div></div><script type="text/javascript">var normalm=L.tileLayer.chinaProvider('GaoDe.Normal.Map',{maxZoom:20,minZoom:1,attribution:'Amap'});var imgm=L.tileLayer.chinaProvider('GaoDe.Satellite.Map',{maxZoom:20,minZoom:1,attribution:'Amap'});var imga=L.tileLayer.chinaProvider('GaoDe.Satellite.Annotion',{maxZoom:20,minZoom:1,attribution:'Amap'});var normalMap=L.tileLayer.chinaProvider('Google.Normal.Map',{maxZoom:20,minZoom:1,attribution:'Google Maps'}),satelliteMap=L.tileLayer.chinaProvider('Google.Satellite.Map',{maxZoom:21,minZoom:1,attribution:'Google Maps'});routeMap=L.tileLayer.chinaProvider('Google.Satellite.Annotion',{maxZoom:21,minZoom:1});var normalMap=L.tileLayer.chinaProvider('Google.Normal.Map',{maxZoom:21,minZoom:1,attribution:'Google Maps'}),satelliteMap=L.tileLayer.chinaProvider('Google.Satellite.Map',{maxZoom:21,minZoom:1,attribution:'Google Maps'}),routeMap=L.tileLayer.chinaProvider('Google.Satellite.Annotion',{maxZoom:21,minZoom:1,attribution:'Google Maps'});var normalm1=L.tileLayer.chinaProvider('Geoq.Normal.Map',{maxZoom:21,minZoom:1,attribution:'GeoQ'});var normal=L.layerGroup([normalm]),image=L.layerGroup([imgm,imga]);var baseLayers={"高德地图":normal,"智图地图":normalm1,"谷歌地图":normalMap,"高德卫星地图":imgm,"谷歌卫星地图":satelliteMap,"高德卫星标注":image,"谷歌卫星标注":routeMap};var mymap=L.map('map-120.101101-30.239119',{center:[30.239119,120.101101],zoom:14,layers:[normal],zoomControl:false});L.control.layers(baseLayers,null).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);</script><br><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet@1.7.1.css"><script data-pjax src="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet@1.7.1.js"></script><script data-pjax src="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet.ChineseTmsProviders@1.0.4.js"></script><div id="googleMap-120.101101-30.239119" style="max-width:100%; height:360px;display: block;margin:0 auto;z-index:1;border-radius: 5px;"></div><script type="text/javascript">var normalMap=L.tileLayer.chinaProvider('Google.Normal.Map',{maxZoom:22,minZoom:1,attribution:'Google Maps'}),satelliteMap=L.tileLayer.chinaProvider('Google.Satellite.Map',{maxZoom:22,minZoom:1,attribution:'Google Maps'}),routeMap=L.tileLayer.chinaProvider('Google.Satellite.Annotion',{maxZoom:22,minZoom:1,attribution:'Google Maps'});var baseLayers={"谷歌地图":normalMap,"谷歌卫星图":satelliteMap,"谷歌卫星标注": routeMap};var overlayLayers={};var mymap=L.map("googleMap-120.101101-30.239119",{center:[30.239119,120.101101],zoom:14,layers:[normalMap],zoomControl:false});L.control.layers(baseLayers,null).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);var marker = L.marker(['30.239119','120.101101']).addTo(mymap);marker.bindPopup("这里是西湖灵隐寺，据说求姻缘很灵验哦！").openPopup();</script><br><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet@1.7.1.css"><script data-pjax src="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet@1.7.1.js"></script><script data-pjax src="https://cdn.jsdelivr.net/npm/hexo-tag-map/lib/leaflet.ChineseTmsProviders@1.0.4.js"></script><div id="geoqMap-120.101101-30.239119" style="max-width:90%; height:320px;display: block;margin:0 auto;z-index:1;border-radius: 5px;"></div><script type="text/javascript">var normalm1=L.tileLayer.chinaProvider('Geoq.Normal.Map',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normalm2=L.tileLayer.chinaProvider('Geoq.Normal.PurplishBlue',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normalm3=L.tileLayer.chinaProvider('Geoq.Normal.Gray',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normalm4=L.tileLayer.chinaProvider('Geoq.Normal.Warm',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normalm5=L.tileLayer.chinaProvider('Geoq.Theme.Hydro',{maxZoom:20,minZoom:1,attribution:'GeoQ'});var normal=L.layerGroup([normalm1,normalm2,normalm3,normalm4,normalm5]);var baseLayers={"智图地图":normalm1,"午夜蓝":normalm2,"灰色":normalm3,"暖色":normalm4,"水系":normalm5};var mymap=L.map("geoqMap-120.101101-30.239119",{center:[30.239119,120.101101],zoom:13,layers:[normalm3],zoomControl:false});L.control.layers(baseLayers,null).addTo(mymap);L.control.zoom({zoomInTitle:'放大',zoomOutTitle:'缩小'}).addTo(mymap);var marker = L.marker(['30.239119','120.101101']).addTo(mymap);marker.bindPopup("这里是西湖灵隐寺，据说求姻缘很灵验哦！").openPopup();</script><br><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><h2 id="2-31-隐藏块">2.31 隐藏块</h2><div class="tabs" id="guide-tabs-41"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#guide-tabs-41-1">标签语法</button></li><li class="tab"><button type="button" data-href="#guide-tabs-41-2">参数配置</button></li><li class="tab"><button type="button" data-href="#guide-tabs-41-3">示例源码</button></li><li class="tab"><button type="button" data-href="#guide-tabs-41-4">渲染演示</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="guide-tabs-41-1"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;% hideBlock display,bg,color %&#125;</span><br><span class="line">content</span><br><span class="line">&#123;% endhideBlock %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-41-2"><ol><li>content：要隐藏的内容</li><li>display：展示前按钮显示的文字（可选）</li><li>bg：按钮的背景颜色（可选）</li><li>color：按钮显示的文字的颜色（可选）</li></ol><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-41-3"><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&#123;% hideBlock 点我预览, blue %&#125;</span><br><span class="line">这里有张图片：</span><br><span class="line"><span class="language-xml"><span class="tag">&lt;<span class="name">img</span> <span class="attr">src</span>=<span class="string">&quot;/assets/home/optimized/pc_30-cover.webp&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;本站背景图片示例&quot;</span> <span class="attr">style</span>=<span class="string">&quot;zoom:67%;&quot;</span> /&gt;</span></span></span><br><span class="line">&#123;% endhideBlock %&#125;</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="guide-tabs-41-4"><div class="hide-block"><button type="button" class="hide-button" style="background-color:  blue;">点我预览    </button><div class="hide-content"><p>这里有张图片：<br><img src="/assets/home/optimized/pc_30-cover.webp" alt="本站背景图片示例" style="zoom:67%;" /></p></div></div><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div>]]></content>
    
    
    <summary type="html">🥧本文汇总Markdown格式以及外挂标签在网页端的渲染效果，可作为文档进行查询</summary>
    
    
    
    <category term="教程" scheme="https://daixiaokang.com/categories/%E6%95%99%E7%A8%8B/"/>
    
    
    <category term="Markdown" scheme="https://daixiaokang.com/tags/Markdown/"/>
    
    <category term="外挂标签" scheme="https://daixiaokang.com/tags/%E5%A4%96%E6%8C%82%E6%A0%87%E7%AD%BE/"/>
    
  </entry>
  
</feed>
